# -*- coding: utf-8 -*-
"""This package defines all sort of classes to handle data for inpystem.
"""

import abc
import pathlib
import configparser
import logging
import copy

import numpy as np
import matplotlib.pyplot as plt
import hyperspy.api as hs

from . import restore
from .tools import misc

_logger = logging.getLogger(__name__)

def search_nearest(pix, mask):
    """Searches the non-zeros pixels of mask which are near to the pix
    pixel.

    The algorithm beggins by searching for non-zero elements around the
    pixel whose index is pix. If there are non-zero elements, their
    positions are returned. Otherwise, the searching horizon rises by
    one. Then, the algorithm goes on.

    The algorithm stops automatically at an horizon of 100 pixels. In
    such case, an error is sent to the logger and None is returned.

    Arguments
    ---------
    pix: int
        The position index of the pixel whose neighbors should be found.
    mask: (m, n) numpy array
        The sampling mask (1 for sampled pixel and 0 otherwise).

    Returns
    -------
    None, 2-tuple
        None is returned in case no neighbor was found. Otherwise, a
        tuple (y, x) is returned where x (resp. y) are the columns
        (resp. rows) index of the pixel neighbors
.    """

    m, n = mask.shape
    y, x = np.unravel_index(pix, (m, n))
    mask[y, x] = 0

    Lmax = 100
    flag = True
    L = 1

    pmask = np.pad(mask, pad_width=Lmax, mode='constant')
    py, px = y + Lmax, x + Lmax

    while flag:

        submask = pmask[py-L:py+L+1, px-L:px+L+1]
        if submask.sum() > 0:
            flag = False
        else:
            if L < Lmax:
                L += 1
            else:
                return None

    nnz = submask.nonzero()

    return (list(nnz[0] + (y-L)), list(nnz[1] + (x-L)))

class Scan:
    """Scan pattern class.

    This class stores the data spatial shape and two copies of the
    scan pattern. One of these copies is the initial scan pattern
    which is given to the class. At the same time, a :code:`ratio`
    argument can be given to keep only a portion of the available
    samples. See Notes for more details.

    Attributes
    ----------
    shape : 2-length tuple
        The spatial shape (m, n) where m is the number of rows and n is the
        number of columns.
    path : numpy array
        The sampling path to be used in the study.
    path_0 : numpy array
        The initial sampling path to be kept in case the ratio is changed.
    ratio: float
        The current :code:`ratio` value such that :code:`path`has size
        :code:`ratio*m*n`. Changing this attribute automaticaly updates
        :code:`path`.

    Note
    -----
    Consider only :code:`r*m*n` pixels hve been sampled, then the
    :code:`path_0` attribute has shape (r*m*n, ) and its elements
    lay between 0 and m*n-1.

    Meanwhile, if the user wants to consider only :code:`ratio` percent of
    the samples, the :code:`ratio` argument should be given. The
    :code:`path` attribute would then have shape (ratio*m*n, ). In such
    case, :code:`path_0[:ratio*m*n]` will be equal to
    :code:`path`. Be aware that :code:`ratio` should be lower than
    :code:`r`.

    Each element of these arrays is the pixel index in row major order.
    To recover the row and column index array, type the following commands.

    ::code:
        i = path // n
        j = path % n
    """

    def __init__(self, shape, path, ratio=None):
        """Scan pattern constructor.

        Arguments
        ---------
        shape: (m, n) tuple
            The spatial shape where m is the number of rows and n is
            the number of columns.
        path : tuple, numpy array
            The sampling path. See class Notes for more detail.
        ratio: optional, float
            The ratio of sampled pixels. This should lay between 0 (excl.)
            and 1. Default is None for full sampling.
        """
        if len(tuple(shape)) != 2:
            raise ValueError('Invalid shape parameter length.')

        path = np.asarray(path)
        if path.ndim != 1:
            raise ValueError('Input path array should have 1 dimension.')
        if path.size == 0 or path.size > shape[0] * shape[1]:
            raise ValueError('Input path array has invalid size.')

        path = path.astype(int)

        # Let us check that no value is given twice
        path_copy = path.copy()
        path_copy.sort()

        if np.any(path_copy[1:] - path_copy[:-1] == 0):
            raise ValueError(
                'Some elements of input path appear at least '
                'twice.')

        self.shape = shape
        self.path = path
        self.path_0 = path

        self._ratio = ratio

        # The following line initializes self.path
        self.ratio = ratio

    @property
    def ratio(self):
        """ Ratio getter.

        Returns
        -------
        float
            The ratio property value.
        """
        return self._ratio

    @ratio.setter
    def ratio(self, value):
        """ Ratio setter.

        It checks that the value is correct and updates the scan
        object attributes.

        Arguments
        ---------
        value: float
            The new ratio value.
        """

        if value is not None and (value > 1 or value <= 0):
            raise ValueError('The ratio should be in the ]0,1] segment.')

        # get sample size
        m, n = self.shape

        if value is not None:
            N = int(m * n * value)  # Number of required samples.
        else:
            N = self.path_0.size
            self._ratio = N / (m*n)

        if N > self.path_0.size:
            N = self.path_0.size
            _logger.warning(
                'Input ratio is higher than higher maximal ratio'
                ' ({:.3f}). Ratio is set to the maximal value.'.format(
                    self.path_0.size/(m*n)))

        # change scan pattern length
        self.path = self.path_0[:N]

        # Set new value
        self._ratio = N / (m*n)

    @classmethod
    def from_file(cls, data_file, ratio=None):
        """ Creates a scan pattern object from a data file
        (such as .dm3, .dm4 or npz).

        In the case of a .npz file, this one should contain the :code:̀'m`,
        :code:̀'n` and :code:̀'path` variables which are resp. the number of
        rows and columns and the path array.

        Concerning the .dm3/.dm4 files, the data storage is specific to
        the LPS Lab (Orsay, France) implementation.

        An aditional argument :code:̀'ratio` allows you to select only a
        given ratio of the sampled pixels. This should lay between 0 (excl.)
        and 1.

        Arguments
        ---------
        data_file: str
            The data file path.
        ratio: optional, float
            The ratio of sampled pixels. This should lay between 0 (excl.)
            and 1. Default is None for full sampling.

        Returns
        -------
        Scan object
            The scan pattern.
        """
        _logger.info('Loading Scan file.')

        # Get file extension
        p = pathlib.Path(data_file)
        file_ext = p.suffix

        # Digital Micrograph file
        if (file_ext == '.dm3' or file_ext == '.dm4'):
            _logger.info('Scan file type is {}.'.format(file_ext))

            data = hs.load(str(p)).data

            if data.ndim == 3:
                _logger.info('{} scan file type is A.'.format(file_ext))
                _, m, n = data.shape
                x = data[0, :, :].flatten()
                y = data[1, :, :].flatten()

            elif data.ndim == 2:
                _logger.info('{} scan file type is B.'.format(file_ext))
                m, n = data.shape
                x = data.flatten() % n
                y = data.flatten() // n

            else:
                raise ValueError(
                    'Scan data has {} dimensions. Expected dimension'
                    ' is 2 or 3.'.format(data.ndim)
                    )
            path = y * n + x

        # Numpy file
        elif (file_ext == '.npz'):
            _logger.info('Scan file type is .npz.')

            data = np.load(str(data_file))
            m, n = int(data['m']), int(data['n'])
            path = data['path']

        return cls((m, n), path, ratio=ratio)

    @classmethod
    def random(cls, shape, ratio=None, seed=None):
        """ Creates a random scan pattern object.

        Arguments
        ---------
        shape: (m, n) tuple
            The data spatial shape.
        ratio: optional, float
            The ratio of sampled pixels. It should lay between 0 (excluded)
            and 1. Default is None for full sampling.
        seed: optional, int
            Seed for random sampling.
            Default is None for random seed.

        Returns
        -------
        Scan object
            The scan pattern.
        """
        _logger.info('Random scan generated.')

        if seed is not None:
            np.random.seed(seed)

        # The following code should do the job.
        #
        # P = shape[0]*shape[1]  # Number of pixels.
        # perm = np.random.permutation(P)
        #
        # However, to match previous version output for seed 0, the
        # following non-optimal code is chosen.
        pix_ratio = 1 if ratio is None else ratio
        mask = np.random.rand(*shape) < pix_ratio

        perm = np.flatnonzero(mask)
        np.random.shuffle(perm)

        return cls(shape, perm)

    def get_mask(self):
        """Returns the sampling mask.

        The sampling mask is boolean and True is for sampled pixels.

        Returns
        -------
        mask : (m, n) numpy array
            The sampling mask.
        """
        mask = np.zeros(self.shape, dtype=bool)

        sampled_pos = np.unravel_index(self.path, self.shape)
        mask[sampled_pos] = True

        return mask

    def plot(self):
        """ Plots the sampling mask.

        White (resp. black) pixels are sampled (resp. non-sampled).
        """

        # Show data
        fig, ax = plt.subplots()
        ax.matshow(self.get_mask())
        # set title
        ax.set_title('Sampling mask')
        # layout
        ax.axis('image')
        ax.axis('off')

    def __repr__(self):
        return "<Scan, shape: {}, ratio: {:.3f}>".format(
            self.shape, self.ratio)

class AbstractStem(abc.ABC):
    """Abstract STEM acquisition class.

    This is an *abstract* class, which mean you can not instantiate such
    object.

    It defines the structure for a STEM acquisition object.

    Attributes
    ----------
    hsdata : hs BaseSignal
        The acquired STEM data hyperspy object.
    scan : Scan object
        The sampling scan object associated with the data.
    verbose: bool
        If True, information is sent to standard output.
        Default is True.
    """
    def __init__(self, hsdata, scan=None, verbose=True):
        """
        AbstractStem constructor.

        Arguments
        ---------
        hsdata : hs BaseSignal
            The acquired STEM data hyperspy object.
        scan : optional, Scan object
            The sampling scan object associated with the data.
            Default is None for full sampling.
        verbose: bool
            If True, information is sent to standard output.
            Default is True.
        """
        if verbose:
            print('Creating STEM acquisition...')

        if issubclass(type(hsdata), hs.signals.BaseSignal):
            self.hsdata = hsdata.copy()
        else:
            raise ValueError('Invalid input data.')

        if scan is None:
            scan = Scan.random(hsdata.data.shape[:2])

        if scan.shape != hsdata.data.shape[:2]:
            raise ValueError('hsdata and scan have incoherent spatial shape.')

        self.scan = copy.deepcopy(scan)
        self.verbose = verbose

    def correct(
            self, rows=slice(None), cols=slice(None), bands=slice(None),
            dpixels=None):
        """Correct deffective data.

        Deffective data correspond to:

        1. Rows to remove at the begging or at the end of the image.
        2. Columns to remove at the begging or at the end of the image.
        3. Bands to remove at the begging or at the end of the image.
        4. Located dead pixels at the center of the image.

        In the cases 1, 2 or 3, the rows and columns are purely removed.
        The dead pixels are filled with the mean over a neighbourhood.

        A :code`slice` object for an object :code:`A` of length :code:`L`
        defines a continuous portion of :code:`A` such as
        :code:`A[n_1], A[n_1+1], ..., A[n_2-1]`
        with :code:`n_1` < :code:`n_2`. In such case, a slice object
        definition is :code:`slice(n_1, n_2)`. If :code:`n_1` is 0, then
        use :code:`slice(None, n_2)`. If :code:`n_2` is :code:`L`
        use :code:`slice(n_1, None)`. Last, if all the elements of
        :code:`A` should be kept, use :code:`slice(None)`.

        Arguments
        ---------
        rows: slice object
            The range of rows to keep.
        cols: slice object
            The range of columns to keep.
        cols: slice object
            The range of bands to keep.
        dpixels: list
            The positions of the dead pixels.
        """

        if self.verbose:
            print('Correcting STEM acquisition...')

        _logger.info('Correcting STEM data.')

        # Get Numpy data
        data = self.hsdata.data
        m, n = data.shape[:2]

        if dpixels is not None:

            # Preparing the sampling mask before searching for neighbor
            # pixels.
            #

            # Valid path array with non-dead sampled pixels.
            path = self.scan.path_0[
                np.isin(self.scan.path_0, dpixels, invert=True)
                ]
            # Position of these non-dead sampled pixels.
            valid_pos = np.unravel_index(path, (m, n))

            mask0 = np.zeros((m, n))
            mask0[valid_pos] = 1

            # Remove rows/columns that will be removed afterwards.
            mask = np.zeros((m, n))
            mask[rows, cols] = mask0[rows, cols]

            for dpix in dpixels:

                if np.sum(np.isin(self.scan.path_0, dpixels)) == 0:
                    # The dead pixel were not sampled.
                    _logger.warning(
                        'The dead pixel at position {} was not sampled and '
                        'was ignored for correction.'.format(dpix))
                    continue

                # Search for the neighbors.
                pixels = search_nearest(dpix, mask)

                if pixels is None:
                    _logger.error(
                        'No sampled pixel were found near enough '
                        'to the dead pixel at position {}. Correction '
                        'for this pixel was aborted.'.format(dpix))
                else:
                    y, x = np.unravel_index(dpix, mask.shape)

                    if data.ndim == 2:
                        data[y, x] = np.mean(data[pixels[0], pixels[1]])
                    else:
                        data[y, x, :] = np.mean(
                            data[pixels[0], pixels[1], :], axis=0)

        # Remove missing columns and rows.
        #

        if cols.step is not None or rows.step is not None:
            raise ValueError(
                'Limit slices should have a None as a step.')
        if data.ndim == 3 and bands.step is not None:
            raise ValueError(
                'Limit slices should have a None as a step.')

        if data.ndim == 2:
            data = data[rows, cols]
        else:
            data = data[rows, cols, bands]

        m, n = data.shape[:2]

        # Handle axes_manager
        #

        # Getting initial axes_manager
        tmp_axes_manager = self.hsdata.axes_manager

        # Modifying limits
        tmp_axes_manager[0].size = n
        tmp_axes_manager[1].size = m
        if data.ndim == 3:
            tmp_axes_manager[2].size = data.shape[2]

        # Modify eV axis scale and offset.
        if data.ndim == 3:
            if bands.start is not None:
                offset = tmp_axes_manager[2].offset
                scale = tmp_axes_manager[2].scale
                tmp_axes_manager[2].offset = offset + bands.start * scale

        # Defining new hs data object.
        im_tmp = hs.signals.Signal2D(data) if data.ndim == 2 else\
            hs.signals.Signal1D(data)
        # Adding modified axes_manager.
        im_tmp.axes_manager = tmp_axes_manager

        # Handle metadata
        #
        im_tmp.metadata = self.hsdata.metadata

        # Setting it as new data in self.
        self.hsdata = im_tmp

        # Handle scan pattern
        #

        p0 = self.scan.path_0       # Initial scan path.
        ratio = self.scan.ratio     # scan ratio.
        m, n = self.scan.shape      # Initial data shape.
        m1, n1 = data.shape[:2]     # New data shape.

        # Getting limits in old axis
        xmin = cols.start if cols.start is not None else 0
        xmax = xmin + n1
        ymin = rows.start if rows.start is not None else 0
        ymax = ymin + m1

        # Getting the old axis y and x position of sampled pixels.
        y0, x0 = np.unravel_index(p0, (m, n))
        # Getting p mask of sampled pixels that belong to the new axis.
        ind = np.flatnonzero(
            np.logical_and(
                np.logical_and(y0 >= ymin, y0 < ymax),
                np.logical_and(x0 >= xmin, x0 < xmax)
            ))

        # The new sampling path.
        p_new = (y0[ind] - ymin) * n1 + (x0[ind] - xmin)

        # The new scan object.
        self.scan = Scan((m1, n1), p_new, ratio)

    def correct_fromfile(self, file, force_ndim=None):
        """
        force_ndim aims at forcing dimension. Default is None for data
        dimension.
        """

        # The path of the config file is defined.
        p = pathlib.Path(file)

        if p.suffix != '.conf':
            raise ValueError('Input file extension should be .conf.')

        # The config file is read.
        config = configparser.ConfigParser(
            converters={'list': lambda text: eval(text)})
        config.read(p)

        # The section inside which to look at.
        ndim = self.hsdata.data.ndim if force_ndim is None else force_ndim
        section = '{}D DATA'.format(ndim)

        keys = ['rows', 'columns', 'bands']
        slices = []
        for cnt in range(3):
            if cnt < len(self.hsdata.data.shape):
                value = config[section].get(keys[cnt], fallback=None)
                slices.append(
                    misc.toslice(value, length=self.hsdata.data.shape[cnt]))

        dpixels = config[section].getlist('dpixels', fallback=None)

        self.correct(*slices, dpixels=dpixels)

    @abc.abstractmethod
    def restore(self):
        """Restores corrupted data.
        """
        pass

    def plot(self):
        """Plots the masked data.
        """
        hs_tmp = self.hsdata.copy()

        if hs_tmp.data.ndim == 2:
            hs_tmp.data = hs_tmp.data * self.scan.get_mask()
        else:
            B = self.hsdata.data.shape[-1]
            hs_tmp.data = hs_tmp.data * \
                np.tile(
                    self.scan.get_mask()[:, :, np.newaxis],
                    [1, 1, B])
        hs_tmp.plot()

    def __repr__(self):

        L = self.hsdata.__repr__()[1:-1].split(',')
        L[0] = 'Stem{}D'.format(self.hsdata.data.ndim)
        L.append(' sampling ratio: {:.2f}'.format(self.scan.ratio))
        L2 = ','.join(L)
        return '<{}>'.format(L2)

class Stem2D(AbstractStem):
    """2D image STEM acquisition.

    This defines a 2D STEM image with its associated sampling scan.

    Attributes
    ----------
    hsdata : hs BaseSignal
        The acquired STEM data hyperspy object.
    scan : Path object
        The sampling scan object associated with the data.
    """
    def restore(self, method='interpolation', parameters={}):
        """Restores the acquisition.

        It performs denoising in the case of full scan and performs
        recontruction in case of partial sampling.

        Arguments
        ---------
        """
        if self.verbose:
            print('Restoring the 2D STEM acquisition...')

        data = self.hsdata.data

        if self.scan is not None:
            mask = self.scan.get_mask()
        else:
            mask = np.ones(data.shape, dtype=bool)

        _logger.info('Restoration with method {} was intended.'.format(
            method))

        method_dico = {
            'INTERPOLATION': restore.interpolation.interpolate,
            'L1': restore.LS_2D.L1_LS,
            'ITKRMM': restore.DL_ITKrMM.ITKrMM,
            'WKSVD': restore.DL_ITKrMM.wKSVD,
            'ITKRMM_MATLAB': restore.DL_ITKrMM_matlab.ITKrMM_matlab,
            'WKSVD_MATLAB': restore.DL_ITKrMM_matlab.wKSVD_matlab,
            'BPFA_MATLAB': restore.DL_BPFA.BPFA_matlab
        }

        method_u = method.upper()
        if method_u in method_dico:

            xhat, InfoOut = method_dico[method_u](
                Y=data, mask=mask, verbose=self.verbose, **parameters)

        else:
            raise ValueError('Unknown method {}.'.format(method))

        xhat_hs = hs.signals.Signal2D(xhat)
        xhat_hs.axes_manager = self.hsdata.axes_manager
        xhat_hs.metadata = self.hsdata.metadata

        return xhat_hs, InfoOut

class Stem3D(AbstractStem):
    """3D image STEM acquisition.

    This defines a 3D STEM image with its associated sampling scan.

    Attributes
    ----------
    hsdata : hs BaseSignal
        The acquired STEM data hyperspy object.
    scan : Path object
        The sampling scan object associated with the data.
    """
    def restore(self, method='interpolation', parameters={},
                PCA_transform=True, PCA_th='auto'):
        """Restores the acquisition.

        It performs denoising in the case of full scan and performs
        recontruction in case of partial sampling.

        Arguments
        ---------

        PCA_transform: optional, bool
            Enables the PCA transformation if True, otherwise, no PCA
            transformation is processed.
            Default is True.
        PCA_th: optional, int, str
            The desired data dimension after dimension reduction.
            Possible values are 'auto' for automatic choice, 'max' for maximum
            value and an int value for user value.
            Default is 'auto'.
        """
        if self.verbose:
            print('Restoring the 3D STEM acquisition...')

        data = self.hsdata.data

        if self.scan is not None:
            mask = self.scan.get_mask()
        else:
            mask = np.ones(data.shape[:2], dtype=bool)

        _logger.info('Restoration with method {} was intended.'.format(
            method))

        method_dico = {
            'INTERPOLATION': restore.interpolation.interpolate,
            '3S': restore.LS_3D.SSS,
            'SNN': restore.LS_3D.SNN,
            'CLS': restore.LS_CLS.CLS,
            'CLS_POST_LS': restore.LS_CLS.Post_LS_CLS,
            'ITKRMM': restore.DL_ITKrMM.ITKrMM,
            'WKSVD': restore.DL_ITKrMM.wKSVD,
            'ITKRMM_MATLAB': restore.DL_ITKrMM_matlab.ITKrMM_matlab,
            'WKSVD_MATLAB': restore.DL_ITKrMM_matlab.wKSVD_matlab,
            'BPFA_MATLAB': restore.DL_BPFA.BPFA_matlab
        }

        method_u = method.upper()
        if method_u in method_dico:

            xhat, InfoOut = method_dico[method_u](
                Y=data, mask=mask, verbose=self.verbose,
                PCA_transform=PCA_transform, PCA_th=PCA_th,
                **parameters)

        else:
            raise ValueError('Unknown method {}.'.format(method))

        Xhat_hs = hs.signals.Signal1D(xhat)
        Xhat_hs.axes_manager = self.hsdata.axes_manager
        Xhat_hs.metadata = self.hsdata.metadata

        return Xhat_hs, InfoOut

    def plot_sum(self):
        """ Shows the sum of the data along the last axis.
        """

        # Show data
        fig, ax = plt.subplots()
        ax.matshow(self.hsdata.data.sum(2) * self.scan.get_mask())

        # set title
        ax.set_title("{}: sum over last axis".format(
            self.hsdata.metadata.General.title))

        # layout
        ax.axis('off')

    def plot_as2D(self):
        """Implements the HypersSpy tool to visualize the image for a
        given band.
        """
        mask3 = np.tile(
            self.scan.get_mask()[:, :, np.newaxis],
            [1, 1, self.hsdata.data.shape[2]])
        hs_data = hs.signals.Signal2D(
                np.moveaxis(self.hsdata.data * mask3, [0, 1, 2], [1, 2, 0]))

        axis_0 = [0, 1, 2]
        axis_1 = [2, 0, 1]
        for n in range(3):
            hs_data.axes_manager[axis_0[n]].name = \
                self.hsdata.axes_manager[axis_1[n]].name
            hs_data.axes_manager[axis_0[n]].offset = \
                self.hsdata.axes_manager[axis_1[n]].offset
            hs_data.axes_manager[axis_0[n]].scale = \
                self.hsdata.axes_manager[axis_1[n]].scale
            hs_data.axes_manager[axis_0[n]].units = \
                self.hsdata.axes_manager[axis_1[n]].units

        hs_data.metadata = self.hsdata.metadata

        hs_data.plot()

    def plot_as1D(self):
        """Implements the HypersSpy tool to visualize the spectrum for
        a given pixel.
        """
        mask3 = np.tile(
            self.scan.get_mask()[:, :, np.newaxis],
            [1, 1, self.hsdata.data.shape[2]])
        hs_data = hs.signals.Signal1D(self.hsdata.data * mask3)

        hs_data.axes_manager = self.hsdata.axes_manager
        hs_data.metadata = self.hsdata.metadata

        hs_data.plot()

    def plot_roi(self):
        """Implements the Hyperspy tool to analyse regions of interest.
        """
        # Create Hyperspy data
        hs_data = hs.signals.Signal1D(self.hsdata.data)

        hs_data.axes_manager = self.hsdata.axes_manager
        hs_data.metadata = self.hsdata.metadata

        # Create ROI
        roi = hs.roi.RectangularROI(left=0, top=0, right=5, bottom=5)

        # Plot Signal
        hs_data.plot()

        # Creates an interactively sliced Signal
        roi = roi.interactive(hs_data)

        # Computes the mean over the ROI
        mean_roi = hs.interactive(
            roi.mean, event=roi.axes_manager.events.any_axis_changed)

        # Plot ROI
        mean_roi.plot()


###################################################################################
#	Marvell GPL License
#
#	If you received this File from Marvell, you may opt to use, redistribute and/or
#	modify this File in accordance with the terms and conditions of the General
#	Public License Version 2, June 1991 (the "GPL License"), a copy of which is
#	available along with the File in the license.txt file or by writing to the Free
#	Software Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 or
#	on the worldwide web at http://www.gnu.org/licenses/gpl.txt.
#
#	THE FILE IS DISTRIBUTED AS-IS, WITHOUT WARRANTY OF ANY KIND, AND THE IMPLIED
#	WARRANTIES OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE ARE EXPRESSLY
#	DISCLAIMED.  The GPL License provides additional details about this warranty
#	disclaimer.
###################################################################################

# change this path to specify alternative path for setup
default_setups_list_path = r"C:\ProgramData\SetupLists.xlsx" # this file should be best saved on a shared drive

# setup list db settings - change this only if you change the above path excel structure
setup_name_sheet = "SetupNames"
setup_name_path_column = "Path"
setup_name_section_name = "SetupNames.Path Settings"
setup_list_section_name = "SetupsList.Common Settings"
setup_list_path_column = "Setup Path 1"


name=[1,2,3,4]
sign=['a','b','c']
dict1=dict(zip(name,sign))
print(dict1)

tuple1=(1,2,3)
sign1=[1,2,3]
dict2={tuple1:sign1}
print(dict2)

dict3={1:100,2:200}
for item in dict3.items():
    print(item)

set1=['星期一','星期二','星期三']
print(set1)


from .constant import void_tag

__all__ = ['Dom']

class Dom:
    def __init__(self, tag_name: (str, None)) -> 'Dom':
        self._tag_name = tag_name
        # html5 sub children, str or Dom
        self.children = list()
        # html5 tag attributes
        # {str : str}
        self.attributes = dict()

    def name(self) -> str:
        return self._tag_name

    def __len__(self) -> int:
        return len(self.children)

    def __repr__(self) -> str:
        return self.build_html()

    def __str__(self) -> str:
        return self.build_html()

    def get_text(self, recursion: bool=True) -> str:
        text = ''
        for children in self.children:
            if isinstance(children, str) and self._tag_name not in ('script', 'style'):
                text += children
            elif isinstance(children, Dom) and recursion is True:
                text += children.get_text(recursion)
        return text

    def build_html(self) -> str:
        if self._tag_name in void_tag:
            return self._build_void_tag_html()

        if self._tag_name == '!--':
            return '<!--' + self.children[0] + '-->'

        body = self._build_children_html()

        if self._tag_name is None:
            html = '{body}'
            return html.format(body=body)
        else:
            attr = self._build_attribute()
            if attr:
                html = '<{tag_name} {tag_attributes}>{body}</{tag_name}>'
                return html.format(tag_name=self._tag_name, tag_attributes=attr, body=body)
            else:
                html = '<{tag_name}>{body}</{tag_name}>'
                return html.format(tag_name=self._tag_name, body=body)

    def find_tag(self, tag_name: str, include_self: bool=True) -> (None, 'Dom'):
        if self._tag_name == tag_name and include_self:
            return self

        for children in self.children:
            if isinstance(children, Dom):
                result = children.find_tag(tag_name, include_self=True)
                if result is not None:
                    return result
                    #else isinstance(children str) need not to process
        return None

    def find_children_tag(self, tag_name: str) -> (None, 'Dom'):
        return self.find_tag(tag_name, include_self=False)

    def xpath(self, path: str) -> (None, 'Dom'):
        parts = path.split('->')
        dom = self
        for part in parts:
            dom = dom.find_children_tag(part)
            if dom is None:
                return None
        return dom

    def find_all_tags(self, tag_name: str) -> ['Dom']:
        result = []
        if self._tag_name == tag_name:
            result.append(self)

        for children in self.children:
            if isinstance(children, Dom):
                result += children.find_all_tags(tag_name)

        return result

    def _build_attribute(self) -> str:
        attribute_list = list()
        for key in self.attributes:
            if self.attributes[key] is None:
                attribute_list.append(key)
            else:
                attribute_list.append("{key}={value}".format(key=key, value=self.attributes[key]))
        return ' '.join(attribute_list)

    def _build_void_tag_html(self) -> str:
        attr = self._build_attribute()
        if attr:
            html = '<{tag_name} {tag_attributes}>'
            return html.format(tag_name=self._tag_name, tag_attributes=attr)
        else:
            html = '<{tag_name}>'
            return html.format(tag_name=self._tag_name)

    def _build_children_html(self) -> str:
        html = ''
        for children in self.children:
            if isinstance(children, str):
                html += children
            elif isinstance(children, Dom):
                html += children.build_html()
            else:
                raise RuntimeError("unknown type")
        return html


from django.contrib.auth.views import LoginView, LogoutView, PasswordResetView, PasswordResetCompleteView
from django.urls import path
from . import views
from django.contrib.auth import views as auth_views
#from . import forms

urlpatterns = [
    path('', views.index, name="Management Index"),
    # path('groups/', views.groups, name="Groups"),
    # path('groups/add/', views.group_new, name="Group new"),
    # path('groups/<str:group_name>/', views.group_view, name="Group view"),
    # path('groups/<str:group_name>/delete/', views.group_delete, name="Group delete"),
    path('customers/', views.customers, name="Customers"),
    path('customers/<str:username>/', views.customers_details, name="Customer Profile"),
    path('customers/<str:username>/delete/', views.user_delete, name="Customer Profile"),
    path('customers/<str:username>/lock/', views.user_lock, name="Customer Lock Account"),
    path('orders/', views.orders, name="Orders"),
    # path('orders/<int:id>', views.orders_details, name="Order Details"),
    path('orders/<int:id>/delete/', views.orders_delete, name="Order Delete"),
    path('orders/<int:id>/complete/', views.orders_complete, name="Order Complete"),
    path('employees/', views.employees, name="Employees"),
    path('employees/<str:username>/$', views.employees_profile, name="Employee Profile"),
    path('employees/<str:username>/delete/', views.user_delete, name="Employee Profile"),
    path('employees/<str:username>/lock/', views.user_lock, name="Employee Profile"),
    path('customers/<str:username>/delete/', views.user_delete, name="Customer Delete Account"),
    path('customers/<str:username>/lock/', views.user_lock, name="Customer Lock Account"),
    path('employees/register/', views.employees_register, name="Register Employee"),
    path('config/', views.config, name="Management Config"),
    path('newitem/', views.new_item, name='Create Item')
]


# MAIN DISCORD BOT FILE
from typing import Optional
import discord
from discord.ext import commands
from discord import Member
from discord.ext.tasks import loop
from googlesearch import search
from selenium import webdriver

import time

driver = webdriver.Edge(
    executable_path='path to executable')
intents = discord.Intents().all()
intents.presences = True
client = commands.Bot(command_prefix="st ", intents=intents)
client.remove_command('help')
u = ''
ind = 0
curr = ''
lin = ''

@client.event
async def on_ready():
    print_info.start()
    print("im alive and working!!(logged in as {0.user})".format(client))
    await client.change_presence(activity=discord.Activity(type=discord.ActivityType.watching, name="SUIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIIII"))

@client.command()
async def join(ctx, user: Optional[Member]):
    if ctx.author.id == 'my discord id':
        try:
            global u, ind, curr, lin
            u = user
            for i in range(len(u.activities)):
                if u.activities[i].name == "Spotify":
                    ind = i
                    curr = u.activities[ind].title
                    query = f"{u.activities[ind].title} {u.activities[ind].artist} youtube lyric video"
                    for j in search(query, tld="co.in", num=1, stop=1, pause=2):
                        link = j
                    indi = link.index('.com')+4
                    lin = link[0:indi]+"."+link[indi:]
                    driver.get(lin)
                    with open('info.txt', 'w') as f:
                        f.write(
                            f'{u.display_name}!@!{u.activities[ind].title}!@!{u.activities[ind].artist}!@!{u.activities[ind].album_cover_url}')
            await ctx.send(f"joined session of {u.display_name}!!")
        except Exception as e:
            pass
    else:
        await ctx.send("i only work for realhardik18 cause he is the best")

@loop(seconds=1)
async def print_info():
    global curr, u, ind, lin
    try:
        if curr != u.activities[ind].title:
            print(u.activities[ind].title)
            curr = u.activities[ind].title
            query = f"{u.activities[ind].title} {u.activities[ind].artist} youtube lyric video"
            for j in search(query, tld="co.in", num=1, stop=1, pause=2):
                link = j
            indi = link.index('.com')+4
            lin = link[0:indi]+"."+link[indi:]
            driver.get(lin)
            with open('info.txt', 'w') as f:
                f.write(
                    f'{u.display_name}!@!{u.activities[ind].title}!@!{u.activities[ind].artist}!@!{u.activities[ind].album_cover_url}')
        else:
            print('same', curr)
    except Exception as e:
        print(e)
        pass

client.run('discord bot token')


"""exercicio025.py em 2018-10-04. Projeto Practice Python.

Você, o usuário, terá em sua cabeça um número entre 0 e 100.
O programa adivinhará um número e você, o usuário, dirá se ele está muito alto, muito baixo ou o seu número.
No final deste intercâmbio, o seu programa deve imprimir quantos palpites foram necessários para obter o seu número.

Como o escritor deste programa, você terá que escolher como seu programa irá adivinhar estrategicamente.
Uma estratégia ingênua pode ser simplesmente começar a adivinhação em 1 e continuar (2, 3, 4, etc.) até atingir
o número. Mas essa não é uma estratégia de adivinhação ideal.
Uma estratégia alternativa pode ser adivinhar 50 (bem no meio do intervalo) e, em seguida, aumentar / diminuir em 1,
conforme necessário. Depois de escrever o programa, tente encontrar a estratégia ideal!

"""
from cicero import cabecalho

def adivinhar(palpites: int = 0) -> object:
    """Encontra um número dividindo uma lista pela metade (https://pt.wikipedia.org/wiki/Pesquisa_binária#Código_em_C)

    :param palpites: quantidade de tentativas para encontrar o número
    :type palpites: int
    :return: imprime a quantidade de tentativa
    :rtype: object
    """
    usuario = ' '
    numeros = list(range(0, 101))

    while not (len(numeros) == 1 or usuario == '='):
        usuario = ' '
        metade = len(numeros) // 2
        # palpite é o índice da medade da lista
        palpite = numeros[metade]
        while usuario not in '<>=':
            usuario = str(input(f'O numero é maior(>), menor(<) ou igual(=) a {palpite}? ')).strip()[0]
        if usuario == '>':
            # a lista passa a ter a metade maior dos valores
            numeros = numeros[(metade + 1):]
            palpites += 1
        elif usuario == '<':
            # a lista passa a ter a metade menor dos valores
            numeros = numeros[:metade]
            palpites += 1
    return print(f'Total de palpites: {palpites}')

if __name__ == '__main__':
    cabecalho('Jogo de adivinhação 2')
    adivinhar()


from csv import writer
from json import loads
from bs4 import BeautifulSoup as soup
from urllib.request import Request, urlopen

# Declare variables
tickers = set()
priceData = {}
data = {'ticker':None,
		'lastOpen':None,
		'lastClose':None,
		'Index':None,
		'Market Cap':None,
		'Income':None,
		'Sales':None,
		'Book/sh':None,
		'Cash/sh':None,
		'Dividend':None,
		'Dividend %':None,
		'Employees':None,
		'Optionable':None,
		'Shortable':None,
		'Recom':None,
		'P/E':None,
		'Forward P/E':None,
		'PEG':None,
		'P/S':None,
		'P/B':None,
		'P/C':None,
		'P/FCF':None,
		'Quick Ratio':None,
		'Current Ratio':None,
		'Debt/Eq':None,
		'LT Debt/Eq':None,
		'SMA20':None,
		'EPS (ttm)':None,
		'EPS next Y':None,
		'EPS next Q':None,
		'EPS this Y':None,
		'EPS next Y':None,
		'EPS next 5Y':None,
		'EPS past 5Y':None,
		'Sales past 5Y':None,
		'Sales Q/Q':None,
		'EPS Q/Q':None,
		'Earnings':None,
		'SMA50':None,
		'Insider Own':None,
		'Insider Trans':None,
		'Inst Own':None,
		'ROA':None,
		'ROE':None,
		'ROI':None,
		'Gross Margin':None,
		'Oper. Margin':None,
		'Profit Margin':None,
		'Payout':None,
		'Shs Outstand':None,
		'Shs Float':None,
		'Short Float':None,
		'Short Ratio':None,
		'Target Price':None,
		'52W Range':None,
		'52W High':None,
		'52W Low':None,
		'RSI (14)':None,
		'Rel Volume':None,
		'Avg Volume':None,
		# 'Volume':None,
		'Perf Week':None,
		'Perf Month':None,
		'Perf Quarter':None,
		'Perf Half Y':None,
		'Perf Year':None,
		'Perf YTD':None,
		'Beta':None,
		'ATR':None,
		'Volatility':None,
		'Prev Close':None,
		'Price':None,
		# 'Change':None,
	}

# Get tickers
with open('tickers-nasdaq-07-2022.csv', 'r') as file:
	for index, row in enumerate(file):
		if index == 0:
			continue

		ticker = row.split(',')[0]

		if '^' in ticker or '/' in ticker:
			continue

		tickers.add(ticker)

# Open TSV file
with open('finviz.tsv', 'w+') as file:
	tsv_writer = writer(file, delimiter='\t')
	tsv_writer.writerow(data.keys())
	for ticker in tickers:
		print (f'\nScraping {ticker}...\n')
		url = f'http://finviz.com/quote.ashx?t={ticker}'
		req = Request(url, headers={'User-Agent': 'Mozilla/5.0'})
		try:
			webpage = urlopen(req).read()
		except Exception as e:
			print(f'{ticker} --- {e}')
			continue
		soupObject = soup(webpage, "html.parser")

		# Parse Javascript
		soupScript = soupObject.find_all('script')
		for row in soupScript:
			rowText = row.text
			if 'var data' in rowText:

				left_braces = []
				right_braces = []

				for index, char in enumerate(rowText):
					if char == '{':
						left_braces.append(index)
					if char == '}':
						right_braces.append(index)

				priceData = loads(rowText[left_braces[1]:right_braces[-2]+1])
				if priceData['lastOpen'] == None or priceData['lastClose'] == None:
					print('skipping')
					continue
				data['ticker'] = priceData['ticker']
				data['lastOpen'] = round(priceData['lastOpen'], 2)
				data['lastClose'] = round(priceData['lastClose'],2)

		# Parse HTML
		soupText = soupObject.get_text().splitlines()
		for row in soupText:
			for key in data:
				if data[key] == None and key in row:
					data[key] = row.split(key)[1]

		# Write to TSV
		tsv_writer.writerow(data.values())

		# Print to Terminal
		for key in data:
			print(f'{key:<15}{data[key]}')

		# Print to Terminal
		for key in data:
			data[key] = None


# -*- coding: utf-8 -*-
"""
Created on Mon Jul  8 20:08:23 2019

@author: Solmir741
"""

import openpyxl, xlrd
import numpy as np
wb = openpyxl.load_workbook(filename = 'test2.xlsm')
sheet = wb["Лист1"]
"""
Алгоритм основан на вычислении значения угла между стороной - вектором четырехугольника (вычисляется разность от конца к началу вектора)
и вектором от одной из вершин до введеной точки. Если вычисленное значение меньше нуля (при обходе вершин против часовой, оно будет больше нуля), то точка внутри
четырехугольника относительно рассматриваемой его стороны. Если значение больше нуля - точка снаружи. Если = 0 - точка на лежит на стороне.
Если координаты вершины совпадаютс с координатами точки - точка в вершине.  Т.о. проводим проверку всех четырех сторон.
"""

def v_delta(x1, x2, y1, y2):
    zx = x2-x1
    zy = y2-y1
    return (zx, zy)

def v_prod (x, y):
    z=x[0]*y[1]-y[0]*x[1]
    return z

def vertex(bool_):
    for e in range(4):
        vx = float(sheet['A' + str(e + 1)].value)
        vy = float(sheet['B' + str(e + 1)].value)
        if vx == Px and vy == Py:
            return True

fl = 0

while True:
    try:
        Px = float(input("Введите координату х: "))
    except:
        print("Вы должны ввести число, попробуйте снова!")
    else:
        break

while True:
    try:
        Py = float(input("Введите координату y: "))
    except:
        print("Вы должны ввести число, попробуйте снова!")
    else:
        break

Ax0 = float(sheet['A1'].value) #координаты вершины
Ay0 = float(sheet['B1'].value)

for r in range(4):
    if r < 3:
        Ax = float(sheet['A' + str(r + 1)].value)
        Ay = float(sheet['B' + str(r + 1)].value)
        Bx = float(sheet['A' + str(r + 2)].value)
        By = float(sheet['B' + str(r + 2)].value)

    else:
        Ax = float(sheet['A' + str(r + 1)].value)
        Ay = float(sheet['B' + str(r + 1)].value)
        Bx = Ax0
        By = Ay0

    res_ = np.round(v_prod(v_delta(Ax, Bx, Ay, By), v_delta(Ax, Px, Ay, Py)), 4)
    if res_ > 0:
        print ('точка снаружи четырехугольника')
        break
    elif res_ < 0:
        fl = r
    elif res_ == 0:
        if vertex(False) == True:
            print ('точка - вершина четырехугольника')
            break
        print ('точка лежит на сторонах четырехугольника')
        break

if fl == 3:
    print ('точка внутри четырехугольника')


#rekurencyjnie
def horner_diagram(wsp, st, x):
    if st == 0:
        return wsp[0]
    return x * horner_diagram(wsp, st-1, x) + wsp[st]

"""#iteracyjnie
def horner_diagram2(wsp, st, x):
    result = wsp[0]
    i = 1
    for i in range(st):
        result = result * x + wsp[i]
        i += 1
    return result"""

if __name__ == '__main__':
    i = 0

    degree = int(input("Podaj stopień wielomianu: "))

    factors = []

    for i in range(degree + 1):
        x = int(input(f"Podaj współczynnik stojący przy potędze {degree - i}: "))
        factors.append(x)
        i += 1

    argument = int(input("Podaj argument: "))
    print(f"W( {argument} ) = {horner_diagram(factors, degree, argument)} \n")


from ..model.Database import IConstants as I
from PyQt5 import QtWidgets

class QueriesController:

    def __init__(self, pView, pModel):

        self.view = pView
        self.model = pModel

        # Defining the data
        self.queries = {
            'Sold Products': [I.PRODUCTS_SOLD,
                              ['ID', 'Product', 'Buyer', 'Price', 'Date Bought'],
                              (self.model.connectedUser.id, )],

            'Most expensive sales': [I.MOST_EXPENSIVE_SALES,
                                      ['ID', 'Product', 'Buyer', 'Country', 'Price', 'Date Bought'],
                                      (self.model.connectedUser.id, )]
        }

        if self.model.connectedUser.isAdmin:
            self.queries['Top Sellers'] = [I.TOP_SELLERS, ['ID', 'USERNAME', 'AMOUNT OF SALES'], ()]
            self.queries['Top Buyers'] = [I.TOP_BUYERS, ['ID', 'USERNAME', 'AMOUNT OF PURCHASES'], ()]
            self.queries['Min and Max per Category'] = [I.MIN_MAX_PRICES, ['CATEGORY', 'MAX', 'MIN'], ()]

        for query in self.queries:
            self.view.ui.Queries_QueriesInput.addItem(query)

        self.view.ui.Queries_QueriesInput.activated.connect(self.changeHeaders)
        self.view.ui.Queries_ShowButton.clicked.connect(self.loadQuery)

    def changeHeaders(self):
        '''
             Changes the headers of the queries.
        '''
        # Obtains the query data
        self.view.ui.Queries_QueriesTableDisplay.clear()
        queryName = self.view.ui.Queries_QueriesInput.currentText()
        queryData = self.queries[queryName]

        # Sets the headers accordingly
        self.view.ui.Queries_QueriesTableDisplay.setColumnCount(len(queryData[1]))
        self.view.ui.Queries_QueriesTableDisplay.setHorizontalHeaderLabels(queryData[1])

    def loadQuery(self):
        '''
            Loads the information obtained from the query into the table
        '''
        try:
            queryName = self.view.ui.Queries_QueriesInput.currentText()
            queryData = self.queries[queryName]

            results = self.model.query(queryData[0], queryData[2])

            self.view.ui.Queries_QueriesTableDisplay.setRowCount(len(results))

            # Loads queried data
            for i in range(len(results)):
                for j in range(len(queryData[1])):
                    item = QtWidgets.QTableWidgetItem(str(results[i][j]))
                    self.view.ui.Queries_QueriesTableDisplay.setItem(i, j, item)

        except Exception as err:
            print(err)


import sys
def argss(pd_df,df):
    def dname():
        dname = "dname"
        if dname in pd_df.columns:
            dname =df[0].get(dname)
            return dname
        else:
            return None
    d_name=dname()
    def target():
        target = "target"
        if target in pd_df.columns:
            target =df[0].get(target)
            return target
        else:
            return None
    target_=target()
    def DTClassifier():
            DTClassifier = "DTClassifier"
            if DTClassifier in pd_df.columns:
                DTClassifier =df[0].get(DTClassifier)
                return DTClassifier
            else:
                return None
    DTClassifier=DTClassifier()
    def RFClassifier():
        RFClassifier="RFClassifier"
        if RFClassifier in pd_df.columns:
            RFClassifier =df[0].get(RFClassifier)
            return RFClassifier
        else:
            return None
    RFClassifier=RFClassifier()
    def config_object_user():
        config_object_user = "config_object_user"
        if config_object_user in pd_df.columns:
            config_object_user =df[0].get(config_object_user)
            return config_object_user
        else:
            return None
    config_object_user_=config_object_user()
    # print(ai)
    def model_file():
        model_file ="model_file"
        if model_file in pd_df.columns:
            amodel_filei =df[0].get(model_file)
            return model_file
        else:
            return None
    model_file_=model_file()
    def predict():
        predict ="predict"
        if predict in pd_df.columns:
            predict =df[0].get(predict)
            return predict
        else:
            return None
    predict_=predict()

    def phenome_data():
        phenome_data ="phenome_data"
        if phenome_data in pd_df.columns:
            phenome_data =df[0].get(phenome_data)
            return phenome_data
        else:
            return None
    phenome_data_=phenome_data()

    def user_defined_terminology():
        user_defined_terminology ="user_defined_terminology"
        if user_defined_terminology in pd_df.columns:
            user_defined_terminology =df[0].get(user_defined_terminology)
            return user_defined_terminology
        else:
            return None
    user_defined_terminology_=user_defined_terminology()
    def sample_type():
        sample_type ="sample_type"
        if sample_type in pd_df.columns:
            sample_type =df[0].get(sample_type)
            return sample_type
        else:
            return None
    sample_type_=sample_type()
    def description():
        description ="description"
        if description in pd_df.columns:
            description =df[0].get(description)
            return description
        else:
            return None
    description_=description()
    def uom_type():
        uom_type ="uom_type"
        if uom_type in pd_df.columns:
            uom_type =df[0].get(uom_type)
            return uom_type
        else:
            return None
    uom_type_=uom_type()
    def all_M():
        all_M ="all_M"
        if all_M in pd_df.columns:
            all_M =df[0].get(all_M)
            return all_M
        else:
            return None
    all_M_=all_M()
    def d_col():
        d_col ="d_col"
        if d_col in pd_df.columns:
            d_col =df[0].get(d_col)
            return d_col
        else:
            return None
    d_col_=d_col()
    def index():
        index ="index"
        if index in pd_df.columns:
            index =df[0].get(index)
            return index
        else:
            return None
    index_=index()
    def to_csv_name():
        to_csv_name ="to_csv_name"
        if to_csv_name in pd_df.columns:
            to_csv_name =df[0].get(to_csv_name)
            return to_csv_name
        else:
            return None
    to_csv_name_=to_csv_name()
    def Classification_or_Regression():
        Classification_or_Regression ="Classification_or_Regression"
        if Classification_or_Regression in pd_df.columns:
            Classification_or_Regression =df[0].get(Classification_or_Regression)
            return Classification_or_Regression
        else:
            return 0.8
    Classification_or_Regression=Classification_or_Regression()
    def analysis_id():
        analysis_id ="analysis_id"
        if analysis_id in pd_df.columns:
            analysis_id =df[0].get(analysis_id)
            return analysis_id
        else:
            print("analysis_id IS not given")
            sys.exit()
            return None
    analysis_id=analysis_id()
    def output():
        output ="output"
        if output in pd_df.columns:
            output =df[0].get(output)
            return output
        else:
            return "test_"
    output=output()
    print(d_name,target_,DTClassifier,RFClassifier,config_object_user_ ,model_file_,predict_,phenome_data_,user_defined_terminology_,sample_type_,description_,uom_type_,all_M_,d_col_,index_,to_csv_name_,Classification_or_Regression,analysis_id,output)
    return  d_name,target_,DTClassifier,RFClassifier,config_object_user_ ,model_file_,predict_,phenome_data_,user_defined_terminology_,sample_type_,description_,uom_type_,all_M_,d_col_,index_,to_csv_name_,Classification_or_Regression,analysis_id,output


from pydantic import BaseSettings, Field

class XpublishSettings(BaseSettings):
    user_agent: str = Field(
        "xpublish-osn", description="User agent to use for any queries"
    )
    development: bool = Field(
        False, description="Is the server in a development environment"
    )
    host: str = Field("0.0.0.0", description="Host IP to respond to")
    port: int = Field(9005, description="Port for the server to respond to")
    log_level: str = Field("debug", description="Default logging level")
    proxied: bool = Field(True, description="Is the server operating behind a proxy")

settings = XpublishSettings()


# import the necessary packages
import cv2
import numpy as np
from PIL import Image
import os

#!/usr/bin/python3
import RPi.GPIO as GPIO # Controller GPIO

# Use the BCM channel numbers
GPIO.setmode(GPIO.BCM)
# Set up a pin (17) as an output
GPIO.setup(17, GPIO.OUT)

# Use file .xml to face recognition
# Load a cascade file for detecting faces
face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')

# Use LBPH(LOCAL BINARY PATTERNS HISTOGRAMS) in the OpenCV library.
recognizer = cv2.face.LBPHFaceRecognizer_create()

# Read training data from file.yml created
recognizer.read('recognizer/trainingDatas.yml')

# Initialize the camera and grab a reference to the video capture
cap = cv2.VideoCapture(0)

# Font for label
font = cv2.FONT_HERSHEY_SIMPLEX

# Iniciate id counter
id = 0

# Names related to ids: example ==> ThDanh: id=1,  etc
names = ['none', 'ThDanh']

# loop over frames from the video file stream
while True:
    # Grab the frame from the threaded video stream
    ret, frame =  cap.read()

    # Convert to grayscale
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Detect faces in the frame
    faces = face_cascade.detectMultiScale(gray)

    #Draw a rectangle around every found face
    for(x,y,w,h) in faces:
        cv2.rectangle(frame,(x,y),(x+w,y+h),(0,255,0),2)

        roi_gray = gray[y:y +h, x:x +w]

        id, confidence = recognizer.predict(roi_gray)

        # Check if confidence is less them 100 ==> "0" is perfect match
        if confidence < 100:
            id = names[id]
            confidence = "  {0}%".format(round(100 - confidence))

            cv2.putText(frame, str(id), (x+5,y-5), font, 1, (255,255,255), 2)

            GPIO.output(17,GPIO.HIGH) #Led_ON

        else:
            id = "Unknown"     #if face is not recognized, then print Unknown
            confidence = "  {0}%".format(round(100 - confidence))

            cv2.putText(frame, str(id), (x+5,y-5), font, 1, (255,0,0), 2)

            GPIO.output(17,GPIO.LOW) #Led_OFF

        cv2.putText(frame, str(confidence), (x+5,y+h-5), font, 1, (255,0,0), 1)
        print(x,y,w,h)

    # Display a frame
    cv2.imshow("Camera", frame)

    # Wait for 'q' key was pressed and break from the loop
    if cv2.waitKey(1) & 0xff == ord("q"):
	    break

# Clear the stream in preparation for the next frame
cap.release()
cv2.destroyAllWindows()


#!/usr/bin/env python3

from socket import socket, create_connection
import sys
from game_logic import Champion, Match, Team, Shape
from datetime import datetime
from threading import Thread
from rich.console import Console
from time import sleep
from os import getcwd

##### DATABASE LOGIC
# Reading the data base
# The function retrieves command from client about which database it must fetch from the database.
# Client input is then used by server to send request to server to get the particular database
def get_database(conn: socket, database_name: str, reciver="client") -> None:
    db_conn.sendall(f"read_database {database_name}".encode())
    db_response: str = db_conn.recv(8024).decode()
    if reciver == "client":
        conn.sendall(db_response.encode())
    else:
        return eval(db_response)

#def get_database_server(database_name: str) -> list:
    #db_conn.sendall(f"read_database {database_name}".encode())
    #db_response: str = db_conn.recv(8024).decode()
    #return eval(db_response)

##### PLAYING TEAM LOCAL TACTICS
# A lobby, when a client is waiting for a game
def start_lobby(conn: socket, name: str) -> None:
    ### How lobby is structured
    # [0] is the players connection
    # [1] is the players name
    # [2] is the players champions
    ###
    lobby.append((conn, name, []))
    console.log(f"'{name}' joined the game lobby. ({len(lobby)}/2)", style=TXT_INFO)

    while len(lobby) < 2: # if not 2 people in the lobby, wait for new connection.
        sleep(1)
    else: # else, lobby_found is sent to the client connection, which initiates the game.
        conn.sendall("lobby_found".encode())
        console.log(f"Lobby full - {[player[1] for player in lobby]}")

# Function which starts the game on the server side.
def play_game() -> None:

    while total_picked_server() < 4: # Waits until 4 champions have been picked before Match is initiated.
        sleep(3)
    else:
        match: Match = Match(
            Team([parse_champion(champion) for champion in lobby[0][2]]), # Adds champions to red team and blue team
            Team([parse_champion(champion) for champion in lobby[1][2]]) # respectively in variable 'match'.
        )
        match.play() # Starts the match using the game logic from game_logic.py
        send_match_summary(match, [player[1:] for player in lobby])

        for player in lobby:
            sleep(0.2) # Or else database and server get overwhelmed
            player[0].send("game_end".encode())

        console.log("Match is over!")
        lobby.clear()
        if len(lobby) == 0:
            console.log("Lobby is empty.")

        play_game()

# Sends match results to the database so the database can append the information to the match_history database
# The winner, the score, the time of the match and which champions played is all sent to the database by the server.
def send_match_summary(match: Match, players: list) -> None:

    match_summary: dict = {} # Dictionary to store all the information from the match
    # Dict keys are 'time', 'players', 'rounds',

    EMOJI = {
        Shape.ROCK: ':raised_fist-emoji:',
        Shape.PAPER: ':raised_hand-emoji:',
        Shape.SCISSORS: ':victory_hand-emoji:'
    }

    now = datetime.now()
    date_time = now.strftime("%d/%m %H:%M")

    match_summary["time"] = date_time

    match_summary["players"] = []
    for index, player in enumerate(players):
        name = player[0]
        champions = player[1]
        match_summary["players"].append({"name": name, "champions": [champion["name"] for champion in champions], "score": match.score[index]})
        # Adds the champion names and the score to both of the players in the list
    match_summary["rounds"] = {}
    for index, round in enumerate(match.rounds):
        n_round = index + 1
        match_summary["rounds"][f"{n_round}"] = []

        for fight in round:
            p1_champ, p2_champ = fight.split(', ')
            current_fight: list = match_summary["rounds"][f"{n_round}"]
            current_fight.append(f"{p1_champ} {EMOJI[round[fight].red]} vs {p2_champ} {EMOJI[round[fight].blue]}")

    console.log(f"Sending to database: append_database match_history {match_summary}")
    db_conn.sendall(f"append_database match_history {match_summary}".encode()) #Sends information about the match to the database

# Function which changes the format of the champion parameter and its attributes (name, rock, paper, scissors)
# so that the Champion Class in game_logic.py can understand.
def parse_champion(champion: dict) -> Champion:
    name: str; rock: int; paper: int; scissors: int

    console.log(champion)

    name = champion["name"]
    rock = champion["abilities"]["rock"] / 100
    paper = champion["abilities"]["paper"] / 100
    scissors = champion["abilities"]["scissors"] / 100

    return Champion(name, rock, paper, scissors)

# Adds champion to the roster for each player
def add_champion(conn: socket, champion: str) -> None:
    for player in lobby:
        if player[0] == conn:
            player[2].append(eval(champion))
            console.log(f"{player[1]} has: {player[2]}")

# Function which counts how many players are in the lobby
# and sends it to the client connection.
def total_picked(conn: socket) -> None:
    n: int = 0
    for player in lobby:
        n += len(player[2])
    conn.send(f"{n}".encode())

# A function where the server counts how many players are in the lobby
# returns the amount of players
def total_picked_server() -> int:
    n: int = 0
    for player in lobby:
        n += len(player[2])

    return n

# Gets the name of the player opponent for player 1.
def get_opponent_names(conn: socket) -> None:
    opponents = []
    for player in lobby:
        if player[0] != conn: # Check that both players is not from the same connection.
            opponents.append(player[1]) # Player name is added to the list

    conn.send(f"{', '.join(opponents)}".encode()) #Joins the list and sends it to the client connection.

def filter_champs(conn: socket, filter: str) -> None:
    my_champions = [] # To handle player 1 champions
    other_champions = [] # To handle player 2 champions

    for player in lobby:
        if player[0] == conn: # If player 1 has connected
            my_champions.append(player[2])
        else:
            other_champions.append(player[2]) # if player 2 has connected

    if filter == "me":
        conn.send(f"{my_champions}".encode())
    elif filter == "other":
        conn.send(f"{other_champions}".encode())

# This function receives a connection from the client and gives the client information about which player it is
# or which player it is going to be.
def whoami(conn: socket):
    found: bool = False # Default value is False.
    for id, player in enumerate(lobby):
        if conn == player[0]: # If the connection connecting to the server is player 1
            conn.send(f"{id}".encode()) # Then send the id number to the client
            found = True # and set found equal to True

    if not found: # If found is True (there is a player in the lobby) then send the length of the lobby + 1.
        conn.sendall(f"{len(lobby) + 1}".encode())

# Gives the server information over how many champion picks that are left and sends it to the client.
def get_turn(conn: socket):
    picks_left = 4 - (len(lobby[0][2]) + len(lobby[1][2]))

    console.log(f"Picks left: {picks_left}", style=TXT_INFO)

    console.log(f"{picks_left % 2}", style=TXT_INFO)
    conn.send(f"{picks_left % 2}".encode())

# A function which simply removes a player from the lobby list.
def remove_from_lobby(player_to_remove: socket, address: tuple) -> None:
    for player in lobby:
        if player[0] == player_to_remove:
            lobby.remove(player)
            console.log(f"{address} has been removed from the lobby.", style=TXT_INFO)
    console.log(f"Lobby: {len(lobby)}/2", style=TXT_INFO)

##### SOCKET LOGIC #####
# Accept incoming connections
def accept(sock: str) -> None:
    while True:
        conn: str; address: tuple
        conn, address = sock.accept()
        console.log(f"Client {address} has connected", style=TXT_CONN)
        Thread(target=read, args=(conn, address)).start()

# Read the incoming connections
def read(conn: socket, address: tuple) -> None:
    while True:
        client_input: bytes = conn.recv(1024)

        if client_input:
            client_input_decoded: str = (client_input.decode() + " ").split(" ", 1)
            command: str = client_input_decoded[0].strip()
            args: str = client_input_decoded[1].strip()

            console.log(f"{address} sent: [{command, args}]", style=TXT_INFO)

            if command in commands:
                if args:
                    commands[command](conn, args)
                else:
                    commands[command](conn)
            else:
                console.log("AN UNKNOWN COMMAND WAS SENT!", style=TXT_DCON)

        else:
            console.log(f"Client {address} has disconnected", style=TXT_DCON)
            remove_from_lobby(conn, address)
            conn.close()
            break

##### MAIN #####
# Commands the server recognises. Stored in a dictionary
commands: dict = {
    "get_database": get_database,
    "start_lobby": start_lobby,
    "add_champion": add_champion,
    "total_picked": total_picked,
    "whoami": whoami,
    "get_turn": get_turn,
    "filter_champs": filter_champs,
    "get_opponent_names": get_opponent_names,
}

cwd: str = getcwd()
console: Console = Console()

# Console colors
TXT_CONN: str = "bold green"
TXT_DCON: str = "bold red"
TXT_INFO: str = "bold yellow"

# Players and lobby
lobby: list = []

if __name__ == "__main__":
    HOST: str; PORT: int; DB_HOST: str; DB_PORT: int
    PORT = 6666
    DB_PORT = 8888
    if "docker" in sys.argv:
        HOST = "server"
        DB_HOST = "database"
    else:
        HOST = "localhost"
        DB_HOST = "localhost"

    # Set up TCP socket
    sock = socket()
    sock.bind((HOST, PORT))
    sock.listen()

    # Connect to the database
    try:
        db_conn = create_connection((DB_HOST, DB_PORT))
    except ConnectionRefusedError:
        console.log(f"Connection to database on {DB_HOST}:{DB_PORT} has failed.", style=TXT_DCON)

    console.print(f"Starting server on {HOST}:{PORT}.", style=TXT_DCON)

    Thread(target=play_game).start()
    accept(sock)

    console.print("Stopping server.")
    db_conn.close()


import numpy as np
import matplotlib.pyplot as plt
from scipy.integrate import odeint
from scipy.optimize import curve_fit
from scipy.signal import find_peaks
from harmonic_analysis import amplitude_sweep, fourier_func

'''
Solving the differential equations describing a Gaussian perturbation to a
two-level system. By varying the perturbation frequency and measuring the state at time
'''

#%%
'''
This cell scans for various standard deviations, amplitudes or means to find
the largest peak for each. Scans one at a time, depending on what is and isn't
commented.
'''
if __name__ == "__main__":
    plt.close()

    omega_fi = 0.2           # frequency between states
    std = 2.5
    t0 = 12.8
    num_points = 10000      # number of time array points
    num_measurements = 1024
    frequency = omega_fi    # resonance
    initial_conditions = [1,0,0,0]

    # arrays
    N = 1000
    amp_array = np.linspace(0.1, 5, N)
    t_array = np.linspace(0, 4*t0, num_points)
    state_array = np.zeros(N)

    probability_averages = amplitude_sweep(omega_fi, std, t0, frequency, t_array, amp_array, initial_conditions)

    ### vectorised?
    # rand_nums = np.random.rand(N)
    # state_array = np.where(rand_nums >= probability_averages, 1, 0)
    # state = np.sum(state_array)

    for i, probability in enumerate(probability_averages):
        state = 0
        for n in range(num_measurements):
            rand_num = np.random.rand()
            if rand_num <= probability:
                state += 1
            else:
                pass
        state = state/num_measurements
        state_array[i] = state
    state_array -= np.mean(state_array)

    # fourier transform
    power, freq = fourier_func(state_array, np.max(t_array))
    sine_freq = freq[np.argmax(power)]
    print("Signal frequency is "+str(sine_freq))

    linestyles = ["#6edbfa","#82a6bd","#957080","#a93b42","#bc0505"]
    labels = []

    # figure for plotting the signal strength
    fig_signal = plt.figure(figsize=(8,6))
    ax_signal = fig_signal.gca()
    ax_signal.set_xlabel("Amplitude", fontsize=16)
    ax_signal.set_ylabel("Signal Strength", fontsize=16)
    ax_signal.set_title("Average Signal Strength over "+str(num_measurements)+" measurements", fontsize=20)
    # ax_signal.set_ylim(0, 1)

    ax_signal.plot(amp_array, state_array, "b")
    # ax_signal.plot(amp_array, np.sin(amp_array + 0.1))

    fig_fourier = plt.figure(figsize=(8,6))
    ax_fourier = fig_fourier.gca()
    ax_fourier.set_xlabel("Signal Frequency $t$", fontsize=16)
    ax_fourier.set_ylabel("Power", fontsize=16)
    ax_fourier.set_title("Frequency Spectrum of Signal", fontsize=20)
    ax_fourier.plot(freq, power, "ko")
#


from django.urls import path
from .views import (CompanyAPIView,
                    CompanyRetrieveUpdateAPIView,
                    AddCompanyUsers,
                    DeleteCompanyUsers,
                    )

urlpatterns = [
        path('', CompanyAPIView.as_view(), name='list_create'),
        path('<int:company_id>/',
             CompanyRetrieveUpdateAPIView.as_view(),
             name='retrieve_update'),
        path('add/user/',
             AddCompanyUsers.as_view(),
             name='add_user_in_company'),
        path('delete/user/',
             DeleteCompanyUsers.as_view(),
             name='delete_user_in_company'),
        ]


from django import template
from django.template import TemplateSyntaxError, Variable, Node, Variable, Library
from django.conf import settings

import re

register = template.Library()

from django.conf import settings

@register.filter
def split_addr(s):
    m = re.match(getattr(settings, "ADDRESS_FORMAT"), s)
    return {
        'street': m.group(1),
        'pcode': m.group(2),
        'city': m.group(3),
        'prov': m.group(4)
    }

@register.filter
def modulo(num, val):
    return num % val

@register.filter(name='roundup_divide')
def roundup_divide(items, items_per_page):
	try:
		return (items - 1) // items_per_page + 1
	except:
		return (len(items) - 1) // items_per_page + 1

@register.filter
def divide(num, val):
    return num // val

@register.filter(name='times')
def times(number):
    return range(number)

@register.filter(name='linepad')
def linepad(total_lines, available_lines_per_page):
    lines_on_last_page = total_lines % available_lines_per_page
    if  lines_on_last_page == 0:
        return 0
    else:
        return available_lines_per_page - lines_on_last_page

@register.simple_tag()
def silversly_version():
    version = settings.VERSION
    return version

@register.simple_tag()
def debug():
    return settings.DEBUG

# thanks to pklaus:

# I found some tricks in URLNode and url from defaulttags.py:
# https://code.djangoproject.com/browser/django/trunk/django/template/defaulttags.py
@register.tag
def value_from_settings(parser, token):
  bits = token.split_contents()
  if len(bits) < 2:
    raise TemplateSyntaxError("'%s' takes at least one " \
      "argument (settings constant to retrieve)" % bits[0])
  settingsvar = bits[1]
  settingsvar = settingsvar[1:-1] if settingsvar[0] == '"' else settingsvar
  asvar = None
  bits = bits[2:]
  if len(bits) >= 2 and bits[-2] == 'as':
    asvar = bits[-1]
    bits = bits[:-2]
  if len(bits):
    raise TemplateSyntaxError("'value_from_settings' didn't recognise " \
      "the arguments '%s'" % ", ".join(bits))
  return ValueFromSettings(settingsvar, asvar)

class ValueFromSettings(Node):
  def __init__(self, settingsvar, asvar):
    self.arg = Variable(settingsvar)
    self.asvar = asvar
  def render(self, context):
    ret_val = getattr(settings,str(self.arg))
    if self.asvar:
      context[self.asvar] = ret_val
      return ''
    else:
      return ret_val


import logging
from shaney.sourapples.config import SourApplesConfig
from shaney.sourapples.build import build

def main():
    # We depend entirely on the configuration file, not on command line
    # arguments, because we may not be executed from a command line.
    config = SourApplesConfig()

    # set up logging
    loglevel = getattr(logging, config.get('main', 'loglevel'))
    logging.basicConfig(level=loglevel)

    build(config)

if __name__ == '__main__':
    main()


import os
import csv

# total number of months
total_months = 0

# total amount of profit/losses over entire period
total_prof_loss = 0

# profit/losses value of last iteration
last_profit = 0

# average of changes of profit/losses
average_change = 0

# store csv file header
header = ""

# greatest increase in profits
max = 0

# date of greatest increase
max_date = 0

# greatest decrease in profits
min = 0

# date of greatest decrease
min_date = 0

# path where output file will be created
parent_path = "./analysis"

# file path to read the data from
budget_csv = os.path.join(".", "Resources", "budget_data.csv")

# if not exists, create  "analysis" directory
if (not os.path.exists(parent_path)):
    os.mkdir(parent_path)

# file path to write to
output_path = os.path.join(".", "analysis", "output.txt")

# Open the file using "write" mode.
with open(budget_csv) as csv_file:
    csv_reader = csv.reader(csv_file, delimiter=",")
    # skip the header
    header = next(csv_file)

    # Read through each row of data after the header
    for row in csv_reader:
        # The first element in the csv list is not a change, so exclude it.
        if total_months == 0:
            last_profit = int(row[1])

        total_prof_loss = total_prof_loss + int(row[1])
        total_months = total_months + 1
        change = int(row[1]) - last_profit
        average_change = average_change + change
        last_profit = int(row[1])

        # Carry min and max values of changes, to not have extra loop for this.
        if change > max:
            max = change
            max_date = row[0]
        if change < min:
            min = change
            min_date = row[0]

average_change = round((average_change/(total_months - 1)), 2)

# Open a new file using "write" mode
with open(output_path, 'w') as file_w:
    #print("'output.txt' file is created.")
    file_w.write("Financial Analysis" + "\n")
    file_w.write("------------------" + "\n")
    file_w.write(""+ "\n")
    file_w.write(f"Total Months: {total_months} \n")
    file_w.write(f"Total: ${total_prof_loss}\n")
    file_w.write(f"Average Change: ${average_change}\n")
    file_w.write(f"Greatest Increase in Profits: {max_date} (${max})\n")
    file_w.write(f"Greatest Decrease in Profits: {min_date} (${min})\n")
print()
print("Financial Analysis")
print("--------------------")
print()
print(f"Total Months: {total_months}")
print(f"Total: ${total_prof_loss}")
print(f"Average Change: ${average_change}")
print(f"Greatest Increase in Profits: {max_date} (${max})")
print(f"Greatest Decrease in Profits: {min_date} (${min})\n")


import argparse
import tkinter as tk
from PIL import ImageTk, Image
import os.path as path
import cv2

def binary_image(image, th):
    new_image = image.copy()
    for d in (0, 1, 2):
        mat = new_image[:, :, d]
        for r in range(mat.shape[0]):
            for c in range(mat.shape[1]):
                mat[r][c] = 255 if mat[r][c] > th else 0

    return new_image

def binary_image_name(image_path, image_name):
    return image_path.replace(image_name, 'binary-' + image_name)

def binarize_image_hook(image_path, image_name, val):
    bv = val.get()
    image = cv2.cvtColor(cv2.imread(image_path), cv2.COLOR_BGR2RGB)
    bi = binary_image(image, bv)
    b_path = binary_image_name(image_path, image_name)
    cv2.imwrite(b_path, bi)

    print('wrote binary image to path ' + str(b_path))

def build_gui(image_path, image_name):
    w_dim = 800
    start_y = 50
    slider_gap = 50

    window = tk.Tk()
    window.title('Image binarization')
    window.geometry('800x800')
    window.configure(background='grey')

    #read images
    image = ImageTk.PhotoImage(Image.open(image_path))
    b_path = binary_image_name(image_path, image_name)
    if path.exists(b_path):
        print('build_gui, reading in binary image')
        binary_image = ImageTk.PhotoImage(image=Image.fromarray(cv2.imread(b_path), 'RGB'))
    else:
        print('build_gui, reading original image')
        binary_image = image

    #left image
    og  = 'Original'
    left_image_label = tk.Text(window, height=1, width=len(og))
    left_image_label.place(x=0, y=0)
    left_image_label.insert(tk.END, og)
    panel1 = tk.Label(image=image)
    panel1.place(x=0, y=start_y)

    #right image
    bin_text = 'Binary'
    right_image_label = tk.Text(window, height=1, width=len(bin_text))
    right_image_label.place(x=w_dim - image.width(), y=0)
    right_image_label.insert(tk.END, bin_text)
    panel2 = tk.Label(image=binary_image)
    panel2.place(x=w_dim - binary_image.width(), y=start_y)

    #slider
    sv = tk.IntVar()
    slider = tk.Scale(window, from_=0.0, to=255.0, orient=tk.HORIZONTAL, variable=sv)
    slider.set(0)
    slider.place(x=slider_gap, y=start_y + image.height() + slider_gap)

    #binarize button
    exec_button = tk.Button(window, text='Binarize', width=15,
                            command=lambda: binarize_image_hook(image_path, image_name, sv))
    exec_button.place(x=slider_gap, y=start_y + image.height() + slider_gap * 2)

    button = tk.Button(window, text='Stop', width=15, command=window.destroy)
    button.pack()

    window.mainloop()

def parse_args():
     parser = argparse.ArgumentParser(description='Image binarization')

     parser.add_argument('--image', required=False, help='Path to input image')
     parser.add_argument('--case', required=False, help='test case run')
     return parser.parse_args()

def run_gui(args):
    base = path.basename(args.image)
    name = base[:base.index('.')]
    build_gui(args.image, name)

def test_case_1():
    bt = 0
    in_file = 'images/apple.jpeg'
    ri = cv2.imread(in_file)
    bi = binary_image(ri, 0)

    print("Input file: %s, binary threshold: %d, \n\nExplanation: %s"
          % (in_file, bt, "This is a bad input because the threshold was set too low. Therefore,\nmost of the pixels were set to white"))
    cv2.imshow('original', ri)
    cv2.imshow('binarized', bi)
    while True:
        cv2.waitKey(1000)
        if input() == 'q':
            break
    cv2.destroyAllWindows()

def test_case_2():
    bt = 255
    in_file = 'images/apple.jpeg'
    ri = cv2.imread(in_file)
    bi = binary_image(ri, bt)

    print("Input file: %s, binary threshold: %d, \n\nExplanation: %s"
          % (in_file, bt, "This is a bad input because the threshold was set too high. Therefore,\nmost of the pixels were set to black"))
    cv2.imshow('original', ri)
    cv2.imshow('binarized', bi)
    while True:
        cv2.waitKey(1000)
        if input() == 'q':
            break
    cv2.destroyAllWindows()

def test_case_3():
    bt = 80
    in_file = 'images/apple.jpeg'
    ri = cv2.imread(in_file)
    bi = binary_image(ri, bt)

    print("Input file: %s, binary threshold: %d, \n\nExplanation: %s"
          % (in_file, bt, "This is a good input because the threshold was set at a level that allowed\nfor pixels to be both black and white, thus producing the desired effect"))
    cv2.imshow('original', ri)
    cv2.imshow('binarized', bi)
    while True:
        cv2.waitKey(1000)
        if input() == 'q':
            break
    cv2.destroyAllWindows()

if __name__ == '__main__':
    args = parse_args()
    if args.case == '1':
        test_case_1()
    elif args.case == '2':
        test_case_2()
    elif args.case == '3':
        test_case_3()
    elif args.image:
        run_gui(args)
    else:
        print("bad inputs")


"""
209. Minimum Size Subarray Sum
Given an array of n positive integers and a positive integer s, find the minimal length of a contiguous subarray of which the sum ≥ s. If there isn't one, return 0 instead.

Example:

Input: s = 7, nums = [2,3,1,2,4,3]
Output: 2
Explanation: the subarray [4,3] has the minimal length under the problem constraint.
Follow up:
If you have figured out the O(n) solution, try coding another solution of which the time complexity is O(n log n).
"""
# Time complexity: O(N)
# Space complexity: O(1)
class Solution:
    def minSubArrayLen(self, s: int, nums: List[int]) -> int:
        if not nums:
            return 0

        best = float('inf')

        i = 0
        window_sum = 0

        for j in range(len(nums)):
            window_sum += nums[j]
            while window_sum >= s:
                best = min(best, j-i+1)
                window_sum -= nums[i]
                i += 1

        return best if best != float('inf') else 0

Leetcode/209. Minimum Size Subarray Sum.py


from utils import retornarlistas
import pandas as pd

num = 19
Id = 26143
num_anterior = 16
sit = 1

def comissoes_legislatura_anterior():

    url = f'https://dadosabertos.almg.gov.br/ws/legislaturas/{num}/comissoes'
    response = retornarlistas(url)
    list = response['list']
    df = pd.DataFrame.from_dict(list)
    df.to_excel(r'./legislaturas/comissoes_legislatura_anterior.xlsx')

def registro_legislatura():

    url = "https://dadosabertos.almg.gov.br/ws/legislaturas/atual"
    response = retornarlistas(url)
    list = response['legislatura']
    df = pd.DataFrame.from_dict(list)
    df.to_excel(r'./legislaturas/registro_legislatura.xlsx')

def registro_de_deputado():

    url = f'https://dadosabertos.almg.gov.br/ws/legislaturas/{num}/deputados/{Id}'
    response = retornarlistas(url)
    df = pd.DataFrame.from_dict(response)
    df.to_excel(r'./legislaturas/registro_de_deputado.xlsx')

def pesquisa_deputados_legislatura_anterior():

    url = f'https://dadosabertos.almg.gov.br/ws/legislaturas/{num_anterior}/deputados/situacao/{sit}'
    response = retornarlistas(url)
    list = response['list']
    df = pd.DataFrame.from_dict(list)
    df.to_excel(r'./legislaturas/pesquisa_deputados_legislatura_anterior.xlsx')

pesquisa_deputados_legislatura_anterior()


#!/usr/bin/env python3

import os
import sys
import csv
import re
import argparse
from unidecode import unidecode

# use as remove_non_ascii("...")
def remove_non_ascii(text):
    return unidecode(str(text))

def replace_trash(unicode_string):
     for i in range(0, len(unicode_string)):
         try:
             unicode_string[i].encode("ascii")
         except:
              #means it's non-ASCII
              unicode_string=unicode_string[i].replace(" ") #replacing it with a single space
     return unicode_string

def split(filehandler, delimiter=',', row_limit=10000,
          output_name_template='output_%s.csv', output_path='.', keep_headers=True,
          remove_all=False, zap_quotes_commas=False):
    """
    Splits a CSV file into multiple pieces.

    A quick bastardization of the Python CSV library.
    Arguments:
        `row_limit`: The number of rows you want in each output file. 10,000 by default.
        `output_name_template`: A %s-style template for the numbered output files.
        `output_path`: Where to stick the output files.
        `keep_headers`: Whether or not to print the headers in each output file.
    Example usage:

        >> from toolbox import csv_splitter;
        >> csv_splitter.split(open('/home/ben/input.csv', 'r'));

    """
    csv.field_size_limit(sys.maxsize)
    reader = csv.reader(filehandler, delimiter=delimiter)
    current_piece = 1
    current_out_path = os.path.join(
        output_path,
        output_name_template  % current_piece
    )
    current_out_writer = csv.writer(open(current_out_path, 'w'), dialect=csv.excel)#, quoting=csv.QUOTE_ALL)
    current_limit = row_limit
    real_line = 0
    if keep_headers:
        headers = next(reader)
        current_out_writer.writerow(headers)
    for i, row in enumerate(reader):
        #row = [s.replace('\0', "X") for s in row] # must be zapped prior
        #row = [re.sub(r'[\x00-\x1f\x7f-\x9f]', r' ', s) for s in row]
        row = [remove_non_ascii(s) for s in row]
        # keep LF, rm CR
        row = [re.sub(r'[\x00-\x09\x0b-\x1f\x7f-\x9f]', r' ', s) for s in row]
        # this used to be included by default...to handle genies
        if(zap_quotes_commas):
            row = [s.replace('"', ' ') for s in row]
            row = [s.replace(',', ' ') for s in row]
        #row = [replace_trash(s) for s in row]
        #row = [s.replaceAll("[^\\P{Cc}\\t\\r\\n]", "") for s in row]
        #print("{} - {}".format(i, row))
        if i + 1 > current_limit:
            current_piece += 1
            current_limit = row_limit * current_piece
            current_out_path = os.path.join(
                output_path,
                output_name_template  % current_piece
            )
            current_out_writer = csv.writer(open(current_out_path, 'w'), dialect=csv.excel)#, quoting=csv.QUOTE_ALL)
            if keep_headers:
                current_out_writer.writerow(headers)
        current_out_writer.writerow(row)

##
## split(open('/your/pat/input.csv', 'r'), row_limit=40000)
##
if __name__ == "__main__":

    parser = argparse.ArgumentParser(description="CSV row cutter and cleaner")
    parser.add_argument("file", help="Input file.")
    parser.add_argument("--rows", type=int, help="Number of rows per chunk.", default=15000)
    parser.add_argument("--zap-quotes-commas", action='store_true',
                        help="Remove quotes and commas",
                        default=False)
    parser.add_argument("--remove-all", action='store_true',
                        help="Remove all bad chars from strings.", default=False)
    args = parser.parse_args()

    split(open(args.file), row_limit=args.rows,
          output_name_template=args.file + '_%s.csv',
          remove_all=args.remove_all,
          zap_quotes_commas=args.zap_quotes_commas)


import logging
from flask import render_template, make_response, url_for
from flask_restful import Resource

from blog_management import hearts

LOGGER = logging.getLogger("running-log")

class HeartsGroup(Resource):

    def __init__(self):
        self.header = {'Content-Type': 'text/html'}

    def get(self, group_name):
        try:
            group = hearts.Group(group_name)
        except Exception as e:
            LOGGER.error(e)
            template = render_template('404.html', error="Group {} not found".format(group_name))
            return make_response(template, 404, self.header)
        group.calculate_scoreboard()
        group.calculate_point_breakdown_day()

        template = render_template('hearts_group.html', group_name=group.name,
                                   scoreboard=group.get_scoreboard(),
                                   player_1=group.get_players()[0],
                                   player_2=group.get_players()[1],
                                   player_3=group.get_players()[2],
                                   player_4=group.get_players()[3],
                                   results=group.point_breakdown_day,
                                   addurl=url_for('heartsgame', group_name=group_name)
                                   )
        return make_response(template, 200, self.header)


from src.utils.helpers import read_json, write_json
from src.utils.base_imports import *
from src.services.LogService import SpecificLog

from src import models as Entity

Logger = SpecificLog(__name__)

if typing.TYPE_CHECKING:
    from src.classes.NightmareFever import NightmareLotus

JsonConfig = read_json("EconomyConfig.json")

class Economy(Extension):
    JobsAvailable = ["example"]

    def __init__(self, bot: AutoShardedBot):
        self.bot = bot

    def UserBanned(_: any = None):
        async def predicate(ctx: BridgeExtContext):
            user = await Entity.User.find_one(Entity.User.dn_id == str(ctx.author.id))
            if (user):
                if (user.disabled):
                    return False
            return True

        return commands.check(predicate)

    def RegisteredAuthor(_: any = None):
        async def predicate(ctx: BridgeExtContext):
            return True
            user = await Entity.User.find_one(Entity.User.dn_id == str(ctx.author.id))
            if (user):
                return True
            raise ValueError

        return commands.check(predicate)

    async def dig_values(self):
        items = (
            random.randrange(0, 300),
            random.randrange(300, 500),
            random.randrange(500, 1000),
            random.randrange(1000, 3800)
        )
        probabilities = [
            0.60,
            0.25,
            0.14,
            0.01
        ]
        return numpy.random.choice(items, p=probabilities)

    async def level_check(self, level):
        # deadtrix's fuck you over system
        partzero = 0.08 * (level ** 3)
        partone = 0.4 * (level ** 3)
        parttwo = 0.8 * (level ** 2)
        partthree = 9 * (level ** 1)
        final = round(partzero + partone + parttwo + partthree, None)
        return final

    async def handleExp(self, ctx, fromUser: Entity.User):
        embed = None
        work = fromUser.occupation.work
        exp = work.daily_exp
        rate = work.daily_rate
        fromUser.economy.wallet += rate
        cap = await self.level_check(fromUser.occupation.level)
        fromUser.occupation.exp += exp
        if cap <= fromUser.occupation.exp:
            fromUser.occupation.exp = fromUser.occupation.exp - cap
            fromUser.occupation.level += 1
            embed = discord.Embed(
                title=f"Level up",
                description="",
                color=0x000c30
            )
        await fromUser.occupation.save()
        return embed

    @commands.command(aliases=["dig"])
    @RegisteredAuthor()
    @UserBanned()
    @commands.guild_only()
    @commands.cooldown(1, 80, commands.BucketType.user)
    async def search(self, ctx):
        user = await  Entity.User.find_one(Entity.User.dn_id == str(ctx.author.id))
        if user == None:
            raise ValueError
        else:
            amount = await self.dig_values()
            user.economy.wallet = user.economy.wallet + int(amount)
            await user.save()
            await ctx.send(f"{ctx.author.mention} Mined {amount} gold Illegally")

    @commands.command()
    @UserBanned()
    @commands.cooldown(1, 5, commands.BucketType.user)
    async def profile(self, ctx, member: discord.Member = None):
        """
        View your profile
        """
        if (member):
            account = await Entity.User.find_one(Entity.User.dn_id == str(member.id), fetch_links=True)
        else:
            account = await Entity.User.find_one(Entity.User.dn_id == str(ctx.author.id), fetch_links=True)
        if account == None:
            raise ValueError(member)
        else:
            Embed = discord.Embed(
                title=f"Profile: {ctx.author.name if member == None else member.name}",
                description="",
                color=0x000c30
            )
            if (account):
                if account.occupation:
                    Embed.add_field(name=f"Account Level", value=f"{round(account.occupation.level)}", inline=True)
                    Embed.add_field(name=f"Account Exp", value=f"{round(account.occupation.exp)}", inline=True)
                    Embed.add_field(name=f"Exp Needed",
                                    value=f"{round(await self.level_check(account.occupation.level))}",
                                    inline=True)
                    Embed.add_field(name=f"Net Worth:", value=f" ", inline=False)
                Embed.add_field(name=f"Bank Account", value=f"{account.economy.bank}", inline=True)
                Embed.add_field(name=f"Wallet", value=f"{account.economy.wallet}", inline=True)
            await ctx.send(embed=Embed)

    @commands.command(aliases=["give"])
    @RegisteredAuthor()
    @UserBanned()
    @commands.cooldown(1, 25, commands.BucketType.user)
    async def pay(self, ctx, value: int, Member: discord.Member):
        """ Pay or Give people money
        """
        fromUser = await  Entity.User.find_one(Entity.User.dn_id == str(ctx.author.id))
        toUser = await  Entity.User.find_one(Entity.User.dn_id == str(Member.id))

        if toUser == None:
            raise ValueError(Member)
        else:
            if (value > fromUser.economy.wallet):
                await ctx.send("Please consider withdrawing from the bank or earning more money for doing activities.")
            elif (value <= fromUser.economy.wallet):
                wallet = fromUser.economy.wallet - value
                await fromUser.set({Entity.User.economy: Entity.Economy(wallet=wallet, bank=fromUser.economy.bank)})
                await toUser.set(
                    {Entity.User.economy: Entity.Economy(wallet=toUser.economy.wallet + value,
                                                         bank=toUser.economy.bank)})
                await ctx.send(f"{ctx.author.mention} payed {value} to {Member.mention}")

    @commands.command(aliases=["dep"])
    @RegisteredAuthor()
    @UserBanned()
    @commands.cooldown(1, 120, commands.BucketType.user)
    async def deposit(self, ctx, amount: int):
        """Deposit money into the bank (must be 5000 or more)
        """
        fromUser = await  Entity.User.find_one(Entity.User.dn_id == str(ctx.author.id))
        if (amount > fromUser.economy.wallet):
            await ctx.send("Please consider withdrawing from the bank or earning more money for doing activities.")
        elif (amount <= fromUser.economy.wallet and amount >= 5000):
            wallet = fromUser.economy.wallet - amount
            bank = fromUser.economy.bank + amount
            await fromUser.set({Entity.User.economy: Entity.Economy(wallet=wallet, bank=bank)})
            await ctx.send(f"{ctx.author.mention} deposited {amount} money into their account")

    @commands.command(aliases=["with"])
    @RegisteredAuthor()
    @UserBanned()
    @commands.cooldown(1, 120, commands.BucketType.user)
    async def withdraw(self, ctx, amount: int):
        """Withdraw money from the bank
        """
        fromUser = await  Entity.User.find_one(Entity.User.dn_id == str(ctx.author.id))
        if (amount > fromUser.economy.bank):
            await ctx.send("Please consider depositing into the bank or earning more money for doing activities.")
        else:
            wallet = fromUser.economy.wallet + amount
            bank = fromUser.economy.bank - amount
            await fromUser.set({Entity.User.economy: Entity.Economy(wallet=wallet, bank=bank)})
            await ctx.send(f"{ctx.author.mention} withdrew {amount} money out of their account")

    @commands.command(aliases=["register-tax"])
    @RegisteredAuthor()
    @UserBanned()
    async def tax(self, ctx):
        """Register for tax
        """
        fromUser = await  Entity.User.find_one(Entity.User.dn_id == str(ctx.author.id))
        if fromUser.occupation:
            raise ValueError()
        else:
            occupation = Entity.Occupation(level=0, exp=0, last_work_day="")
            await occupation.save()
            fromUser.occupation = occupation;
            await fromUser.save()
            await ctx.send("Registered for tax.")

    @bridge_command(description=JsonConfig["intern-jobs-des"])
    @RegisteredAuthor()
    @UserBanned()
    @discord.option(name="internship", choices=JsonConfig["intern-jobs"])
    async def internship(self, ctx: BridgeContext, *, internship: str = "None"):
        fromUser = await  Entity.User.find_one(Entity.User.dn_id == str(ctx.author.id), fetch_links=True)
        if fromUser.occupation == None:
            raise ValueError()
        elif internship == "None":
            if isinstance(ctx, BridgeExtContext):
                return await ctx.send(f"Internship cannot be none")
            elif isinstance(ctx, BridgeApplicationContext):
                return await ctx.respond(f"Internship cannot be none")
        else:
            work = await  Entity.Work.find_one(Entity.Work.name == internship)
            occupation = fromUser.occupation
            if occupation.level >= work.level:
                occupation.work = work
                await occupation.save()
                if isinstance(ctx, BridgeExtContext):
                    await ctx.send(f"{ctx.author.mention} you have applied and been accepted as an {internship}")
                elif isinstance(ctx, BridgeApplicationContext):
                    await ctx.respond(f"{ctx.author.mention} you have applied and been accepted as an {internship}")
            else:
                if isinstance(ctx, BridgeExtContext):
                    await ctx.send(f"{ctx.author.mention} your level is to low to apply for {internship}")
                elif isinstance(ctx, BridgeApplicationContext):
                    await ctx.respond(f"{ctx.author.mention} your level is to low to apply for {internship}")

    @bridge_command()
    @RegisteredAuthor()
    @UserBanned()
    @commands.cooldown(1, 43200, commands.BucketType.user)
    async def work(self, ctx: BridgeContext):
        fromUser = await  Entity.User.find_one(Entity.User.dn_id == str(ctx.author.id), fetch_links=True)
        if fromUser.occupation == None:
            raise ValueError()
        emb = await self.handleExp(ctx, fromUser)
        await fromUser.save()
        if isinstance(ctx, BridgeExtContext):
            await ctx.send(
                f"{ctx.author.mention} you have earned {fromUser.occupation.work.daily_rate} gold for today.",
                embed=emb)
        elif isinstance(ctx, BridgeApplicationContext):
            await ctx.respond(
                f"{ctx.author.mention} you have earned {fromUser.occupation.work.daily_rate} gold for today.",
                embed=emb)

def setup(bot):
    cog = Economy(bot)
    bot.add_cog(cog)