# -*- coding: utf-8 -*-

from __future__ import print_function

import collections
from datetime import datetime
import heapq
import time

import requests

from .._protos.public.modeldb.versioning import VersioningService_pb2 as _VersioningService

from ..external import six

from .._internal_utils import _utils
from .. import code
from .. import configuration
from .. import dataset
from .. import environment
from . import blob as blob_module
from . import diff as diff_module

class Commit(object):
    """
    Commit within a ModelDB Repository.

    There should not be a need to instantiate this class directly; please use
    :meth:`Repository.get_commit() <verta._repository.Repository.get_commit>`.

    Attributes
    ----------
    id : str or None
        ID of the Commit, or ``None`` if the Commit has not yet been saved.

    """
    def __init__(self, conn, repo, commit_msg, branch_name=None):
        self._conn = conn
        self._commit_json = _utils.proto_to_json(commit_msg)  # dict representation of Commit protobuf

        self._repo = repo
        self._parent_ids = list(collections.OrderedDict.fromkeys(commit_msg.parent_shas or []))  # remove duplicates while maintaining order

        self.branch_name = branch_name  # TODO: find a way to clear if branch is moved

        self._blobs = dict()  # will be loaded when needed
        self._loaded_from_remote = False

    @property
    def id(self):
        return self._commit_json['commit_sha'] or None

    @property
    def parent(self):
        return self._repo.get_commit(id=self._parent_ids[0]) if self._parent_ids else None

    def _lazy_load_blobs(self):
        if self._loaded_from_remote:
            return

        # until Commits can be created from blob diffs, load in blobs
        if self.id is not None:
            self._update_blobs_from_commit(self.id)
        else:
            for parent_id in self._parent_ids:
                # parents will be read in first-to-last, possibly overwriting previous blobs
                self._update_blobs_from_commit(parent_id)

        self._loaded_from_remote = True

    def describe(self):
        self._lazy_load_blobs()

        contents = '\n'.join((
            "{} ({}.{})".format(path, blob.__class__.__module__.split('.')[1], blob.__class__.__name__)
            for path, blob
            in sorted(six.viewitems(self._blobs))
        ))
        if not contents:
            contents = "<no contents>"

        components = [self.__repr__(), 'Contents:', contents]
        return '\n'.join(components)

    def __repr__(self):
        branch_and_tag = ' '.join((
            "Branch: {}".format(self.branch_name) if self.branch_name is not None else '',
            # TODO: put tag here
        ))
        if self.id is None:
            header = "unsaved Commit"
            if branch_and_tag:
                header = header +  " (was {})".format(branch_and_tag)
        else:
            header = "Commit {}".format(self.id)
            if branch_and_tag:
                header = header +  " ({})".format(branch_and_tag)

        # TODO: add author
        # TODO: make data more similar to git
        date_created = int(self._commit_json['date_created'])  # protobuf uint64 is str, so cast to int
        date = 'Date: ' + datetime.fromtimestamp(date_created/1000.).strftime('%Y-%m-%d %H:%M:%S')
        message = '\n'.join('    ' + c for c in self._commit_json['message'].split('\n'))
        components = [header, date, '', message, '']
        return '\n'.join(components)

    @classmethod
    def _from_id(cls, conn, repo, id_, **kwargs):
        endpoint = "{}://{}/api/v1/modeldb/versioning/repositories/{}/commits/{}".format(
            conn.scheme,
            conn.socket,
            repo.id,
            id_,
        )
        response = _utils.make_request("GET", endpoint, conn)
        _utils.raise_for_http_error(response)

        response_msg = _utils.json_to_proto(_utils.body_to_json(response),
                                            _VersioningService.GetCommitRequest.Response)
        commit_msg = response_msg.commit
        return cls(conn, repo, commit_msg, **kwargs)

    @staticmethod
    def _raise_lookup_error(path):
        e = LookupError("Commit does not contain path \"{}\"".format(path))
        six.raise_from(e, None)

    # TODO: consolidate this with similar method in `_ModelDBEntity`
    def _get_url_for_artifact(self, blob_path, dataset_component_path, method, part_num=0):
        """
        Obtains a URL to use for accessing stored artifacts.

        Parameters
        ----------
        blob_path : str
            Path to blob within repo.
        dataset_component_path : str
            Filepath in dataset component blob.
        method : {'GET', 'PUT'}
            HTTP method to request for the generated URL.
        part_num : int, optional
            If using Multipart Upload, number of part to be uploaded.

        Returns
        -------
        response_msg : `_VersioningService.GetUrlForBlobVersioned.Response`
            Backend response.

        """
        if method.upper() not in ("GET", "PUT"):
            raise ValueError("`method` must be one of {'GET', 'PUT'}")

        Message = _VersioningService.GetUrlForBlobVersioned
        msg = Message(
            location=path_to_location(blob_path),
            path_dataset_component_blob_path=dataset_component_path,
            method=method,
            part_number=part_num,
        )
        data = _utils.proto_to_json(msg)
        endpoint = "{}://{}/api/v1/modeldb/versioning/repositories/{}/commits/{}/getUrlForBlobVersioned".format(
            self._conn.scheme,
            self._conn.socket,
            self._repo.id,
            self.id,
        )
        response = _utils.make_request("POST", endpoint, self._conn, json=data)
        _utils.raise_for_http_error(response)

        response_msg = _utils.json_to_proto(response.json(), Message.Response)

        url = response_msg.url
        # accommodate port-forwarded NFS store
        if 'https://localhost' in url[:20]:
            url = 'http' + url[5:]
        if 'localhost%3a' in url[:20]:
            url = url.replace('localhost%3a', 'localhost:')
        if 'localhost%3A' in url[:20]:
            url = url.replace('localhost%3A', 'localhost:')
        response_msg.url = url

        return response_msg

    # TODO: consolidate this with similar method in `ExperimentRun`
    def _upload_artifact(self, blob_path, dataset_component_path, file_handle, part_size=64*(10**6)):
        """
        Uploads `file_handle` to ModelDB artifact store.

        Parameters
        ----------
        blob_path : str
            Path to blob within repo.
        dataset_component_path : str
            Filepath in dataset component blob.
        file_handle : file-like
            Artifact to be uploaded.
        part_size : int, default 64 MB
            If using multipart upload, number of bytes to upload per part.

        """
        file_handle.seek(0)

        # check if multipart upload ok
        url_for_artifact = self._get_url_for_artifact(blob_path, dataset_component_path, "PUT", part_num=1)

        print("uploading {} to ModelDB".format(dataset_component_path))
        if url_for_artifact.multipart_upload_ok:
            # TODO: parallelize this
            file_parts = iter(lambda: file_handle.read(part_size), b'')
            for part_num, file_part in enumerate(file_parts, start=1):
                print("uploading part {}".format(part_num), end='\r')

                # get presigned URL
                url = self._get_url_for_artifact(blob_path, dataset_component_path, "PUT", part_num=part_num).url

                # wrap file part into bytestream to avoid OverflowError
                #     Passing a bytestring >2 GB (num bytes > max val of int32) directly to
                #     ``requests`` will overwhelm CPython's SSL lib when it tries to sign the
                #     payload. But passing a buffered bytestream instead of the raw bytestring
                #     indicates to ``requests`` that it should perform a streaming upload via
                #     HTTP/1.1 chunked transfer encoding and avoid this issue.
                #     https://github.com/psf/requests/issues/2717
                part_stream = six.BytesIO(file_part)

                # upload part
                response = _utils.make_request("PUT", url, self._conn, data=part_stream)
                _utils.raise_for_http_error(response)

                # commit part
                url = "{}://{}/api/v1/modeldb/versioning/commitVersionedBlobArtifactPart".format(
                    self._conn.scheme,
                    self._conn.socket,
                )
                msg = _VersioningService.CommitVersionedBlobArtifactPart(
                    commit_sha=self.id,
                    location=path_to_location(blob_path),
                    path_dataset_component_blob_path=dataset_component_path,
                )
                msg.repository_id.repo_id = self._repo.id
                msg.artifact_part.part_number = part_num
                msg.artifact_part.etag = response.headers['ETag']
                data = _utils.proto_to_json(msg)
                response = _utils.make_request("POST", url, self._conn, json=data)
                _utils.raise_for_http_error(response)
            print()

            # complete upload
            url = "{}://{}/api/v1/modeldb/versioning/commitMultipartVersionedBlobArtifact".format(
                self._conn.scheme,
                self._conn.socket,
            )
            msg = _VersioningService.CommitMultipartVersionedBlobArtifact(
                commit_sha=self.id,
                location=path_to_location(blob_path),
                path_dataset_component_blob_path=dataset_component_path,
            )
            msg.repository_id.repo_id = self._repo.id
            data = _utils.proto_to_json(msg)
            response = _utils.make_request("POST", url, self._conn, json=data)
            _utils.raise_for_http_error(response)
        else:
            # upload full artifact
            response = _utils.make_request("PUT", url_for_artifact.url, self._conn, data=file_handle)
            _utils.raise_for_http_error(response)

        print("upload complete")

    def _update_blobs_from_commit(self, id_):
        """Fetches commit `id_`'s blobs and stores them as objects in `self._blobs`."""
        endpoint = "{}://{}/api/v1/modeldb/versioning/repositories/{}/commits/{}/blobs".format(
            self._conn.scheme,
            self._conn.socket,
            self._repo.id,
            id_,
        )
        response = _utils.make_request("GET", endpoint, self._conn)
        _utils.raise_for_http_error(response)

        response_msg = _utils.json_to_proto(_utils.body_to_json(response),
                                            _VersioningService.ListCommitBlobsRequest.Response)
        self._blobs.update({
            '/'.join(blob_msg.location): blob_msg_to_object(blob_msg.blob)
            for blob_msg
            in response_msg.blobs
        })

    def _become_child(self):
        """
        This method is for when `self` had been saved and is then modified, meaning that
        this commit object has become a child of the commit that had been saved.

        """
        self._lazy_load_blobs()
        self._parent_ids = [self.id]
        self._commit_json['commit_sha'] = ""

    def _become_saved_child(self, child_id):
        """
        This method is for when a child commit is created in the back end from `self`, and `self`
        and its branch need to be updated to become that newly-created commit.

        """
        if self.branch_name is not None:
            # update branch to child commit
            set_branch(self._conn, self._repo.id, child_id, self.branch_name)
            new_commit = self._repo.get_commit(branch=self.branch_name)
        else:
            new_commit = self._repo.get_commit(id=child_id)

        self.__dict__ = new_commit.__dict__

    def _to_create_msg(self, commit_message):
        self._lazy_load_blobs()

        msg = _VersioningService.CreateCommitRequest()
        msg.repository_id.repo_id = self._repo.id  # pylint: disable=no-member
        msg.commit.parent_shas.extend(self._parent_ids)  # pylint: disable=no-member
        msg.commit.message = commit_message

        for path, blob in six.viewitems(self._blobs):
            blob_msg = _VersioningService.BlobExpanded()
            blob_msg.location.extend(path_to_location(path))  # pylint: disable=no-member
            blob_msg.blob.CopyFrom(blob._as_proto())
            msg.blobs.append(blob_msg)  # pylint: disable=no-member

        return msg

    def walk(self):
        """
        Generates folder names and blob names in this commit by walking through its folder tree.

        Similar to the Python standard library's ``os.walk()``, the yielded `folder_names` can be
        modified in-place to remove subfolders from upcoming iterations or alter the order in which
        they are to be visited.

        Note that, also similar to ``os.walk()``, `folder_names` and `blob_names` are simply the
        *names* of those entities, and *not* their full paths.

        Yields
        ------
        folder_path : str
            Path to current folder.
        folder_names : list of str
            Names of subfolders in `folder_path`.
        blob_names : list of str
            Names of blobs in `folder_path`.

        """
        if self.id is None:
            raise RuntimeError("Commit must be saved before it can be walked")

        endpoint = "{}://{}/api/v1/modeldb/versioning/repositories/{}/commits/{}/path".format(
            self._conn.scheme,
            self._conn.socket,
            self._repo.id,
            self.id,
        )

        locations = [()]
        while locations:
            location = locations.pop()

            msg = _VersioningService.GetCommitComponentRequest()
            msg.location.extend(location)  # pylint: disable=no-member
            data = _utils.proto_to_json(msg)
            response = _utils.make_request("GET", endpoint, self._conn, params=data)
            _utils.raise_for_http_error(response)

            response_msg = _utils.json_to_proto(_utils.body_to_json(response), msg.Response)
            folder_msg = response_msg.folder

            folder_path = '/'.join(location)
            folder_names = list(sorted(element.element_name for element in folder_msg.sub_folders))
            blob_names = list(sorted(element.element_name for element in folder_msg.blobs))
            yield (folder_path, folder_names, blob_names)

            locations.extend(
                location + (folder_name,)
                for folder_name
                in reversed(folder_names)  # maintains order, because locations are popped from end
            )

    def update(self, path, blob):
        """
        Adds `blob` to this Commit at `path`.

        If `path` is already in this Commit, it will be updated to the new `blob`.

        Parameters
        ----------
        path : str
            Location to add `blob` to.
        blob : :ref:`Blob <blobs>`
            ModelDB versioning blob.

        """
        if not isinstance(blob, blob_module.Blob):
            raise TypeError("unsupported type {}".format(type(blob)))

        self._lazy_load_blobs()

        if self.id is not None:
            self._become_child()

        self._blobs[path] = blob

    def get(self, path):
        """
        Retrieves the blob at `path` from this Commit.

        Parameters
        ----------
        path : str
            Location of a blob.

        Returns
        -------
        blob : :ref:`Blob <blobs>`
            ModelDB versioning blob.

        Raises
        ------
        LookupError
            If `path` is not in this Commit.

        """
        self._lazy_load_blobs()

        try:
            blob = self._blobs[path]
        except KeyError:
            self._raise_lookup_error(path)

        if isinstance(blob, dataset._Dataset):
            # for _Dataset.download()
            blob._set_commit_and_blob_path(self, path)

        return blob

    def remove(self, path):
        """
        Deletes the blob at `path` from this Commit.

        Parameters
        ----------
        path : str
            Location of a blob.

        Raises
        ------
        LookupError
            If `path` is not in this Commit.

        """
        self._lazy_load_blobs()

        if self.id is not None:
            self._become_child()

        try:
            del self._blobs[path]
        except KeyError:
            self._raise_lookup_error(path)

    def save(self, message):
        """
        Saves this commit to ModelDB.

        .. note::

            If this commit contains new S3 datasets to be versioned by ModelDB, a very large
            temporary download may occur before uploading them to ModelDB.

        Parameters
        ----------
        message : str
            Description of this Commit.

        """
        # prepare ModelDB-versioned blobs, and track for upload after commit save
        mdb_versioned_blobs = dict()
        for blob_path, blob in self._blobs.items():
            if isinstance(blob, dataset._Dataset) and blob._mdb_versioned:
                blob._prepare_components_to_upload()
                mdb_versioned_blobs[blob_path] = blob

        msg = self._to_create_msg(commit_message=message)
        self._save(msg)

        # upload ModelDB-versioned blobs
        for blob_path, blob in mdb_versioned_blobs.items():
            for component in blob._components_map.values():
                if component._internal_versioned_path:
                    with open(component._local_path, 'rb') as f:
                        self._upload_artifact(blob_path, component.path, f)

            blob._clean_up_uploaded_components()

    def _save(self, proto_message):
        data = _utils.proto_to_json(proto_message)
        endpoint = "{}://{}/api/v1/modeldb/versioning/repositories/{}/commits".format(
            self._conn.scheme,
            self._conn.socket,
            self._repo.id,
        )
        response = _utils.make_request("POST", endpoint, self._conn, json=data)
        _utils.raise_for_http_error(response)
        response_msg = _utils.json_to_proto(_utils.body_to_json(response), proto_message.Response)

        self._become_saved_child(response_msg.commit.commit_sha)

    # TODO: Add ways to retrieve and delete tag
    def tag(self, tag):
        """
        Assigns a tag to this Commit.

        Parameters
        ----------
        tag : str
            Tag.

        Raises
        ------
        RuntimeError
            If this Commit has not yet been saved.

        """
        if self.id is None:
            raise RuntimeError("Commit must be saved before it can be tagged")

        data = self.id
        endpoint = "{}://{}/api/v1/modeldb/versioning/repositories/{}/tags/{}".format(
            self._conn.scheme,
            self._conn.socket,
            self._repo.id,
            tag,
        )
        response = _utils.make_request("PUT", endpoint, self._conn, json=data)
        _utils.raise_for_http_error(response)

    def log(self):
        """
        Yields ancestors, starting from this Commit until the root of the Repository.

        Analogous to ``git log``.

        Yields
        ------
        commit : :class:`Commit`
            Ancestor commit.

        """
        if self.id is None:  # unsaved commit
            # use parent
            commit_id = self._parent_ids[0]
        else:
            commit_id = self.id

        endpoint = "{}://{}/api/v1/modeldb/versioning/repositories/{}/commits/{}/log".format(
            self._conn.scheme,
            self._conn.socket,
            self._repo.id,
            commit_id,
        )
        response = _utils.make_request("GET", endpoint, self._conn)
        _utils.raise_for_http_error(response)

        response_msg = _utils.json_to_proto(_utils.body_to_json(response),
                                            _VersioningService.ListCommitsLogRequest.Response)
        commits = response_msg.commits

        for c in commits:
            yield Commit(self._conn, self._repo, c, self.branch_name if c.commit_sha == commit_id else None)

    def new_branch(self, branch):
        """
        Creates a branch at this Commit and returns the checked-out branch.

        If `branch` already exists, it will be moved to this Commit.

        Parameters
        ----------
        branch : str
            Branch name.

        Returns
        -------
        commit : :class:`Commit`
            This Commit as the head of `branch`.

        Raises
        ------
        RuntimeError
            If this Commit has not yet been saved.

        Examples
        --------
        .. code-block:: python

            master = repo.get_commit(branch="master")
            dev = master.new_branch("development")

        """
        if self.id is None:
            raise RuntimeError("Commit must be saved before it can be attached to a branch")

        set_branch(self._conn, self._repo.id, self.id, branch)

        return self._repo.get_commit(branch=branch)

    def diff_from(self, reference=None):
        """
        Returns the diff from `reference` to `self`.

        Parameters
        ----------
        reference : :class:`Commit`, optional
            Commit to be compared to.

        Returns
        -------
        :class:`~verta._repository.diff.Diff`
            Commit diff.

        Raises
        ------
        RuntimeError
            If this Commit or `reference` has not yet been saved, or if they do not belong to the
            same Repository.

        """
        if self.id is None:
            raise RuntimeError("Commit must be saved before a diff can be calculated")

        if reference is None:
            reference_id = self._parent_ids[0]
        elif not isinstance(reference, Commit) or reference.id is None:
            raise TypeError("`reference` must be a saved Commit")
        elif self._repo.id != reference._repo.id:
            raise ValueError("Commit and `reference` must belong to the same Repository")
        else:
            reference_id = reference.id

        endpoint = "{}://{}/api/v1/modeldb/versioning/repositories/{}/diff?commit_a={}&commit_b={}".format(
            self._conn.scheme,
            self._conn.socket,
            self._repo.id,
            reference_id,
            self.id,
        )
        response = _utils.make_request("GET", endpoint, self._conn)
        _utils.raise_for_http_error(response)

        response_msg = _utils.json_to_proto(_utils.body_to_json(response),
                                            _VersioningService.ComputeRepositoryDiffRequest.Response)
        return diff_module.Diff(response_msg.diffs)

    def apply_diff(self, diff, message, other_parents=[]):
        """
        Applies a diff to this Commit.

        This method creates a new Commit in ModelDB, and assigns a new ID to this object.

        Parameters
        ----------
        diff : :class:`~verta._repository.diff.Diff`
            Commit diff.
        message : str
            Description of the diff.

        Raises
        ------
        RuntimeError
            If this Commit has not yet been saved.

        """
        if self.id is None:
            raise RuntimeError("Commit must be saved before a diff can be applied")

        msg = _VersioningService.CreateCommitRequest()
        msg.repository_id.repo_id = self._repo.id
        msg.commit.parent_shas.append(self.id)
        msg.commit.parent_shas.extend(other_parents)
        msg.commit.message = message
        msg.commit_base = self.id
        msg.diffs.extend(diff._diffs)

        self._save(msg)

    def get_revert_diff(self):
        return self.parent.diff_from(self)

    def revert(self, other=None, message=None):
        """
        Reverts `other`.

        This method creates a new Commit in ModelDB, and assigns a new ID to this object.

        Parameters
        ----------
        other : :class:`Commit`, optional
            Commit to be reverted. If not provided, this Commit will be reverted.
        message : str, optional
            Description of the revert. If not provided, a default message will be used.

        Raises
        ------
        RuntimeError
            If this Commit or `other` has not yet been saved, or if they do not belong to the
            same Repository.

        """
        if self.id is None:
            raise RuntimeError("Commit must be saved before a revert can be performed")

        if other is None:
            other = self
        elif not isinstance(other, Commit) or other.id is None:
            raise TypeError("`other` must be a saved Commit")
        elif self._repo.id != other._repo.id:
            raise ValueError("Commit and `other` must belong to the same Repository")

        msg = _VersioningService.RevertRepositoryCommitsRequest()
        msg.base_commit_sha = self.id
        msg.commit_to_revert_sha = other.id
        if message is not None:
            msg.content.message = message

        data = _utils.proto_to_json(msg)
        endpoint = "{}://{}/api/v1/modeldb/versioning/repositories/{}/commits/{}/revert".format(
            self._conn.scheme,
            self._conn.socket,
            self._repo.id,
            msg.commit_to_revert_sha,
        )
        response = _utils.make_request("POST", endpoint, self._conn, json=data)
        _utils.raise_for_http_error(response)
        response_msg = _utils.json_to_proto(_utils.body_to_json(response), msg.Response)

        self._become_saved_child(response_msg.commit.commit_sha)

    def _to_heap_element(self):
        date_created = int(self._commit_json['date_created'])  # protobuf uint64 is str, so cast to int
        # Most recent has higher priority
        return (-date_created, self.id, self)

    def get_common_parent(self, other):
        if self.id is None:
            raise RuntimeError("Commit must be saved before a common parent can be calculated")

        if not isinstance(other, Commit) or other.id is None:
            raise TypeError("`other` must be a saved Commit")
        elif self._repo.id != other._repo.id:
            raise ValueError("Commit and `other` must belong to the same Repository")

        # Keep a set of all parents we see for each side. This doesn't have to be *all* but facilitates implementation
        left_ids = set([self.id])
        right_ids = set([other.id])

        # Keep a heap of all candidate commits to be the common parent, ordered by the date so that we fetch the most recent first
        heap = []
        heapq.heappush(heap, self._to_heap_element())
        heapq.heappush(heap, other._to_heap_element())

        while heap:
            # Get the most recent commit
            _, _, commit = heapq.heappop(heap)

            # If it's in the list for both sides, then it's a parent of both and return
            if commit.id in left_ids and commit.id in right_ids:
                return commit

            # Update the heap with all the current parents
            parent_ids = commit._parent_ids
            for parent_id in parent_ids:
                parent_commit = self._repo.get_commit(id=parent_id)
                heap_element = parent_commit._to_heap_element()
                try:
                    heapq.heappush(heap, heap_element)
                except TypeError:  # already in heap, because comparison between Commits failed
                    pass

            # Update the parent sets based on which side the commit came from
            # We know the commit came from the left if its ID is in the left set. If it was on the right too, then it would be the parent and we would have returned early
            if commit.id in left_ids:
                left_ids.update(parent_ids)
            if commit.id in right_ids:
                right_ids.update(parent_ids)

        # Should never happen, since we have the initial commit
        return None

    def merge(self, other, message=None):
        """
        Merges a branch headed by `other` into this Commit.

        This method creates a new Commit in ModelDB, and assigns a new ID to this object.

        Parameters
        ----------
        other : :class:`Commit`
            Commit to be merged.
        message : str, optional
            Description of the merge. If not provided, a default message will be used.

        Raises
        ------
        RuntimeError
            If this Commit or `other` has not yet been saved, or if they do not belong to the
            same Repository.

        """
        if self.id is None:
            raise RuntimeError("Commit must be saved before a merge can be performed")

        if not isinstance(other, Commit) or other.id is None:
            raise TypeError("`other` must be a saved Commit")
        elif self._repo.id != other._repo.id:
            raise ValueError("Commit and `other` must belong to the same Repository")

        msg = _VersioningService.MergeRepositoryCommitsRequest()
        if self.branch_name is not None:
            msg.branch_b = self.branch_name
        else:
            msg.commit_sha_b = self.id
        if other.branch_name is not None:
            msg.branch_a = other.branch_name
        else:
            msg.commit_sha_a = other.id
        if message is not None:
            msg.content.message = message

        data = _utils.proto_to_json(msg)
        endpoint = "{}://{}/api/v1/modeldb/versioning/repositories/{}/merge".format(
            self._conn.scheme,
            self._conn.socket,
            self._repo.id,
        )
        response = _utils.make_request("POST", endpoint, self._conn, json=data)
        _utils.raise_for_http_error(response)
        response_msg = _utils.json_to_proto(_utils.body_to_json(response), msg.Response)

        # raise for conflict
        if response_msg.conflicts:
            raise RuntimeError('\n    '.join([
                "merge conflict",
                "resolution is not currently supported through the Client",
                "please create a new Commit with the updated blobs",
                "see https://docs.verta.ai/en/master/examples/tutorials/merge.html for instructions",
            ]))

        self._become_saved_child(response_msg.commit.commit_sha)

def blob_msg_to_object(blob_msg):
    # TODO: make this more concise
    content_type = blob_msg.WhichOneof('content')
    content_subtype = None
    blob_cls = None
    if content_type == 'code':
        content_subtype = blob_msg.code.WhichOneof('content')
        if content_subtype == 'git':
            blob_cls = code.Git
        elif content_subtype == 'notebook':
            blob_cls = code.Notebook
    elif content_type == 'config':
        blob_cls = configuration.Hyperparameters
    elif content_type == 'dataset':
        content_subtype = blob_msg.dataset.WhichOneof('content')
        if content_subtype == 's3':
            blob_cls = dataset.S3
        elif content_subtype == 'path':
            blob_cls = dataset.Path
    elif content_type == 'environment':
        content_subtype = blob_msg.environment.WhichOneof('content')
        if content_subtype == 'python':
            blob_cls = environment.Python
        elif content_subtype == 'docker':
            raise NotImplementedError

    if blob_cls is None:
        if content_subtype is None:
            raise NotImplementedError("found unexpected content type {};"
                                      " please notify the Verta development team".format(content_type))
        else:
            raise NotImplementedError("found unexpected {} type {};"
                                      " please notify the Verta development team".format(content_type, content_subtype))

    return blob_cls._from_proto(blob_msg)

def path_to_location(path):
    """Messages take a `repeated string` of path components."""
    if path.startswith('/'):
        # `path` is already meant to be relative to repo root
        path = path[1:]

    return path.split('/')

def location_to_path(location):
    return '/'.join(location)

def set_branch(conn, repo_id, commit_id, branch):
    """Sets `branch` to Commit `commit_id`."""
    data = commit_id
    endpoint = "{}://{}/api/v1/modeldb/versioning/repositories/{}/branches/{}".format(
        conn.scheme,
        conn.socket,
        repo_id,
        branch,
    )
    response = _utils.make_request("PUT", endpoint, conn, json=data)
    _utils.raise_for_http_error(response)


# -*- coding: utf-8 -*-
"""A class to clean the dataset."""
import re
from datetime import datetime

class BaselinerClean:
    def __init__(
            self, num_atleast_rating, size_subset,
            date_from, date_to, domain_label):
        """initialize  parameter.
        Args:
            num_atleast_rating:
                For each user, it rated at least 'num_atleast_rating' items.
            size_subset:
                The number of observation we want to choose.
            date_from:
                The starting date of ratings.
            date_to:
                The end date of ratings.
            domain_label:
                Add a domain label to the original dataset.
        """
        self.num_atleast_rating = num_atleast_rating
        self.size_subset = size_subset
        self.period = range(date_from, date_to + 1)
        self.label = domain_label

    def parse_time(self, s):
        """convert unix timestamp to readable date.
        Args:
            s: unix timestamp (string)
        Returns:
            datetime
        """
        return datetime.fromtimestamp(float(s))

    def parse_line(self, iterators):
        """parse a line.
        Args:
            iterators: data in lines with format: 'uid, iid, rating, datetime'.
        Returns:
            (uid, [iid + domain_label, rating, datetime])
        """
        for line in iterators:
            splitted_line = re.split('\\s+', line)
            parsed_time = self.parse_time(splitted_line[3])
            if parsed_time.year in self.period:
                yield (
                    splitted_line[0], (
                        splitted_line[1] + self.label,
                        float(splitted_line[2]), parsed_time))

    def parse_data(self, originalRDD):
        """parse the dataset."""
        return originalRDD.mapPartitions(self.parse_line)

    def take_partial_data(self, dataRDD):
        """take partial data to do the computation."""
        return dataRDD.take(self.size_subset)

    def remove_invalid(self, iterators):
        """remove invalid rating, e.g., old or duplicate.
        iterators is a set of line in the form of [uid, (iid, rating, time)*].
        """
        def check_invalid(line, tmpdict):
            """check data and update invalid data.
            e.g., we only use latest data.
            """
            iid, rating, time = line
            if time > tmpdict[iid][2]:
                tmpdict[iid] = line
            return tmpdict

        for uid, ratings in iterators:
            tmpdict = {}
            for token in ratings:
                # token: in the form of (iid, rating, time)
                if token[0] in tmpdict.keys():
                    tmpdict = check_invalid(token, tmpdict)
                else:
                    tmpdict[token[0]] = token
            yield uid, list(tmpdict.values())

    def filter_data(self, dataRDD):
        """filter the invalid data.
        e.g., 1. duplicate data; 2. same uid, iid, but with different rating.
        """
        seq_op = (lambda a, b: a + [b])
        comb_op = (lambda a, b: a + b)
        groupedRDD = dataRDD.aggregateByKey([], seq_op, comb_op)
        return groupedRDD.mapPartitions(self.remove_invalid)

    def clean_data(self, filteredRDD):
        """remove users who have low rating frequency."""
        return filteredRDD.filter(
            lambda line: len(line[1]) >= self.num_atleast_rating)


import pickle

class ContactList:

    def __init__(self):
        self.contacts = []
        try:
            f2 = open("contacts.pickle", "rb")
            from_file = f2.read()
            f2.close()
            self.contacts = pickle.loads(from_file)
        except FileNotFoundError:
            pass

    def add(self, contact):
        """As the contacts are added to the list when they are created,
        they always will be sorted by the date of creation"""
        self.contacts.append(contact)
        self.save()

    def get_contacts(self, hidden):
        "Generator to obtain contacts filtered by the hidden paramter"
        for contact in self.contacts:
            if contact.hidden == hidden:
                yield contact

    def save(self):
        """Save contacts in the file"""
        f1 = open("contacts.pickle", "wb")
        f1.write(pickle.dumps(self.contacts))
        f1.close()


import json
import sys

datoteka = sys.argv[1]
players = []
with open(datoteka, 'r') as f:
    players = (json.load(f))

#print(players)

godine = float(input())
pozicija = int(input())

visina = -1

for player in players:
    if(int(player['visina']) >= 200):
        player['pozicija'] = 5
    elif(int(player['visina']) >= 190):
        player['pozicija'] = 3
    else:
        player['pozicija'] = 1

for player in players:
    if(int(player['godine'] <= godine) and int(player['pozicija']) == pozicija and int(player['visina']) > visina):
        visina = int(player['visina'])
print(visina)


import json
cache_name = "vgmusic_downloads"
games_file = "games.json"
genres_file = "genres.json"
themes_file = "themes.json"
debug_print = True
games = None
genres = None
themes = None

# backwards compatability. This function was used back when the game database was a python dictionary :puke:
# now its a very lovely json file!
def verify():
    global games, themes, genres
    if games == None:
        with open(games_file) as file:
            games = json.loads(file.read())

#if __name__ == "__main__":
#    try:
#        verify()
#        print("This file is configured correctly!")
#    except AssertionError as e:
#        print("Failed to verify.")
#        print(str(e))


from abc import ABCMeta, abstractmethod

from lib.devices import get_metrics_names

class Connector(object):

    __metaclass__ = ABCMeta

    def __init__(self, publishers, buffer_size, step_size, device_name, device_port, device_mac=None):

      self.metrics = get_metrics_names(device_name)
      self.device = None
      self.device_port = device_port
      self.device_name = device_name
      self.device_mac = device_mac

      self.buffers = {metric: ConnectorBuffer(buffer_size, step_size, publishers[metric].publish) for metric in self.metrics}
      self.publishers = publishers

    @abstractmethod
    def connect_device(self):
      """

      :return:
      """

class ConnectorBuffer(object):

  def __init__(self, buffer_size, step_size, callback):
    self.buffer_size = buffer_size
    self.step_size = step_size
    self.callback = callback
    self.message_buffer = []

    self.count = 0

  def write(self, datum):
    """
    add one data point to the buffer

    :param datum:
    :return:
    """
    self.message_buffer.append(datum)
    self.count += 1

    # print(len(self.message_buffer), self.count, self.step_size, self.buffer_size)

    # if len(self.message_buffer) % self.buffer_size == 0:
    if self.count >= self.step_size and len(self.message_buffer) >= self.buffer_size:
      self.callback(self.message_buffer[-self.buffer_size:])
      self.message_buffer = self.message_buffer[-self.buffer_size:]
      self.count = 0


from collections import defaultdict
class Solution:
    def subarraySum(self, nums: List[int], k: int) -> int:
        d = defaultdict(lambda:0)
        d[0] =1
        s =0
        res =0
        for i in range(len(nums)):
            s+=nums[i]
            if d[s-k]>0:
                res+=d[s-k]
            d[s]+=1
        return res


from main_io import *
from filtering import *
from extraction import *

# Empty list to store the data
over_data = []
revisit = []
# Get data from Bugcrowd API
url = "https://bugcrowd.com/programs.json?page[]="
for page in range(1, 9999):
    # Add the page number to the URL
    new_url = url + str(page)
    print("Getting page " + new_url)
    # Get the data from the URL
    # If there's an error getting the data, add number
    # to revisit list and continue
    try:
        data = get_data(new_url)
    except:
        revisit.append(page)
        print("Error getting page " + str(page))
        continue
    # Filter the data and save it as a CSV file
    filtered_data = filter_data(data)
    if filtered_data is None:
        print("No more pages")
        break
    # Extend the filtered data to the list (includes flattened data)
    over_data.extend(filtered_data)
    print("Got page " + str(page))

# Save the data to a CSV file
save_as_csv(over_data, "bugcrowd_programs.csv")


import items, enemies, actions, Game, designs, Puzzle, classes, items_dagger, rangeditems
# from colorama import Fore, Back, Style

class MapTile:
  def __init__(self, x, y, name, visited=False, inspect=False):
    self.x = x
    self.y = y
    self.name = name
    self.visited = visited
    self.inspect = inspect

  def intro_text(self):
    raise NotImplementedError()

  def modify_player(self, player):
    raise NotImplementedError()

  def adjacent_moves(self):
    """Returns all move actions for adjacent tiles"""
    moves = []
    #TODO: import Game and set to Game.WORLD_CHOICE
    world_inst = Game.WORLD_CHOICE
    if world_inst.tile_exists(self.x, self.y+1):
      moves.append(actions.MoveEast())
    if world_inst.tile_exists(self.x, self.y-1):
      moves.append(actions.MoveWest())
    if world_inst.tile_exists(self.x-1, self.y):
      moves.append(actions.MoveNorth())
    if world_inst.tile_exists(self.x+1, self.y):
      moves.append(actions.MoveSouth())
    return moves

  def available_actions(self):
    """Returns all of the available actions in this room"""

    moves = self.adjacent_moves()
    moves.append(actions.ViewInventory())
    moves.append(actions.ViewMap())

    if self.inspect == True:
      moves.append(actions.Inspect())

    if type(Game.CLASS_CHOICE) == classes.Mage:
      moves.append(actions.ViewSpells())

    return moves

class StartingRoom(MapTile):
  def intro_text(self):
	# was return Fore.GREEN + ... + Style.RESET_ALl
    return """
    You are in a empty room.
    how wonderful!
    """

  def modify_player(self, player):
    #Room has not action on player
    self.visited=True
    pass

class LootRoom(MapTile):
  def __init__(self, x, y, item_f, item_x, item_a, name):
    self.item = self.choose_item(item_f, item_x, item_a)
    self.this_player = None
    super().__init__(x, y, name)
    self.item_taken = False

  def choose_item(self, f, x, a):
    if isinstance(Game.CLASS_CHOICE, classes.Assassin):
      return x
    if isinstance(Game.CLASS_CHOICE, classes.Archer):
      return a
    if isinstance(Game.CLASS_CHOICE, classes.Mage) and not isinstance(f, items.Gold):
      print("There is nothing here, move along")
      return None
    return f

  def modify_player(self, player):
    self.visited = True
    self.this_player = player
    if not self.item_taken:
      self.add_loot()
    else:
      return

  def add_loot(self):
    self.this_player.inventory.append(self.item)
    self.item_taken = True

class EnemyRoom(MapTile):
  def __init__(self, x, y, enemy, name):
    self.enemy = enemy
    self.player_facing = None
    self.inverserange = 1
    super().__init__(x, y, name)

  def run_status(self, target):
    if target.status != None:
      target.do_status()

  def modify_player(self, player):
    self.visited = True
    self.player_facing = player
    player.enemy_facing = self.enemy
    if self.enemy.is_alive():

      #status call
      self.run_status(self.enemy)
      self.run_status(player)

      #archer interaction
      if isinstance(Game.CLASS_CHOICE, classes.Archer) and (self.inverserange > 0 or self.enemy.combat_tick == 1):
        print("You see a {} from a distance".format(self.enemy.name))
        if self.enemy.combat_tick==1 or self.enemy.hot_swap:
          self.set_inverse()
        else:
          if self.enemy.combat_tick > 1:
            self.inverserange -= 1
        print("Your remaining range is: " + str(self.inverserange))

        if self.enemy.combat_tick > 1 and self.inverserange == 0:
          player.give_back_ranged()

      else:
        player.HP -= self.enemy.damage
        print("Enemy does {} damage. You have {} HP remaining.".format(self.enemy.damage, player.HP))
        print("Enemy has {} HP".format(self.enemy.HP))

    self.enemy.combat_tick += 1

  def set_inverse(self):
    self.inverserange = self.player_facing.p_range

  def available_actions(self):
    if self.enemy.is_alive():
      return [actions.Flee(tile=self), actions.Attack(enemy=self.enemy), actions.Block(enemy=self.enemy), actions.UseSkill()]
    else:
      return self.adjacent_moves()

  def __str__(self):
    return "You face a {}".format(self.enemy.name)

class EmptyCavePath(MapTile):
  def intro_text(self):
    return"""
    another bland peice of empty cave.
    """

  def modify_player(self, player):
    self.visited = True
    pass

class GiantSpiderRoom(EnemyRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, enemies.GiantSpider(), name)

  def intro_text(self):
    if self.enemy.is_alive():
      return designs.SPIDER_TEXT
    else:
      return"""
      a dead spider lays on the ground
      """

class FindDaggerRoom(LootRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, items_dagger.Dagger(), items_dagger.Dagger(), items_dagger.Dagger(), name)

  def intro_text(self):
    if not self.item_taken:
      return"""
      in the middle of this room there is a stone pedestal.
      on the pedestal you see a Dagger with a plaque in front of it.
      it reads "a Dagger".

      you got the Dagger!
      """
    else:
      return"""
      the stone pedestal is empty there is a plaque that says "a Dagger" but it is empty
      """

class FindSmallGoldRoom(LootRoom):
  def __init__(self,x, y, name):
    super().__init__(x, y, items.Gold(50), items.Gold(50), items.Gold(50), name)

  def intro_text(self):
    if not self.item_taken:
      return"""
    You see a faint glitter in the corner of the room.
    You found 50 gp!
    """
    else:
      return """
      You found the gold here already!!
      """

class OgreRoom(EnemyRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, enemies.Ogre(), name)

  def intro_text(self):
    if self.enemy.is_alive():
      return"""
      As you walk into this room you see a huge Ogre!
      """
    else:
      return"""
      as you walk into this room you see
      the rotting corpse of an Ogre.
      You are disgusted.
      """

class GoblinRoom(EnemyRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, enemies.Goblin(), name)

  def intro_text(self):
    if self.enemy.is_alive():
      return"""
      As you walk into this room you see a small little green guy you assume its a goblin, it attacks you!
      """
    else:
      return"""
      as you walk into this room you see what at first glance is a small green rock.
      You are disgusted.
      """

class QueenSpiderRoom(EnemyRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, enemies.QueenSpider(), name)

  def intro_text(self):
    if self.enemy.is_alive():
      return"""
      As you walk into this room you see a spider it looks to be very angry, it attacks you!
      """
    else:
      return"""
      as you walk into this room you see a large green blob on the floor.
      You are disgusted.
      """
class OgreLordRoom(EnemyRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, enemies.OgreLord(), name)

  def intro_text(self):
    if self.enemy.is_alive():
      return"""
      As you walk into this room you see a very lrage ogre dressed in gold, it attacks you!
      """
    else:
      return"""
      as you walk into this room you see a bunch of gold armor on the floor.
      You do want to pick it up.
      """

class KingoftheDungeonRoom(EnemyRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, enemies.KingoftheDungeon(), name)

  def intro_text(self):
    if self.enemy.is_alive():
      return"""
      As you walk into this room you see a short goblin that is dressed in kings garb it look at you mencingly, it attacks you!
      """
    else:
      return"""
      How are you reading this? you need to go into the next room to finish the game!
      """

  def modify_player(self, player):
    if self.enemy.is_alive():
      player.HP -= self.enemy.damage
      print("The Boss does {} damage. You have {} HP remaining.".format(self.enemy.damage, player.HP))
    else:
      player.victory = True

class LeaveCaveRoom(MapTile):
  def intro_text(self):
    return"""
    you won!
    """

  def modify_player(self, player):
    player.victory = True

class PuzzleRoom(MapTile):
  this_player = None

  def __init__(self, x, y, name):
    super().__init__(x, y, name)
    self.SUCCESS = False

  def intro_text(self):
    if not self.SUCCESS:
      return """\n you walk into the room and see a large red door \n it is locked.\n"""
    else:
      return """\n you walk into the room and see a large red door \n it is unlocked and open \n"""

  def modify_player(self, player):
    """BREAKING ABSTRACTION LAWS"""
    self.visited = True
    self.this_player = player

    #if we haven't won, do this process.
    if not self.SUCCESS:
      print ("guess a letter")
      guess = input("")
      print (" ")
      puzzle_inst = Puzzle.HangMan()
      puzzle_inst.start(guess, 6, [])
      self.SUCCESS = puzzle_inst.SUCCESS

  def get_starting_room(self):
    return Game.WORLD_CHOICE.StartingXY

  def available_actions(self):
    """Returns all of the available actions in this room"""
    moves = []
    while not self.SUCCESS:
      self.available_actions_fail()
    moves = self.available_actions_success()
    return moves

  def available_actions_success(self):
    moves = super().adjacent_moves()
    moves.append(actions.ViewInventory())
    return moves

  def available_actions_fail(self):
    self.this_player.HP -= 10
    print("\n--- You took 10 damage! Your health is now {} ---\n".format(self.this_player.HP))
    self.modify_player(self.this_player)

class ActionRoom(MapTile):
  def __init__(self, x, y, amt, method, name):
    """
    method = actions.Heal, actions.TakeGold
    """
    self.this_player = None
    self.amt = amt
    self.method = method
    super().__init__(x, y, name)
    self.amt_taken = False

  def intro_text(self):
    return NotImplementedError

  def modify_player(self, player):
    self.visited = True
    self.this_player = player
    if not self.amt_taken:
      response = input("y/n\n")
      if response == 'y':
        self.amt_taken = True
        self.method(self.amt).method(self.this_player, self.amt)
      elif response == 'n':
        return

class MedicalRoom(ActionRoom):
  def __init__(self, x, y, amt, name):
    method = actions.Heal
    super().__init__(x, y, amt, method, name)

  def intro_text(self):
    if not self.amt_taken:
      return"""\n you see a small tent with a red cross\ndo you heal yourself?\n"""
    else:
      return"""\n the tent has been destoryed\ntheres nothing you can do.\n"""

class ManaRoom(ActionRoom):
  def __init__(self, x, y, amt, name):
    method = actions.GainMana
    super().__init__(x, y, amt, method, name)

  def intro_text(self):
    if not self.amt_taken:
      return"""\n you see a small pad with the anicant symbol for mana ingraves into it, it is glowing\ndo you gain back your mana?"""
    else:
      return"""\n a weird ring sits in the middle of the room\ntheres nothing you can do.\n"""

class FindGoldRoom(ActionRoom):
  def __init__(self, x, y, amt, name):
    method = actions.TakeGold
    super().__init__(x, y, amt, method, name)

  def intro_text(self):
    if not self.amt_taken:
      return"""\n you see a pile of gold in the middle of the room\ndo you take the gold?\n"""
    else:
      return"""\nthere is nothing but a few loose coins in this room\n"""

class FindOldSwordRoom(LootRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, items.OldSword(), items_dagger.OldNunchucks(), rangeditems.OldBow(), name)

  def intro_text(self):
    if not self.item_taken:
      return"""
      in the middle of this room there is a stone pedestal.
      on the pedestal you see a rusted old sword with a plaque in front of it.
      it reads "this is a old sword."

      you got the old Sword!
      """
    else:
      return"""
      the stone pedestal is empty there is a plaque that says "a Old Sword" but it is empty
      """

class FindOldShortSwordRoom(LootRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, items.Oldshortsword(), items_dagger.OldDuelDaggers(), rangeditems.OldCrossBow(), name)

  def intro_text(self):
    if not self.item_taken:
      return"""
      in the middle of this room there is a stone pedestal.
      on the pedestal you see a rusted old short sword with a plaque in front of it.
      it reads "this is a old short sword."

      you got the old Short Sword!
      """
    else:
      return"""
      the stone pedestal is empty there is a plaque that says "a Old ShortSword" but it is empty
      """

class FindSwordRoom(LootRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, items.Sword(), items_dagger.Nunchucks(), rangeditems.Bow(), name)

  def intro_text(self):
    if not self.item_taken:
      return"""
      in the middle of this room there is a stone pedestal.
      on the pedestal you see a shinling and glinting sword with a plaque in front of it.
      it reads "a Sword".

      you got the Sword!
      """
    else:
      return"""
      the stone pedestal is empty there is a plaque that says "a Sword" but it is empty
      """

class FindShortSwordRoom(LootRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, items.Shortsword(), items_dagger.DuelDaggers(), rangeditems.CrossBow(), name)

  def intro_text(self):
    if not self.item_taken:
      return"""
      in the middle of this room there is a stone pedestal.
      on the pedestal you see a shining Shortsword with a plaque in front of it.
      it reads "a Shortsword".

      you got the Shortsword!
      """
    else:
      return"""
      the stone pedestal is empty there is a plaque that says "a Shortsword" but it is empty
      """

class FindOldLongSwordRoom(LootRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, items.Oldlongsword(), items_dagger.OldDuelHandaxe(), rangeditems.OldLongBow(), name)

  def intro_text(self):
    if not self.item_taken:
      return"""
      in the middle of this room there is a stone pedestal.
      on the pedestal you see a rusted Longsword with a plaque in front of it.
      it reads "a Dagger".

      you got the Old Longsword!
      """
    else:
      return"""
      the stone pedestal is empty there is a plaque that says "a Old Longsword" but it is empty
      """

class FindLongSwordRoom(LootRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, items.Longsword(), items_dagger.DuelHandaxe(), rangeditems.LongBow(), name)

  def intro_text(self):
    if not self.item_taken:
      return"""
      in the middle of this room there is a stone pedestal.
      on the pedestal you see a shining Longsword with a plaque in front of it.
      it reads "a Longsword".

      you got the Longsword!
      """
    else:
      return"""
      the stone pedestal is empty there is a plaque that says "a Longsword" but it is empty
      """

class FindShieldRoom(LootRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, items.Shield(), None, None, name)

  def intro_text(self):
    if not self.item_taken:
      return"""
      in the middle of this room there is a stone pedestal.
      on the pedestal you see a glinting Shield with a plaque in front of it.
      it reads "a Shield".

      you got the Shield!
      """
    else:
      return"""
      the stone pedestal is empty there is a plaque that says "a Sheild" but it is empty
      """

class ShopRoom(MapTile):
  def __init__(self, x, y, goods, name):
    self.goods = goods
    self.inside = False
    super().__init__(x, y, name)

  def intro_text(self):
    return """\nas you enter the room you see a small tent in\na wharm glow flows out from the inside\n"""

  def modify_player(self, player):
    if not self.inside:
      self.inside = player.enter_shop()
    self.visited = True

  def available_actions(self):
    """if entered, return list of buy, sell, or leave,
        else, normal available-actions"""
    moves = []
    if self.inside:
      moves.append(actions.GetItem(self.goods))
      moves.append(actions.SellItem())
      moves.append(actions.ViewInventory())
      #moves.append(actions.LeaveShop())
      self.inside = False
    else:
      moves = self.adjacent_moves()
      #moves.append(actions.EnterShop())
      moves.append(actions.ViewInventory())
      moves.append(actions.ViewMap())
    return moves

class SpellRoom(MapTile):
  def __init__(self, x, y, name, spell):
    self.spell = spell
    self.item_taken = False
    super().__init__(x, y, name)

  def modify_player(self, player):
    """use player.load_spell"""
    self.visited = True
    self.this_player = player
    if not self.item_taken:
      if isinstance(Game.CLASS_CHOICE, classes.Mage):
        player.load_spell(self.spell)
    else:
      self = EmptyCavePath(self.x, self.y, "ECP")

class FindIceBolt(SpellRoom):
  def __init__(self, x, y, name):
    super().__init__(x, y, name, items.IceBolt())

  def intro_text(self):
      if isinstance(Game.CLASS_CHOICE, classes.Mage):
        if not self.item_taken:
          return"""
          You see a dusty book in the middle of the room it reads "Ice Bolt".
          """
        else:
          return"""
          You see a book with all the pages blank.
          """
      else:
        return """
        You see a book with symbols you cannot read.
        """


from typing import List

class NumMatrix:

    def __init__(self, matrix: List[List[int]]):
        self.matrix = matrix
        self.cache = {}

    def sumRegion(self, row1: int, col1: int, row2: int, col2: int) -> int:
        if (row1, col1, row2, col2) in self.cache:
            return self.cache[(row1, col1, row2, col2)]
        else:
            s = sum([sum([self.matrix[row][col] for col in range(col1, col2+1)])
                     for row in range(row1, row2+1)])
            self.cache[(row1, col1, row2, col2)] = s
            return s

# Your NumMatrix object will be instantiated and called as such:
# obj = NumMatrix(matrix)
# param_1 = obj.sumRegion(row1,col1,row2,col2)


#Mia Katz
#10.24.18
#Fractals Project
#On my honor, I've neither given nor received unauthorized aid
#The first project is a Mandelbrot, with an ombre pattern replacing anywhere that doesn't escape. It is layered with a small checkerboard for an added effect.
#The second is a Julia with a blurred filter over it. It also has some alternating color stripes
#The third is a mandelbrot divided into four squares. Two of them are very patterned, and the other two have a gradient and a smoothing filter over them!
#Sources: https://lodev.org/cgtutor/juliamandelbrot.html for learning what the Julia set actually is, https://docs.python-guide.org/scenarios/imaging/ for help with Filters, and https://pillow.readthedocs.io/en/5.2.x/reference/ImageFilter.html for even more about the filters. https://www.atopon.org/mandel/# for the zooms on the mandelbrot, and https://www.cs.unm.edu/~stharding/julia/julia.html for the Julia shapes

from PIL import Image, ImageFilter
xa, xb = 0.3038888888, 0.35888888 #This changes the zoom
ya, yb = 0.545, 0.6
jxa, jxb = -0.6, 0.4
imgx, imgy = 512, 512

maxIt = 256

image = Image.new("RGB", (imgx, imgy)) #First Mandelbrot
julia = Image.new("RGB", (imgx, imgy)) #Second Mandelbrot
two = Image.new("RGB", (imgx, imgy)) #Third Mandelbrot

for y in range(imgy):
	cy = y * (yb-ya)/(imgy-1) + ya
	for x in range(imgx):
		cx = x * (xb-xa)/(imgx-1) + xa
		c = complex(cx, cy)
		z = 0
		for i in range(maxIt):
			if abs(z) >= 2.0:
				break
			z = z**2 + c

		if (x%2 == 0 and y%2 == 0) or (x%2 != 0 and y%2 != 0): #These loops here make the checkerboard on the first Mandelbrot
			if 254 > i:
				image.putpixel((x, y), ((i*6)%256, i, 50))
			else: #The checkerboard is also ombre, though very slightly!
				image.putpixel((x, y), (int(y/2), int((y+x)/4), int(x/2)))
		elif 254< i: #This one controls the ombre type effect
			image.putpixel((x,y), (int(x/2), 0, int(y/2)))
		else:
			image.putpixel((x, y), ((i*12)%256, i, (i*86)%256))
print("Mandelbrot 1 Complete") #Completion tracking

d = 0.2314190881763527 #This is the zoom on the Julia. I chose to work with the Julia as I loved the spiral-type patterns, and it was much easier to comprehend due to the work on the Mandelbrot.
e = - 0.5322770541082162
c = complex(d,e)
xa, xb = .245, .345
ya, yb = 0.813, 0.913
maxIt = 256
cy = 0
cx = 0
for y in range(imgy):
	cy = y * (yb-ya)/(imgy-1) + ya
	for x in range(imgx):
		cx = x * (xb-xa)/(imgx-1) + xa
		z = complex(cx, cy)
		for i in range(maxIt):
			if abs(z) >= 2.0:
				break
			z = z**2 + c
		if x< 103 or 206<=x<306 or x>409: #This adds the blue and purple stripes
			julia.putpixel((x,y),(i, 12, (i*68)%256))
		else: #yellow and green stripe
			julia.putpixel((x,y), (i*68%256, i, 12))

print("Julia Complete")

xa, xb = -1.9425254, -1.9425244 #Second mandelbrot zoom, this one is much smaller
ya, yb = -0.0000132425, -0.000012279805

for y in range(imgy):
	cy = y * (yb-ya)/(imgy-1) + ya
	for x in range(imgx):
		cx = x * (xb-xa)/(imgx-1) + xa
		c = complex(cx, cy)
		z = 0
		for i in range(maxIt):
			if abs(z) >= 2.0:
				break
			z = z**2 + c
		if (x > 256 and y > 256) or (x<256 and y<256): #These blocks are the heavily patterned parts of the image. I just picked some random numbers and also used a slight blue gradient on them. It's not the most apparent though, but it was before I separated the picture into the four corners.
			two.putpixel((x, y), ((i*48)%256, (i*1982)%256, int(x/2)))
		else: #This loop is for the gradient corners.
			two.putpixel((x,y), (i, int(y/2), int(x/2)))

print("Done!")
ju = julia.filter(ImageFilter.BLUR) #This blurs the Julia, and I imported ImageFilter from PIL to achieve that.
image.show()
ju.show()
tu = two.filter(ImageFilter.SMOOTH) #This is another filter from PIL's ImageFilter. It was originally set to Emboss, but smooth really emphasized the colors.
tu.show()


from core.expr_parser import ExprParser
from .helper_types import NodeType, TreeNode

class QuarkParser:
    def __init__(self, token_stream):
        self.tree = None
        self.tokens = list(token_stream)
        self.expr_parser = ExprParser(self)
        self.prev, self.cur = None, self.tokens[0]

    # Util functions
    def peek(self, index=1):
        return self.tokens[index] if index < len(self.tokens) else None

    def consume(self):
        self.prev = self.tokens.pop(0)
        self.cur = self.tokens[0]
        return self.prev

    def is_term(self, token):
        return token.type in ["ID", "INT", "FLOAT", "STR"]

    def expect(self, type):
        if self.cur.type == type:
            return self.consume()
        else:
            raise Exception(f"Expected {type} but got {self.cur.type}.")

    # Parsing functions
    def block(self):
        print(f"Block: {self.cur}")
        node = TreeNode(NodeType.Block)

        if self.cur.type == "NEWLINE" and self.peek().type == "INDENT":
            pass
        else:
            while self.cur.type != "NEWLINE":
                node.children.append(self.statement())
            self.expect("NEWLINE")

        return node

    def statement(self):
        print(f"Statement: {self.cur}")
        node = None

        if self.cur.type == "IF":
            node = self.ifelse()
        elif "FN" in [self.cur.type, self.peek(2).type]:
            node = self.function()
        elif self.cur.type == "AT":
            self.consume()
            node = self.function_call()
        else:
            node = self.expression()

        return node

    def expression(self):
        print(f"Expression: {self.cur}")
        return self.expr_parser.parse()

    def function(self):
        print(f"Function: {self.cur}")
        node = None

        if self.cur.type == "FN":
            node = TreeNode(NodeType.Function, self.consume())
            node.children.extend(
                [TreeNode(NodeType.Identifier, self.expect("ID")), self.arguments()]
            )
            self.expect("COLON")
            node.children.append(self.block())
        elif self.peek(2).type == "FN":
            id = TreeNode(NodeType.Identifier, self.expect("ID"))
            self.expect("EQUALS")
            node = TreeNode(NodeType.Function, self.consume())
            node.children.extend([id, self.arguments()])
            self.expect("COLON")
            node.children.append(self.block())

        return node

    def function_call(self):
        print(f"Function Call: {self.cur}")
        node = TreeNode(NodeType.FunctionCall)
        node.children.extend(
            [TreeNode(NodeType.Identifier, self.expect("ID")), self.arguments()]
        )
        return node

    def arguments(self):
        print(f"Arguments: {self.cur}")
        node = TreeNode(NodeType.Arguments)

        while self.cur.type not in ["COLON", "NEWLINE"]:
            node.children.append(self.expression())

            if self.cur.type == "COMMA":
                self.consume()

        print(node)
        return node

    def ifelse(self):
        pass

    def term(self):
        return TreeNode(
            NodeType.Identifier if self.cur.type == "ID" else NodeType.Literal,
            self.consume(),
        )

    def parse(self):
        self.tree = TreeNode(NodeType.CompilationUnit)
        self.tree.children.append(self.block())


def count_text(string):
    dictionary = {}
    density = {}
    dictionary['total_words'] = len(string.rsplit())
    dictionary['punctuations'] = string.count(",") + string.count("!") + string.count(".")
    dictionary['spaces'] = string.count(" ")

    if string[-1] == ".":
        dictionary['punctuations']+=1

    punc = '''!()-[]{};:'“”"\,<>./?@#$%^&*_~'''

    for ele in string:
        if ele in punc:
            string = string.replace(ele, "")

    words_ = string.rsplit()

    dictionary['upper_char'] = sum(1 for c in string if c.isupper())
    dictionary['lowercase_char'] = sum(1 for c in string if c.islower())

    total_words = len(words_)

    for word in words_:
        if word not in density:
            density[word] = {"counter":1,"percentange":""}
        else:
            density[word]["counter"] +=1

    for item in density:
        density[item]["percentage"] = int((density[item]["counter"]*100)//total_words )

    dictionary["words"] = density

    return dictionary

count_text("model, cascade on any user interface.")

# def count(string):


# Given a triangle array, return the minimum path sum from top to bottom.
# For each step, you may move to an adjacent number of the row below.
# More formally, if you are on index i on the current row, you may move
# to either index i or index i + 1 on the next row.

# Input: triangle = [[2],[3,4],[6,5,7],[4,1,8,3]]
# Output: 11
# Explanation: The triangle looks like:
#    2
#   3 4
#  6 5 7
# 4 1 8 3
# The minimum path sum from top to bottom is 2 + 3 + 5 + 1 = 11 (underlined above).

def minimumTotal(triangle):
    n = len(triangle)
    tab = [[float('inf') for _ in range(n)] for _ in range(n)]
    tab[0][0] = triangle[0][0]
    for row in range(1, n):
        for col in range(row + 1):
            if col - 1 >= 0:
                tab[row][col] = min(tab[row][col], tab[row - 1][col - 1] + triangle[row][col], tab[row - 1][col] + triangle[row][col])
            else:
                tab[row][col] = min(tab[row][col], tab[row - 1][col] + triangle[row][col])
    return min(tab[n - 1])

LeetCode/Dynamic Programming/120 [medium] Triangle.py


import pytest

import numpy.testing as npt

from xbout.load import _auto_open_mfboutdataset

from boutdata import collect

class TestAccuracyAgainstOldCollect:
    @pytest.mark.xfail(reason="Collect tries to read 'nx' when it doesn't exist")
    def test_single_file(self):
        var = 'n'
        expected = collect(var, path='./tests/data/dump_files/single',
                           prefix='equilibrium', xguards=False)

        ds, metadata = _auto_open_mfboutdataset('./tests/data/dump_files/single/equilibrium.nc')
        print(ds)
        actual = ds[var].values

        assert expected.shape == actual.shape
        npt.assert_equal(actual, expected)

    @pytest.mark.xfail(reason="Collect says mz=129, then collects an array of "
                              "length 128?!")
    def test_multiple_files_along_x(self):
        var = 'n'
        expected = collect(var, path='./tests/data/dump_files/',
                           prefix='BOUT.dmp', xguards=False)

        ds, metadata = _auto_open_mfboutdataset('./tests/data/dump_files/BOUT.dmp.*.nc')
        actual = ds[var].values

        assert expected.shape == actual.shape
        npt.assert_equal(actual, expected)

    @pytest.mark.skip
    def test_multiple_files_along_x(self):
        ...

    @pytest.mark.skip
    def test_metadata(self):
        ...

@pytest.mark.skip
class test_speed_against_old_collect:
    ...


from nltk.tokenize import RegexpTokenizer
from nltk.corpus import stopwords
import pandas as pd
import nltk
from nltk.tokenize.treebank import TreebankWordDetokenizer
import os.path

class CsvSettings():
    isdata_exist = False

    def csv_parser(self):
        nltk.download('stopwords')

        stop_words = set(stopwords.words('english'))
        regexp = RegexpTokenizer('\w+')

        data = pd.read_csv("rows.csv")

        data.drop(columns=["Date received", "Sub-product", "Sub-issue",
                           "Consumer complaint narrative", "Company public response", "Tags",
                           "Consumer consent provided?", "Submitted via", "Date sent to company",
                           "Company response to consumer", "Timely response?", "Consumer disputed?"],
                  inplace=True, axis=1)

        # Null kayıtların silinmesi
        data = data.dropna()

        for column in data.columns:
            data[column] = data[column].astype(str).str.lower()
            data[column] = data[column].apply(regexp.tokenize)
            data[column] = data[column].apply(
                lambda x: [item for item in x if item not in stop_words])
            data[column] = data[column].apply(
                lambda x: ' '.join([item for item in x if len(item) > 1]))
            data[column] = data[column].astype(
                str).str.replace(r'[^\w\s]+', "", regex=True)

        data = data.dropna()

        data.to_csv("new_rows.csv")

    def use_new_rows(self):

        if (os.path.isfile("new_rows.csv")):
            self.isdata_exist = True
            data = pd.read_csv("new_rows.csv", index_col=0,
                               dtype={'Complaint ID': 'str'})
            print("Dosya kullanıma hazır.")
            return data
        else:
            print("Dosya Oluşturulmamış.\nYeni dosya oluşturluyor.\nLütfen bekleyiniz.. ")
            self.csv_parser()
            return self.use_new_rows()

    def get_column_names(self):
        data = self.use_new_rows()
        if (self.isdata_exist):
            data_top = data.columns.values.tolist()
            print("Sütunlar", data_top)
            return data_top
        else:
            print("Sütunlar bulunamadı çünkü dosya oluşturulmamış")


from setuptools import find_packages, setup

with open("README.md", encoding='utf-8') as f:
    long_description = f.read()

with open('requirements.txt') as f:
    requirements = f.readlines()

setup(name='MEDprofiles',
      version='0.1.0',
      description='Python module for treatment and visualization of medical data.',
      long_description=long_description,
      long_description_content_type="text/markdown",
      author='Sarah Denis',
      author_email='dens1704@usherbrooke.ca',
      url='https://github.com/MEDomics-UdeS/MEDprofiles',
      packages=find_packages(),
      install_requires=requirements
      )


'''
Neural network that recognizes numbers
and training it with PyTorch
'''

import torch
import torch.nn as nn
import torch.optim as optim
import torchvision.datasets as datasets
import torchvision.transforms as transforms
from torch.autograd import Variable

# Data Loading and Retrieval
transform = transforms.Compose([
        transforms.ToTensor(),
        transforms.Normalize((0.5), (0.5))
     ])

train_datasets = datasets.MNIST(root='./data', train=True, download=True, transform=transform)
test_datasets = datasets.MNIST(root='./data', train=False, download=True, transform=transform)

# Creating Data Loaders
train_loader = torch.utils.data.DataLoader(dataset=train_datasets, batch_size=100, shuffle=True)
test_loader = torch.utils.data.DataLoader(dataset=train_datasets, batch_size=100, shuffle=False)

# Definition of the model
class Net(nn.Module):
    def __init__(self):
        super(Net, self).__init__()
        self.fc1 = nn.Linear(28 * 28, 500)
        self.activation1 = nn.ReLU()
        self.fc2 = nn.Linear(500, 10)

    def forward(self, x):
        x = x.view(-1, 28 * 28)
        x = self.activation1(self.fc1(x))
        x = self.fc2(x)
        return x

# Create a model instance and determine the loss function and optimizer
model = Net()
criterion = nn.CrossEntropyLoss()
optimizer = optim.SGD(model.parameters(), lr=0.01)

# Training a model
for epoch in range(10):
    running_loss = 0.0
    for i, (images, labels) in enumerate(train_loader):
        images = Variable(images)
        labels = Variable(labels)
        optimizer.zero_grad()
        outputs = model(images)
        loss = criterion(outputs, labels)
        loss.backward()
        optimizer.step()
        running_loss += loss.data.item()
    print('Epoch [%d/%d], Loss: %.4f' % (epoch+1, 10, running_loss))

# Testing a model

correct = 0
total = 0
for images, labels in test_loader:
    images = Variable(images)
    outputs = model(images)
    _, predicted = torch.max(outputs.data, 1)
    total += labels.size(0)
    correct += (predicted == labels).sum()
print('Accuracy of the network on the 10000 test images: %d %%' % (100 * correct / total))


#myList=[1,2,3,4]
#for item in myList:
 #   print(item)

#while True:
  #  print("hi")
#item=0
#while item< 3:
 #   print(myList[item])
  #  item+=1

#for num in range(11):
 #   print(num)

#string="i love python"
#for count in range(10):
 #   print(string)

numbers=[1,4,6,2]
count=0
for i in numbers:
    count=count+i
print(count)


import django
import csv

from contactos.models import Contacto, Empresa

def busqueda():
    e=Empresa.objects.get(id=1)
    print(e.contacto_empresas.all())

    c=Contacto.objects.get(id=1)
    print(c.empresas.all())

def crear_empresa(reg):
    emp = Empresa.objects.create()
    emp.nombre = reg['Razon Social']
    emp.razon_social = reg['Razon Social']
    emp.cuit = reg['CUIT']
    emp.telefono1 = reg['Tel1']
    emp.telefono2 = reg['Tel2']
    emp.vendedor = reg['Vendedor']
    emp.actividad = reg['Actividad']
    emp.id_referencia = reg['idGest']
    emp.save()
    return emp

def crear_contacto(reg):
    if Contacto.objects.filter(numero_tel=reg['Movil']).exists():
        con = Contacto.objects.get(numero_tel=reg['Movil'])
    else:
        con = Contacto.objects.create()
        con.nombre = reg['Nombre']
        con.apellido = reg['Apellido']
        con.tipo_tel = 'movil'
        con.area_tel = ''
        con.numero_tel = reg['Movil']
        con.email = reg['Correo']
        con.save()
    return con

def asociar_contacto():
    pass

def leer_csv():
    with open('Contactos.csv') as csvarchivo:
        entrada = csv.DictReader(csvarchivo, delimiter=';', quoting=csv.QUOTE_NONE)
        for (contador, reg) in enumerate(entrada):
            try:
                emp = crear_empresa(reg)
                con = crear_contacto(reg)
                con.empresas = emp
                con.save()

            except BaseException:
                print('Error al procesar linea número ', contador + 2)
                raise

leer_csv()


import sys
input = sys.stdin.readline

N,M = list(map(int,input().split()))

Map = []
visit = []

for i in range(N):
    Map.append(list(map(int,input().split())))
    visit.append([False] * M)

dx = [0, 1, 0, -1]
dy = [-1, 0, 1, 0]

def find_island(y, x, idx):
    visit[y][x] = True
    Map[y][x] = idx
    for i in range(4):
        tx = x + dx[i]
        ty = y + dy[i]
        if(-1 < tx and tx < M and
            -1 < ty and ty < N):
            if(Map[ty][tx] != 0 and not visit[ty][tx]):
                find_island(ty,tx,idx)

def find_road(y, x):
    start = Map[y][x]
    dst = -1
    cost = 1
    _bridges = []
    for i in range(4):
        tx = x + dx[i]
        ty = y + dy[i]
        cost = 0
        dst = -1
        while(True):
            if(-1 < tx and tx < M and
                -1 < ty and ty < N):
                if(Map[ty][tx] == start):
                    break
                if(Map[ty][tx] != 0):
                    dst = Map[ty][tx]
                    break
            else:
                break
            tx = tx + dx[i]
            ty = ty + dy[i]
            cost += 1
        if(dst != -1 and cost > 1):
            if(bridge_Map[start][dst] == -1):
                bridge_Map[start][dst] = cost
                # print(y,x)
                # print([cost, start, dst])
                _bridges.append([cost, start, dst])
            else:
                if(bridge_Map[start][dst] > cost):
                    bridge_Map[start][dst] = min(bridge_Map[start][dst],cost)
                    # print(y,x)
                    # print([cost, start, dst])
                    _bridges.append([cost, start, dst])

    return _bridges

idx = 1
for i in range(N):
    for j in range(M):
        if(Map[i][j] != 0 and visit[i][j] == False):
            find_island(i,j,idx)
            idx += 1

bridges = [] #[cost / start / dst]
bridge_Map = []
for i in range(idx):
    bridge_Map.append([-1]*idx)

for i in range(N):
    for j in range(M):
        if(Map[i][j] != 0):
            bridge_list = find_road(i,j)

            if(bridge_list):
                [bridges.append(brid) for brid in bridge_list]

bridges.sort()

n = idx - 1
uf = [-1 for _ in range(n+1)]

def find(a):
    if uf[a] < 0: return a
    uf[a] = find(uf[a])
    return uf[a]

def merge(a, b):
    print(a,b)
    a = find(a)
    b = find(b)
    print(a,b)
    print("-------------")
    if a == b: return False
    uf[b] = a
    return True

total, cnt = 0, 0

for w, a, b in bridges:
    print(w)
    if merge(a, b):
        total += w
        cnt += 1
        if cnt == n-1: break
if cnt == n-1: print(total)
else: print(-1)

# total_island = idx - 1
# connected = [False] * idx

# answer = 0
# for i, v in enumerate(bridges):
#     _cost, _start, _dst = v
#     if(connected[_start] == False and connected[_dst] == False):
#         connected[_start] = True
#         connected[_dst] = True
#         answer += _cost
#         total_island -= 2
#         continue

#     if(connected[_start] == True and connected[_dst] == True):
#         continue

#     if(connected[_start] or connected[_dst]):
#         connected[_start] = True
#         connected[_dst] = True
#         total_island -= 1
#         answer += _cost

# print(Map)
# print(bridges)
# print(connected)

# if answer == 0:
#     print(-1)
#     exit()

# for i in range(1,len(connected)):
#     if(not connected[i]):
#         print(-1)
#         exit()

# print(answer)


import csv
import re
import pandas as pd
import seaborn as sb
import matplotlib.pyplot as plt

# Create CSV file and writer
f = open('data.csv', 'w', newline='')
writer = csv.writer(f)

# Regex matches for temp and time
regex = re.compile(": (\d*\.\d*),.*: (\d*)")

# Trying to take care not to load the whole file into memory at once
# in case of larger files with waveforms
with open("data.txt") as data:
    # Go through each line of data.txt
    for line in data:
        # See if it matches with regex
        for match in regex.finditer(line):
            # Write a new row with regex matches
            writer.writerow([match.group(1),match.group(2)])

#Close writer and CSV file, data.csv
f.close()

# Read data.csv, defining column names and setting index column set to 'ms'.
# Files should normally not be large enough to require chunksize...
data = pd.read_csv('data.csv', names=['temp', 'ms'], index_col='ms')

# Rewrite time column to panda timedelta milliseconds
data.index = pd.to_timedelta(data.index, unit='ms')

# Resample to calculate mean temperature and number of events every 30 minutes
resamp = data.resample('30min').agg({'temp': ['mean', 'std', 'count']})

# Flattens multiindex columns and fixes names
resamp.columns = resamp.columns.map('_'.join)

print(resamp)

resamp.to_csv('result.csv')

sb.set_style("darkgrid")

fig, ax =plt.subplots(1,3)

res = sb.lineplot(x='ms', y='temp_mean', data=resamp, ci='temp_std', ax=ax[0])

res.set(xlabel='Time [ms]', ylabel='Mean temperature [°C]')

res2 = sb.lineplot(x='ms', y='temp_count', data=resamp, ax=ax[1], ci='sd')

res2.set(xlabel='Time [ms]', ylabel='# events pr 30 minutes')

res3 = sb.scatterplot(x='temp_count', y='temp_mean', data=resamp, ax=ax[2])

res3.set(xlabel='# events pr 30 minutes', ylabel='Mean temperature [°C]')

plt.show()

fig.savefig("result.pdf", bbox_inches='tight')


#!/usr/bin/python

import math

"""
example input:
recipe_batches(
  { 'milk': 100, 'butter': 50, 'flour': 5 },
  { 'milk': 138, 'butter': 48, 'flour': 51 }
)

"""

def recipe_batches(recipe, ingredients):
  for key, value in recipe.items():
    print(key)
    print(value)

recipe_batches({ 'milk': 100, 'butter': 50, 'flour': 5 },
  { 'milk': 138, 'butter': 48, 'flour': 51 })

# if __name__ == '__main__':
#   # Change the entries of these dictionaries to test
#   # your implementation with different inputs
#   recipe = { 'milk': 100, 'butter': 50, 'flour': 5 }
#   ingredients = { 'milk': 132, 'butter': 48, 'flour': 51 }
#   print("{batches} batches can be made from the available ingredients: {ingredients}.".format(batches=recipe_batches(recipe, ingredients), ingredients=ingredients))


from django.forms import ModelForm, FileInput
from accounts.models import Order, Customer
from django.contrib.auth.models import User
from django.contrib.auth.forms import UserCreationForm

class OrderForm(ModelForm):
    class Meta:
        model = Order
        fields = '__all__'

class UpdateOrderForm(ModelForm):
    class Meta:
        model = Order
        fields = ['product','status']

class CustomerForm(ModelForm):
    class Meta:
        model = Customer
        fields = '__all__'
        exclude = ['user']
        widgets = {
            'porfile_pic': FileInput(),
        }

    def __init__(self, *args, **kwargs):
        super(CustomerForm, self).__init__(*args, **kwargs)
        self.fields['porfile_pic'].widget.attrs = {'id':'selectedFile'}

class CreateUserForm(UserCreationForm):
    class Meta:
        model  = User
        fields = ['username','email','password1','password2']


t = {1, 2, 3, 4, 56, 'string', (5, 'new', 25)}
# объявление множества, может состоять только из строк, чисел, кортежей
# множество неупорядоченная структура в которой невозможно создать два одинаковых значения
y = set()
x = (1, 2, 3, 4, 5, 6, 7)  # кортеж
y = [1, 2, 3, 4, 5, 6, 7]  # список
u = {'1': 1, '2': 2, '3': 3, '4': 4, '5': 5, '6': 6, '7': 7}  # словарь
h = {1, 2, 3, 4, 5, 6, 7}  # множество

print(x.__sizeof__())
print(y.__sizeof__())
print(u.__sizeof__())
print(h.__sizeof__())


import re
import supybot.utils as utils
from supybot.commands import *
import supybot.plugins as plugins
import supybot.ircutils as ircutils
import supybot.callbacks as callbacks

class Parrot(callbacks.Plugin):
	"""To use parrot, simply call it with a nickname:
	@parrot tehJ
	"""

	def __init__(self, irc):
		self.__parent = super(Parrot, self)
		self.__parent.__init__(irc)
		self._targets = set()

	def add(self, irc, msg, args, user):
		"""<user>
		adds user to parrot list"""
		if ircutils.strEqual(user, irc.nick):
			irc.reply('No, I will not parrot myself.')
			return
		self._targets.add(user)
		irc.replySuccess()
	add = wrap(add, [('checkCapability', 'owner'), 'text'])

	def remove(self, irc, msg, args, user):
		"""<user>
		removes user from parrot list"""
		self._targets.remove(user)
		irc.replySuccess()
	remove = wrap(remove, [('checkCapability', 'owner'), 'text'])

	def targets(self, irc, msg, args):
		"""takes no arguments
		returns current list of targets"""
		if self._targets:
			irc.reply("Current targets: " + utils.str.commaAndify(self._targets))
		else:
			irc.reply("There are currently no targets.")
	targets = wrap(targets, [('checkCapability', 'owner')])

	def doPrivmsg(self, irc, msg):
		if msg.nick in self._targets:
			IAmRe = re.compile(r'I am', re.I)
			text = re.sub(IAmRe, msg.nick + " is", msg.args[1])
			irc.reply(text, prefixNick=False)

	def doNick(self, irc, msg):
		oldNick = msg.nick
		newNick = msg.args[0]
		if oldNick in self._targets:
			self._targets.remove(oldNick)
			self._targets.add(newNick)

Class = Parrot


from datetime import datetime
from database import Database
from itertools import groupby
from helper import Helper

class Chart:
    def __init__(self,sensors,rows,start_date,end_date,main_type,variable,opt):
        self.helper = Helper()
        self.options = {}
        self.options['tick'] = self.calculate_tickness(start_date,end_date);
        self.rows = rows
        self.main_type = main_type
        self.variable = variable
        self.opt = opt
        self.database = Database()
        self.sensors = sensors
        self.options['sensor_ids'] = self.helper.pluck(sensors,'id')
        self.title = self.resolve_title(sensors[0])
        self.options['title'] = self.title

    def calculate_tickness(self,start_date,end_date):
        difference = self.string_to_datetime(end_date) - self.string_to_datetime(start_date)
        difference_in_seconds = difference.total_seconds()
        hours = divmod(difference_in_seconds,3600)[0]
        if hours < 24 :
            return 1000 * 60 * 60
        else :
            return 1000 * 60 * 60 * 24

    def string_to_datetime(self,date):
        return datetime.strptime(date,'%Y-%m-%d %H:%M:%S')

    def resolve_title(self, sensor) :
        if self.variable == 'stream' :
            return 'Corriente'
        elif self.variable == 'power':
            if sensor['name'] == 'P1':
                return 'Potencia líneas'
            else:
                return f"Potencia {sensor['name']}"
        else :
            if self.main_type == 'LL' :
                return 'Tensión LL'
            else :
                return 'Tensión LN'

    def make_chart_data(self):
        self.make_series()
        self.get_y_axis()

    def make_series(self):
        series = []
        i = 0

        self.sensors =  sorted(self.sensors, key=self.sensor_key_func)
        for key, sensor in groupby(self.sensors, self.sensor_key_func):
            ss = list(sensor)
            series.append({
                'name'  : f"{ss[0]['name']} ({ss[0]['disposition'] != None and ss[0]['disposition']['unit'] or 'N/A'})",
                'data' : self.get_points(ss),
                'turboThreshold' : 0,
                'type' :'spline',
                'zIndex' : (i + 100)
            })
            i+=1

        self.options['series'] = series

    def sensor_key_func(self,k):
        return k['name']

    def point_key_func(self,k):
        return k['grouper']

    def get_points(self,sensors):
        values = []
        for sensor in sensors:
            for value in list(map(self.map_point,filter(lambda row: row['sensor_id'] == sensor['id'], self.rows))):
                values.append(value)

        pp = []
        for key, points in groupby(sorted(values, key=self.point_key_func), self.point_key_func):
            pp.append(self.format_point(points))
        return pp

    def map_point(self,row):
        return {
            'grouper' : row['date'].strftime('%Y-%m-%d %H:%M:%S'),
            'date' : row['date'],
            'result' : row['result']
        }

    def format_point(self,rows):
        rows = list(rows)
        row = rows[0]
        return {
            'x' : int(row['date'].strftime('%s'))*1000,
            'y' : self.calculate_avg(rows),
            'name' : row['date'].strftime('%Y-%m-%d %H:%M:%S')
        }

    def calculate_avg(self,rows):
        avg = 0
        for row in rows:
            avg = avg + row['result']
        return avg / float(len(rows))

    def get_y_axis(self):
        self.options['yAxis'] = [{
                'title' :{
                    'text' : self.title
                },
                'stacklabels' : {
                    'enabled' : True,
                    'style' : {
                        'fontWeight' : 'bold',
                        'color' : 'gray'
                    }
                },
                'opposite' : False
            }]


import os
import pprint
from osgeo import gdal
from os.path import join
import numpy as np
from datetime import datetime
import gc
import time

import matplotlib.pyplot as pyplot

def hist_match(source, template):
    """
    Adjust the pixel values of a grayscale image such that its histogram
    matches that of a target image

    Arguments:
    -----------
        source: flattened np.ndarray
            Image to transform; the histogram is computed over the flattened
            array
        template: np.ndarray
            Template image; can have different dimensions to source
    Returns:
    -----------
        matched: flattened np.ndarray
            The transformed output image
    """
    # oldshape = source.shape
    # source = source.ravel()
    # template = template.ravel()

    # get the set of unique pixel values and their corresponding indices and
    # counts
    s_values, bin_idx, s_counts = np.unique(
        source, return_inverse=True, return_counts=True
    )
    t_values, t_counts = np.unique(template, return_counts=True)

    # take the cumsum of the counts and normalize by the number of pixels to
    # get the empirical cumulative distribution functions for the source and
    # template images (maps pixel value --> quantile)
    s_quantiles = np.cumsum(s_counts).astype(np.float64)
    s_quantiles /= s_quantiles[-1]
    t_quantiles = np.cumsum(t_counts).astype(np.float64)
    t_quantiles /= t_quantiles[-1]

    # interpolate linearly to find the pixel values in the template image
    # that correspond most closely to the quantiles in the source image
    interp_t_values = np.interp(s_quantiles, t_quantiles, t_values)

    return interp_t_values[bin_idx]

if __name__ == "__main__":

    fullimg = "/home/tq/data_pool/zgq/estarfm/test/sub-0802.tif"  # full img
    gapimg = "/home/tq/data_pool/zgq/estarfm/test/sub-0818.tif"  # img with gap

    # read img
    ds = gdal.Open(fullimg)
    geo_trans = ds.GetGeoTransform()
    w = ds.RasterXSize
    h = ds.RasterYSize
    img_shape = [h, w]
    proj = ds.GetProjection()
    arrfull = ds.GetRasterBand(4).ReadAsArray()
    ds = None

    ds = gdal.Open(gapimg)
    geo_trans = ds.GetGeoTransform()
    w = ds.RasterXSize
    h = ds.RasterYSize
    img_shape = [h, w]
    proj = ds.GetProjection()
    arrgap = ds.GetRasterBand(4).ReadAsArray()
    ds = None

    # get mask of gap
    mask = arrgap.copy()
    mask[mask > 0] = 1
    mask[mask <= 0] = 0  # zero is cloud
    maxv = np.max(arrfull) / 5  # np.percentile(arrfull, 0.7) / 5  #

    fill = arrfull.copy()
    idx0 = np.where(mask == 0)
    idx1 = np.where(mask == 1)
    fill[idx1] = 0

    # valid pixels = vp
    vp_fill = fill[idx0]
    vp_gap = arrgap[idx1]

    vp_fill = hist_match(vp_fill, vp_gap)
    fill[idx0] = vp_fill

    arrgapnew = arrgap + fill

    pyplot.figure(num="test", figsize=(8, 8))  # image show part
    p1 = pyplot.subplot(131)
    p2 = pyplot.subplot(132)
    p3 = pyplot.subplot(133)
    p1.imshow(arrfull, cmap=pyplot.cm.rainbow, vmin=0., vmax=maxv)
    p2.imshow(arrgap, cmap=pyplot.cm.rainbow, vmin=0., vmax=maxv)
    p3.imshow(arrgapnew, cmap=pyplot.cm.rainbow, vmin=0., vmax=maxv)
    pyplot.show()  # image show part end

    print("fin")


from NLP.SpeachAnalysis import NLPObject
from NLP.Common import DatabaseConnection as dbc
import NLP.Common.DataOperations as do

bodysFocus = do.getBodys(dbc.collectionFocusData)
bodysTaz = do.getBodys(dbc.collectionTazData)
bodysAll = bodysFocus + bodysTaz

#rawCorpus = []

wordList = ['nachhaltigkeit', 'armut', 'hunger', 'gesunheit' , 'bildung', 'gleichheit', 'gleichstellung', 'trinkwasser', 'energie', 'energiewende', 'menschenwürde',
            'infrastruktur', 'ungleichheit', 'stadtenwicklung','konsum', 'konsumverhalten', 'klimaschutz', 'ökosysteme', 'frieden', 'partnerschaft', 'wirtschaftswachstum',
            'stadt', 'meer', 'lebensraum','wirtschaften', 'ökologie', 'regionalität', 'umweltschutz', 'energieeffizienz', 'ressourcenschonung', 'ressourceneffizienz',
            'wohlergehen', 'meeresschutz', 'frieden', 'global', 'trinkwasser', 'energiewende', 'stadtentwicklung']

NLP = NLPObject()

processedCorpusFocus = NLP.processCorpus(bodysFocus)
processedCorpusTaz = NLP.processCorpus(bodysTaz)
processedCorpusAll = NLP.processCorpus(bodysAll)

file1 = open('data/WordFrequencies.txt', 'w')

'''Count word frequencies in a Corpus and write them into the WordFrequencies text file'''
for word in wordList:
       focus = NLP.countWordFrequencyInACorpus(processedCorpusFocus, f'{word}')
       file1.write("\r\nHäufigkeit des Vorkommens im Focus: " + focus.__str__())
       taz = NLP.countWordFrequencyInACorpus(processedCorpusTaz, f'{word}')
       file1.write("\r\nHäufigkeit des Vorkommens in der Taz: " + taz.__str__())

'''Create a dictionary with words of all texts from both newspaper'''
#dictionary = NLP.createDictionary(processedCorpusAll)

'''Load the created dictionary with words of all texts from both newspaper'''
dictionary = NLP.loadDictionary()

'''Build word stems from both newpaper and add them to the dictionary'''
#wordStemCorpusAll = NLP.buildWordStemms(processedCorpusAll)
#NLP.addToDictionary(wordStemCorpusAll, dictionary)

'''Build bigrams from both newpaper and add them to the dictionary'''
#bigramsAll = NLP.buildBigramsOfAText(bodysAll)
#NLP.addToDictionary(bigramsAll, dictionary)

NLP.vecotrizeCorpus(dictionary, bodysFocus, 'Focus')  # vectorize bowCorpusFocus
bowCorpusFocus = NLP.loadBowCorpus('Focus')

NLP.vecotrizeCorpus(dictionary, bodysTaz, 'Taz')  # vectorize bowCorpusTaz
bowCorpusTaz = NLP.loadBowCorpus('Taz')

#print('Focus Corpus: ', bowCorpusFocus)
#print('Taz Corpus: ', bowCorpusTaz)

'''Count most common in a Corpus and write them into the WordFrequencies text file (Bag-Of-Words approach)'''
file1.write("\r\n ")
file1.write("\r\nHäufigste Erwähnungen im Focus: " + NLP.createTFIDFModel(bowCorpusFocus, dictionary).__str__())
file1.write("\r\nHäufigste Erwähnungen in der Taz: " + NLP.createTFIDFModel(bowCorpusTaz, dictionary).__str__())

''' Word2Vec approach'''
file2 = open('data/WordSimilarities.txt', 'w')

wordListExt = ['Nachhaltigkeit', 'Armut', 'Hunger', 'Gesunheit', 'Bildung', 'Gleichheit', 'Gleichstellung', 'Trinkwasser', 'Energie', 'Energiewende', 'Menschenwuerde',
                  'Infrastruktur', 'Ungleichheit', 'Stadtenwicklung', 'Konsum', 'Konsumverhalten', 'Klimaschutz', 'Oekosysteme', 'Frieden', 'Partnerschaft',
                  'Wirtschaftswachstum' 'Stadt', 'Meer', 'Lebensraum']

'''Load a extern, pretrained german model word2Vec model'''
''' https://cloud.devmount.de/d2bc5672c523b086/ '''
germanW2vModel = NLP.load_ext_model()

'''Returns a list of the 10 most similar words to a given word from the extern germanwW2vModel'''
for word in wordListExt:
    file2.write(f"\r\nExternes Modell und {word.upper().__str__()} " + NLP.mostSimilar(germanW2vModel, f'{word}').__str__())

'''Create a word2Vec model for the Focus'''
# NLP.save_w2v_model(processedCorpusFocus, 'Focus')

'''Load the Focus word2Vec model'''
w2vModelFocus = NLP.load_w2v_model('Focus')

'''Build word stems from the Focus and add them to the word2Vec model'''
#wordStemCorpusFocus = NLP.buildWordStemms(processedCorpusFocus)
#for wordList in wordStemCorpusFocus:
    #NLP.trainModel(w2vModelFocus, wordList)

'''Build bigrams from the Focus and add them to the word2Vec model'''
#bigramsFocus = NLP.buildBigramsOfAText(bodysFocus)
#for wordList in bigramsFocus:
     #NLP.trainModel(w2vModelFocus, wordList)

'''Returns a list of the 10 most similar words to a given word from the w2VModelFocus and write them into the WordSimilarities text file'''
for word in wordList:
    file2.write(f"\r\nFocus und {word.upper().__str__()} " + NLP.mostSimilar(w2vModelFocus, f'{word}').__str__())

# print('Übereinstimmung von Nachhaltigkeit und Umwelt: ', NLP.checkSimiarity(w2vModelFocus, 'nachhaltigkeit', 'umwelt'))
# print('Höchste Übereinstimmung zu Nachhaltigkeit: ', NLP.checkMostSimilarWord(w2vModelFocus, 'nachhaltigkeit'))

'''Create a word2Vec model for the Taz'''
# NLP.save_w2v_model(processedCorpusTaz, 'Taz')

'''Load the Taz word2Vec model'''
w2vModelTaz = NLP.load_w2v_model('Taz')

'''Build word stems from the Taz and add them to the word2Vec model'''
#wordStemCorpusTaz = NLP.buildWordStemms(processedCorpusTaz)
#for wordList in wordStemCorpusTaz:
    #NLP.trainModel(w2vModelTaz, wordList)

'''Build bigrams from the Focus and add them to the word2Vec model'''
#bigramsTaz = NLP.buildBigramsOfAText(bodysTaz)
#for wordList in bigramsTaz:
     #NLP.trainModel(w2vModelTaz, wordList)

'''Returns a list of the 10 most similar words to a given word from the w2VModelTaz and write them into the WordSimilarities text file'''
for word in wordList:
    file2.write(f"\r\nTaz und {word.upper().__str__()} " + NLP.mostSimilar(w2vModelTaz, f'{word}').__str__())

'''Create a word2Vec model for both newspaper'''
# NLP.save_w2v_model(processedCorpusAll, 'All')

'''Load the All word2Vec model'''
w2vModelAll = NLP.load_w2v_model('All')

'''Build word stems from the Taz and add them to the word2Vec model'''
#wordStemCorpusAll = NLP.buildWordStemms(processedCorpusAll)
#for wordList in wordStemCorpusAll:
    #NLP.trainModel(w2vModelAll, wordList)

'''Build bigrams from the Focus and add them to the word2Vec model'''
#bigramsAll = NLP.buildBigramsOfAText(bodysAll)
#for wordList in bigramsAll:
     #NLP.trainModel(w2vModelAll, wordList)

'''Returns a list of the 10 most similar words to a given word from the w2VModelAll and write them into the WordSimilarities text file'''
for word in wordList:
    file2.write(f"\r\nGesamt und {word.upper().__str__()} " + NLP.mostSimilar(w2vModelAll, f'{word}').__str__())