# -*- encoding: UTF-8 -*-
##############################################################################

from openerp import fields, api
from openerp.addons.field_secure import models  # @UnresolvedImport
import logging
_logger = logging.getLogger(__name__)

AVAILABLE_PRIORITIES = [
    ('0', 'Bad'),
    ('1', 'Below Average'),
    ('2', 'Average'),
    ('3', 'Good'),
    ('4', 'Excellent')
]

class hr_applicant(models.SecureModel):
    _inherit = "hr.applicant"

    salary_expected_secure = fields.Secure(
        string='Expected Salary',
        security="_password_security",
        help="Salary Expected by Applicant")
    salary_proposed_secure = fields.Secure(
        string='Proposed Salary',
        security="_password_security",
        help="Salary Proposed by the Organization")
    partner_name = fields.Char("Applicant's Name", track_visibility="onchange")
    email_from = fields.Char('Email', size=128,
                             help="These people will receive email.",
                             track_visibility="onchange")
    partner_mobile = fields.Char('Mobile', size=32,
                                 track_visibility="onchange")
    type_id = fields.Many2one('hr.recruitment.degree', 'Degree',
                              track_visibility="onchange")
    date_action = fields.Date('Next Action Date', track_visibility="onchange")
    title_action = fields.Char('Next Action', size=64,
                               track_visibility="onchange")
    priority = fields.Selection(AVAILABLE_PRIORITIES, 'Appreciation',
                                track_visibility="onchange")
    source_id = fields.Many2one('hr.recruitment.source', 'Source',
                                track_visibility="onchange")
    reference = fields.Char('Referred By', track_visibility="onchange")
    job_id = fields.Many2one('hr.job', 'Applied Job',
                             track_visibility="onchange")
    availability = fields.Integer(
        'Availability', help="The number of days in which the applicant will "
        "be available to start working", track_visibility="onchange")
    categ_ids = fields.Many2many('hr.applicant_category', string='Tags',
                                 track_visibility="onchange")
    description = fields.Text('Description', track_visibility="onchange")

    @api.model
    def create(self, vals):
        """
        Override function
        Calculate Subject = {Applied Job} - {Applicants name}
        """
        job_obj = self.env['hr.job']
        job_name = ''
        if vals.get('job_id'):
            job_name = job_obj.browse(vals['job_id']).name
        vals['name'] = job_name and job_name + ' - ' + vals['partner_name'] \
            or vals['partner_name']
        return super(hr_applicant, self).create(vals)

    @api.multi
    def write(self, vals):
        """
        Override function
        Calculate Subject = {Applied Job} - {Applicants name}
        """
        if 'job_id' not in vals and 'partner_name' not in vals:
            # Nothing change
            return super(hr_applicant, self).write(vals)

        job_obj = self.env['hr.job']
        if 'job_id' in vals and 'partner_name' in vals:
            # change job and applicant name
            # update all applicant at the same time
            job_name = ''
            if vals.get('job_id'):
                job_name = job_obj.browse(vals['job_id']).name
            vals['name'] = job_name and job_name + ' - ' \
                + vals['partner_name'] \
                or vals['partner_name']
            return super(hr_applicant, self).write(vals)
        else:
            # change job or partner_name
            if 'job_id' in vals:
                # Only change job name
                job_name = ''
                if vals['job_id']:
                    job_name = job_obj.browse(vals['job_id']).name
                for app in self:
                    pos = app.name.find('-')
                    vals['name'] = job_name and job_name + ' - ' + \
                        (pos > -1 and app.name[pos + 2:] or app.name) \
                        or app.name[pos + 2:]
                    super(hr_applicant, app).write(vals)
            elif 'partner_name' in vals:
                # On change the application name
                for app in self:
                    pos = app.name.find('-')
                    vals['name'] = (pos > -1 and app.name[: pos + 2] or '') + \
                        vals['partner_name']
                    super(hr_applicant, app).write(vals)
        return True

    @api.multi
    def _password_security(self):
        """
            Only the followers of the application can read/update/delete the
            Propose Salary/Suggested Salary.
        """
        is_allow = False
        for rec in self:
            if self.env.user.partner_id.id in rec.message_follower_ids.ids:
                is_allow = True
            else:
                is_allow = False
                break
        return is_allow

    @api.model
    def _get_applicants_of_followers(self, user_id):
        filter_ids = []
        current_user = self.env["res.partner"].search(
            [('user_id', '=', user_id)])
        self._cr.execute(""" SELECT id FROM hr_applicant """)
        datas = [data[0] for data in self._cr.fetchall()]
        for rec in self.browse(datas):
            if current_user in rec.message_follower_ids:
                filter_ids.append(rec.id)
        if filter_ids:
            return [('id', 'in', filter_ids)]
        else:
            return [('id', 'in', [])]

    @api.model
    def search(self, args, offset=0, limit=None, order=None, count=False):
        uid = self._context.get('uid', self._uid)
        if self.message_follower_ids and \
                uid in self.message_follower_ids.ids:
            args.extend(self._get_applicants_of_followers(uid))
        return super(hr_applicant, self).search(
            args, offset=offset, limit=limit, order=order, count=count)

    @api.cr_uid_ids_context
    def message_track(self, cr, uid, ids, tracked_fields,
                      initial_values, context=None):
        def convert_for_display(value, col_info):
            if not value and col_info['type'] == 'boolean':
                return 'False'
            if not value:
                return ''
            if col_info['type'] == 'many2one':
                return value.name_get()[0][1]
            if col_info['type'] == 'selection':
                return dict(col_info['selection'])[value]
            if col_info['type'] == 'many2many':
                str1 = ', '.join([v.name_get()[0][1] for v in value])
                return str1
            return value

        def format_message(message_description, tracked_values):
            message = ''
            if message_description:
                message = '%s' % message_description
            for name, change in tracked_values.items():
                old_values = change.get('old_value')
                if isinstance(old_values, int):
                    old_values = str(old_values)
                list_old_values = \
                    [item.strip().encode('utf-8')
                     for item in old_values.strip('[]').split(',')]

                new_values = change.get('new_value')
                if isinstance(new_values, int):
                    new_values = str(new_values)
                list_new_values = \
                    [item.strip().encode('utf-8')
                     for item in new_values.strip('[]').split(',')]

                vals = []
                for x in list_old_values:
                    if x not in list_new_values:
                        vals.append(x.decode('utf-8'))
                if vals:
                    message +=\
                        '
     • Removed %s: ' %\
                        change.get('col_info')
                    message += '%s
' % ', '.join(vals)

                vals = []
                for x in list_new_values:
                    if x not in list_old_values:
                        vals.append(x.decode('utf-8'))
                if vals:
                    message +=\
                        '
     • Added %s: ' %\
                        change.get('col_info')
                    message += '%s
' % ', '.join(vals)
            return message

        if not tracked_fields:
            return True

        for browse_record in self.browse(cr, uid, ids, context=context):
            initial = initial_values[browse_record.id]
            changes = set()
            tracked_values = {}

            # generate tracked_values data structure: {'col_name': {col_info,
            # new_value, old_value}}
            for col_name, col_info in tracked_fields.items():
                field = self._fields[col_name]
                initial_value = initial[col_name]
                record_value = getattr(browse_record, col_name)

                if record_value == initial_value and\
                        getattr(field, 'track_visibility', None) == 'always':
                    tracked_values[col_name] = dict(
                        col_info=col_info['string'],
                        new_value=convert_for_display(record_value, col_info),
                    )
                # because browse null != False
                elif record_value != initial_value and\
                        (record_value or initial_value):
                    if getattr(field, 'track_visibility', None) in\
                            ['always', 'onchange']:
                        tracked_values[col_name] = dict(
                            col_info=col_info['string'],
                            old_value=convert_for_display(
                                initial_value, col_info),
                            new_value=convert_for_display(
                                record_value, col_info),
                        )
                    if col_name in tracked_fields:
                        changes.add(col_name)
            if not changes:
                continue

            # find subtypes and post messages or log if no subtype found
            subtypes = []
            # By passing this key, that allows to let the subtype empty and so
            # don't sent email because partners_to_notify from
            # mail_message._notify will be empty
            if not context.get('mail_track_log_only'):
                for field, track_info in self._track.items():
                    if field not in changes:
                        continue
                    for subtype, method in track_info.items():
                        if method(self, cr, uid, browse_record, context):
                            subtypes.append(subtype)

            posted = False
            for subtype in subtypes:
                subtype_rec = self.pool.get('ir.model.data').xmlid_to_object(
                    cr, uid, subtype, context=context)
                if not (subtype_rec and subtype_rec.exists()):
                    _logger.debug('subtype %s not found' % subtype)
                    continue
                message = format_message(
                    subtype_rec.description if subtype_rec.description else
                    subtype_rec.name, tracked_values)
                self.message_post(
                    cr, uid, browse_record.id, body=message,
                    subtype=subtype, context=context)
                posted = True
            if not posted:
                message = format_message('', tracked_values)
                self.message_post(
                    cr, uid, browse_record.id,
                    body=message, context=context)
        return True


from pathlib import Path
from experimaestro.compat import cached_property
import importlib
import os
import hashlib
import logging
import inspect
import json
from experimaestro.mkdocs.metaloader import Module
import pkg_resources
from typing import Iterable, Iterator, List, Dict
from .utils import CachedFile, downloadURL
from .settings import UserSettings, Settings

from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from datamaestro.definitions import AbstractDataset

class Compression:
    @staticmethod
    def extension(definition):
        if not definition:
            return ""
        if definition == "gzip":
            return ".gz"

        raise Exception("Not handled compression definition: %s" % definition)

class Context:
    """
    Represents the application context
    """

    MAINDIR = Path(os.environ.get("DATAMAESTRO_DIR", "~/datamaestro")).expanduser()

    INSTANCE = None

    """Main settings"""

    def __init__(self, path: Path = None):
        assert not Context.INSTANCE

        Context.INSTANCE = self
        self._path = path or Context.MAINDIR
        self._dpath = Path(__file__).parents[1]
        self._repository = None
        # self.registry = Registry(self.datapath / "registry.yaml")
        self.keep_downloads = False
        self.traceback = False

        # Read global preferences
        self.settings = Settings.load(self._path / "settings.json")

        # Read user preferences
        path = Path("~").expanduser() / ".config" / "datamaestro" / "user.json"
        self.user_settings = UserSettings.load(path)

    @staticmethod
    def instance():
        if Context.INSTANCE is None:
            Context.INSTANCE = Context()
        return Context.INSTANCE

    @staticmethod
    def remote(host, pythonpath, datapath=None):
        """Create a remote context by connecting to a given host"""
        from experimaestro.rpyc import client

        client = client(hostname=host, pythonpath=pythonpath).__enter__()
        context = client.connection.modules.datamaestro.context.Context(datapath)
        return context

    @staticmethod
    def frompath(path: Path):
        context = Context.instance()

        class ContextManager:
            def __enter__(self):
                self.previous = Context.INSTANCE
                return context

            def __exit__(self, exc_type, exc_val, exc_tb):
                Context.INSTANCE = self.previous

        return ContextManager()

    @property
    def datapath(self):
        return self._path.joinpath("data")

    @property
    def cachepath(self) -> Path:
        return self._path.joinpath("cache")

    @cached_property
    def repositorymap(self) -> Dict[str, "Repository"]:
        return {
            repository.basemodule(): repository for repository in self.repositories()
        }

    def repositories(self) -> Iterable["Repository"]:
        """Returns an iterator over repositories"""
        for entry_point in pkg_resources.iter_entry_points("datamaestro.repositories"):
            yield entry_point.load().instance()

    def repository(self, repositoryid):
        if repositoryid is None:
            return None

        l = [
            x
            for x in pkg_resources.iter_entry_points(
                "datamaestro.repositories", repositoryid
            )
        ]
        if not l:
            raise Exception("No datasets repository named %s", repositoryid)
        if len(l) > 1:
            raise Exception(
                "Too many datasets repository named %s (%d)" % (repositoryid, len(l))
            )
        return l[0].load()(self)

    @property
    def running_test(self):
        return "PYTEST_CURRENT_TEST" in os.environ

    def datasets(self):
        """Returns an iterator over all files"""
        for repository in self.repositories():
            for dataset in repository:
                yield dataset

    def dataset(self, datasetid) -> "AbstractDataset":
        """Get a dataset by ID"""
        for repository in self.repositories():
            dataset = repository.search(datasetid)
            if dataset is not None:
                return dataset

        raise Exception("Dataset {} not found".format(datasetid))

    def downloadURL(self, url, size: int = None):
        """Downloads an URL

        Args:
            url (str): The URL to download
            size (str): The size if known (in bytes)
        """

        self.cachepath.mkdir(exist_ok=True)

        def getPaths(hasher):
            """Returns a cache file path"""
            path = self.cachepath.joinpath(hasher.hexdigest())
            urlpath = path.with_suffix(".url")
            dlpath = path.with_suffix(".dl")

            if urlpath.is_file():
                if urlpath.read_text() != url:
                    # TODO: do something better
                    raise Exception(
                        "Cached URL hash does not match. Clear cache to resolve"
                    )
            return urlpath, dlpath

        hasher = hashlib.sha256(json.dumps(url).encode("utf-8"))

        urlpath, dlpath = getPaths(hasher)
        urlpath.write_text(url)

        if dlpath.is_file():
            logging.debug("Using cached file %s for %s", dlpath, url)
        else:

            logging.info("Downloading %s", url)
            tmppath = dlpath.with_suffix(".tmp")

            downloadURL(url, tmppath, tmppath.is_file(), size=size)

            # Now, rename to original
            tmppath.rename(dlpath)

        return CachedFile(dlpath, keep=self.keep_downloads, others=[urlpath])

    def ask(self, question: str, options: Dict[str, str]):
        """Ask a question to the user"""
        print(question)
        answer = None
        while answer not in options:
            answer = input().strip().lower()
        return options[answer]

class ResolvablePath:
    """An object than can be resolved into a Path"""

    @staticmethod
    def resolve(context, path):
        if isinstance(path, ResolvablePath):
            return path(context)
        return Path(path)

    """Class that returns a path"""

    def __call__(self, context: Context) -> Path:
        raise NotImplementedError()

class DatafolderPath(ResolvablePath):
    def __init__(self, folderid, path):
        self.folderid = folderid
        self.path = path

    def __str__(self):
        return "datafolder-path({folderid}):{path}".format(**self.__dict__)

    def __call__(self, context: Context) -> Path:
        return Path(context.settings.datafolders[self.folderid]) / self.path

class Datasets(Iterable["AbstractDataset"]):
    """A set of datasets contained within a Python module"""

    def __init__(self, module: Module):
        """Initialize with a module"""
        self.module = module
        self._title = None
        self._description = None

    @property
    def id(self):
        return ".".join(self.module.__name__.split(".", 2)[2:])

    @property
    def title(self):
        self._getdoc()
        return self._title

    @property
    def description(self):
        self._getdoc()
        return self._description

    def _getdoc(self):
        if self._title is not None:
            return

        if not self.module.__doc__:
            self._title = ""
            self._description = ""
            return

        intitle = True
        title = []
        description = []
        for line in self.module.__doc__.split("\n"):
            if line.strip() == "" and intitle:
                intitle = False
            else:
                (title if intitle else description).append(line)

        self._title = " ".join(title)
        self._description = "\n".join(description)

    def __iter__(self) -> Iterable["AbstractDataset"]:
        from .definitions import DatasetWrapper

        # Iterates over defined symbols
        for key, value in self.module.__dict__.items():
            # Ensures it is annotated
            if isinstance(value, DatasetWrapper):
                # Ensure it comes from the module
                if self.module.__name__ == value.t.__module__:
                    yield value

class Repository:
    """A repository regroup a set of datasets and their corresponding specific handlers (downloading, filtering, etc.)"""

    def __init__(self, context: Context):
        """Initialize a new repository

        :param context: The dataset main context
        :param basedir: The base directory of the repository
            (by default, the same as the repository class)
        """
        self.context = context
        p = inspect.getabsfile(self.__class__)
        self.basedir = Path(p).parent
        self.configdir = self.basedir.joinpath("config")
        self.id = self.__class__.NAMESPACE
        self.name = self.id
        self.module = self.__class__.__module__
        self.__class__.INSTANCE = self

    @classmethod
    def basemodule(cls):
        return cls.__module__

    @classmethod
    def instance(cls, context=None):
        try:
            return cls.__getattribute__(cls, "INSTANCE")
        except AttributeError:
            return cls(context if context else Context.instance())

    @classmethod
    def version(cls):
        from pkg_resources import get_distribution, DistributionNotFound

        try:
            return get_distribution(cls.__module__).version
        except DistributionNotFound:
            __version__ = None

    def __repr__(self):
        return "Repository(%s)" % self.basedir

    def __hash__(self):
        return self.basedir.__hash__()

    def __eq__(self, other):
        assert isinstance(other, Repository)
        return self.basedir == other.basedir

    def search(self, name: str):
        """Search for a dataset in the definitions"""
        logging.debug("Searching for %s in %s", name, self.configdir)

        candidates: List[str] = []
        components = name.split(".")
        path = self.configdir
        for i, c in enumerate(components):
            path = path / c

            if (path / "__init__.py").is_file():
                candidates.append(".".join(components[: i + 1]))

            if path.with_suffix(".py").is_file():
                candidates.append(".".join(components[: i + 1]))

            if not path.is_dir():
                break

        # Get the dataset
        for candidate in candidates[::-1]:
            logging.debug("Searching in module %s.config.%s", self.module, candidate)
            module = importlib.import_module("%s.config.%s" % (self.module, candidate))
            for value in Datasets(module):
                if name in value.aliases:
                    return value

        return None

    def datasets(self, candidate):
        try:
            module = importlib.import_module("%s.config.%s" % (self.module, candidate))
        except ModuleNotFoundError:
            return None
        return Datasets(module)

    def modules(self) -> Iterator["Module"]:
        """Iterates over all modules in this repository"""
        for _, fid, package in self._modules():
            try:
                module = importlib.import_module(package)
                yield Datasets(module)
            except Exception as e:
                import traceback

                traceback.print_exc()
                logging.error("Error while loading module %s: %s", package, e)

    def _modules(self):
        """Iterate over modules (without parsing them)"""
        for path in self.configdir.rglob("*.py"):
            try:
                relpath = path.relative_to(self.configdir)
                c = [p.name for p in relpath.parents][:-1][::-1]
                if path.name != "__init__.py":
                    c.append(path.stem)
                fid = ".".join(c)

                package = ".".join([self.module, "config", *c])

                yield self, fid, package
            except Exception as e:
                import traceback

                traceback.print_exc()
                logging.error("Error while reading definitions file %s: %s", path, e)

    def __iter__(self) -> Iterator["AbstractDataset"]:
        """Iterates over all datasets in this repository"""
        for datasets in self.modules():
            for dataset in datasets:
                yield dataset

    @property
    def generatedpath(self):
        return self.basedir.joinpath("generated")

    @property
    def datapath(self):
        return self.context.datapath.joinpath(self.id)

    @property
    def extrapath(self):
        """Path to the directory containing extra configuration files"""
        return self.basedir.joinpath("data")

def find_dataset(dataset_id: str):
    """Find a dataset given its id"""
    from .definitions import AbstractDataset

    return AbstractDataset.find(dataset_id)

def prepare_dataset(dataset_id: str):
    """Find a dataset given its id and download the resources"""
    from .definitions import AbstractDataset

    ds = AbstractDataset.find(dataset_id)
    return ds.prepare(download=True)

def get_dataset(dataset_id: str):
    """Find a dataset given its id"""
    from .definitions import AbstractDataset

    ds = AbstractDataset.find(dataset_id)
    return ds.prepare(download=False)


from django.contrib.auth.models import AbstractUser
from django.db import models

class User(AbstractUser):
    MAN = "man"
    WOMEN = "women"
    SEX = [(MAN, MAN), (WOMEN, WOMEN)]

    sex = models.CharField(max_length=6, choices=SEX, default=MAN)

    class Meta:
        verbose_name = "Пользователь"
        verbose_name_plural = "Пользователи"
        ordering = ["username"]


#!/usr/bin/env python
"""
Measure phase ghosts by taking the ratio of the phase background to the frequency background.
"""
import sys
import nibabel
import argparse
import labels
import _utilities as util
import numpy

def nii_4d(in_nii):
     pass

def cummean_nii(in_nii, scale=1, verbose=False):

     # Read in NIBABEL NIFTI object
     in_array = in_nii.get_data()

     # Perform cumulative sum
     out_array = scale * numpy.cumsum( in_array, axis=3)

     # Scale each sum by the number of volumes used in the summation to calculate the mean.
     for ii in range(0,out_array.shape[3]):
          out_array[...,ii] /= ii+1

     # Create nibabel NIFTI object
     out_nii = nibabel.Nifti1Image( out_array, None, in_nii.get_header())

     return out_nii

#
# Main Function
#

if __name__ == '__main__':

     ## Parsing Arguments

     usage = 'usage: %prog [options] arg1 arg2'

     parser = argparse.ArgumentParser(prog='sort_nii')

     parser.add_argument('in_nii',    help='Background labels')

     parser.add_argument('-o','--out_nii', help='Filename of NIFTI output label. (default = cumsum_nii.<in> ) ', default=None)

     parser.add_argument('-s','--scale', help='Multiply NIFTI output array by scale factor ', type=float, default=1.0)
     parser.add_argument('-v','--verbose',  help='Verbose flag',      action='store_true', default=False )

     inArgs = parser.parse_args()

     # Read NIFTI File
     in_nii = nibabel.load(inArgs.in_nii)

     out_nii = cummean_nii(in_nii, inArgs.scale)

     if inArgs.out_nii is None:
          out_nii_filename = util.add_prefix_to_filename( inArgs.in_nii, 'cumsum_nii.')
     else:
          out_nii_filename = inArgs.out_nii

     nibabel.save( out_nii, out_nii_filename)


debug_flag=True

import base64
import hmac
import secrets
import time
import traceback

import flask
from Application.Api.UserContext import UserContext

from Application.Util.ParamsBinder import bind_optional_params, bind_params
from Application.Api.ApiError import ApiError
from Application.App import App
from Crypto.Cipher import AES
import hashlib

#def make_audio_urls(audios:list):# optimize for many audios to avoid instantiation of AES multiple times
#    pass
AUDIO_URL_LIFETIME=1200

def check_audio_url(ip:str,url:str):
    key=bytes.fromhex(App.key)
    raw=b''
    url_i=url.replace('~','=')
    try:
        raw=base64.urlsafe_b64decode(url_i)
        if raw==b'':return False,'Invalid URL'
    except:
        return False,'Invalid URL'
    if len(raw)<(16+32+8):
        return False,'Invalid URL'
    nonce=raw[:16]
    mac=raw[16:16+32]
    b=raw[16+32:]
    cipher=AES.new(key,mode=AES.MODE_EAX,nonce=nonce)
    raw=cipher.decrypt(b)
    _mac=hmac.new(key,msg=nonce+b,digestmod='SHA256')
    pack_id=raw[:4]
    expires=raw[4:8]
    data=raw[8:]
    if not hmac.compare_digest(mac,_mac.digest()):
        return False,'Signature invalid'
    try:
        _ip,exp,_url='.'.join([str(x) for x in pack_id]),int.from_bytes(expires,'big'),base64.urlsafe_b64encode(data).decode().replace('=','')
        if _ip!=ip:
            return False,"Invalid ip"
        if exp<int(time.time()):
            return False,'URL Expired'
        return True,_url
    except:
        print(traceback.format_exc())
        return False,'Invalid URL'

def make_audio_url(ip:str,s:bytes,owner_id:int,audio_id:int,data_url:str):
    key=bytes.fromhex(App.key)
    #action_hashes=[hmac.new(key,msg="{}_{}_{}_{}".format(act,owner_id,audio_id,s.hex()).encode('utf-8'),digestmod='sha256').hexdigest() for act in actions]
    nonce=secrets.token_bytes(16)
    cipher=AES.new(key=key,mode=AES.MODE_EAX,nonce=nonce)
    data_raw=base64.urlsafe_b64decode(data_url)
    pack_ip=bytes([int(x) for x in ip.split('.')])
    ts=int(time.time()+AUDIO_URL_LIFETIME)
    expires=ts.to_bytes(4,'big')
    b=cipher.encrypt(pack_ip+expires+data_raw)
    mac=hmac.new(key,msg=nonce+b,digestmod="SHA256").digest()
    raw=nonce+mac+b
    return base64.urlsafe_b64encode(raw).decode().replace('=','~'),ts
def check_audio_hash(h:str,s:bytes,owner_id:int,audio_id:int):
    key=bytes.fromhex(App.key)
    exp,_h=h.split('_')
    sig=hmac.new(key,msg="ts={};id={}_{},s={};".format(expires,owner_id,audio_id,s.hex()).encode('utf-8'),digestmod='sha256').hexdigest()
    return hmac.compare_digest(_h,sig)

def make_audio_hash(s:bytes,owner_id:int,audio_id:int):
    key=bytes.fromhex(App.key)
    expires=int(time.time()+AUDIO_URL_LIFETIME)
    h="{}_{}".format(expires,hmac.new(key,msg="ts={};id={}_{},s={};".format(expires,owner_id,audio_id,s.hex()).encode('utf-8'),digestmod='sha256').hexdigest())
    return h

class Audios():
    def start_playback(args,user_context:UserContext):
        bind_params(args,{
            'id':str,
            'hash':str
            })
        owner_id,audio_id=args['id'].split('_')
        data=None
        with App.db.make_connection(False,20) as cur:
            cur.execute("""
            SELECT data_url
            FROM audios
            WHERE owner_id=? AND audio_id=?
            """,[int(owner_id),int(audio_id)])
            data=cur.fetchone()
        if not data:return {}
        data_url=data[0]
        s=user_context.session_id.binary
        url,expires=make_audio_url(str(flask.request.remote_addr),s,int(owner_id),int(audio_id),data_url)
        return {
        'url':'http://cdn.notvk.com/audios/'+url+'/128.mp3',
        'expires':expires
        }

    def search(args,user_context:UserContext):
        bind_params(args,{
            'q':str,
            'count':int,
            'offset':int,
        })
        bind_optional_params(args,{
            'name':str,
            'artist':str,
            'owner_id':int
        })
        data=[]
        audios=[]
        s=user_context.session_id.binary
        q=str(args['q']).strip()
        if len(q.strip())==0:
            return []
        count=args['count']
        offset=args['offset']
        where=''
        #_args=[q,'%{}%'.format(q),'%{}%'.format(q)]
        _args=[q]
        if 'owner_id' in args:
            owner_id=args['owner_id']
            where="owner_id=? AND"
            _args.append(owner_id)
        _args.append(count)
        _args.append(offset)
        #
        """
            WITH tempvar AS (SELECT ? AS q)
		    SELECT audios.id,audios.owner_id,audios.audio_id,audios.data_url,audios.duration,audios.artist,audios.name,
			instr(lower(audios.name),tempvar.q) AS npos,
			instr(lower(audios.artist),tempvar.q) AS apos
            FROM audios,tempvar
            WHERE {}  ( npos OR apos)
            ORDER BY MIN(npos,apos))
            LIMIT ?
            OFFSET ?
            """
        #
        with App.db.make_connection(False,20) as cur:
            cur.execute("""
            WITH tempvar AS (SELECT lower(?) AS q)
		    SELECT audios.id,audios.owner_id,audios.audio_id,audios.data_url,audios.duration,audios.artist,audios.name,audios.is_official,audios.thumbnail,audios.text,audios.explicit,audios.genre,
			instr(lower(audios.name),tempvar.q) AS npos,
			instr(lower(audios.artist),tempvar.q) AS apos
            FROM audios,tempvar
            WHERE   ( npos+apos)!=0
            ORDER BY  ( SELECT CASE WHEN npos==0 THEN apos WHEN apos==0 THEN npos ELSE MIN(apos,npos) END u)
            LIMIT ?
            OFFSET ?
            """.format(where),_args)
            data=cur.fetchall()
        if not data:
            return []
        for x in data:
            i,owner_id,audio_id,data_url,duration,artist,name,is_official,thumbnail,text,explicit,genre,unused1,unused2=x
            url,expires=make_audio_url(str(flask.request.remote_addr),s,int(owner_id),int(audio_id),data_url)
            audios.append({
                'duration':duration,
                'name':name,
                'artist':artist,
                'hash':make_audio_hash(s,owner_id,audio_id),
                'id':"{}_{}".format(owner_id,audio_id),
                'url':'http://cdn.notvk.com/audios/'+url+'/128.mp3',
                'expires':expires,
                'is_official':bool(is_official),
                'thumbnail':thumbnail,
                'text':text,
                'explicit':bool(explicit),
                'genre':genre
            })
        return audios
    def get(args,user_context:UserContext):
        bind_params(args,{
            'owner_id':int,
            'count':int,
            'offset':int
        })

        data=[]
        audios=[]
        s=user_context.session_id.binary
        owner_id=args['owner_id']
        count=args['count']
        offset=args['offset']
        with App.db.make_connection(False,20) as cur:
            cur.execute("""
            SELECT id,audio_id,data_url,duration,name,artist,is_official,thumbnail,text,explicit,genre
            FROM audios
            WHERE owner_id = ?
            ORDER BY audio_id DESC
            LIMIT ?
            OFFSET ?
            """,[owner_id,count,offset])
            data=cur.fetchall()
        if not data:
            return []
        for x in data:
            _id,audio_id,data_url,duration,name,artist,is_official,thumbnail,text,explicit,genre=x
            url,expires=make_audio_url(str(flask.request.remote_addr),s,int(owner_id),int(audio_id),data_url)
            audios.append({
                'duration':duration,
                'name':name,
                'artist':artist,
                'hash':make_audio_hash(s,owner_id,audio_id),
                'id':"{}_{}".format(owner_id,_id),
                'url':'http://cdn.notvk.com/audios/'+url+'/128.mp3',
                'expires':expires,
                'is_official':bool(is_official),
                'thumbnail':thumbnail,
                'text':text,
                'explicit':bool(explicit),
                'genre':genre

            })
        return audios


import os
import random
import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.datasets import load_iris, load_breast_cancer, load_wine, make_blobs
from sklearn.model_selection import train_test_split

project_dir = os.path.dirname(os.getcwd())

# This file describes utility functions for loading and creating (dummy) datasets.

def load(subsample_train_frac=None, prop_train=None, prop_test=None, is_iid=True, verbose=None):
    # This is where we locate the .csv files and read them as pandas dataframes.
    iris = load_iris()
    df = pd.DataFrame(iris.data, columns=iris.feature_names)
    df_train, df_test = train_test_split(df, test_size=prop_test)
    # print(df.columns)
    if verbose:
        print(df.head())
    return df_train, df_test

def load_data(dataset=None, is_iid=True, num_devices=3, split_train_test=False, prop_test=None, dims=2, samples=100,
              clusters=3, verbose=False):
    eligible_datasets = ['iris', 'breast cancer', 'wine', 'heart disease', 'forest types', 'blobs', 'dummy']
    if dataset not in eligible_datasets:
        print("No dataset was requested or the requested dataset could not be retrieved.")
        print("Defaulting to generating blobs...")
        return create_blobs(dims=dims, samples=samples, clusters=clusters, split_train_test=split_train_test,
                            prop_test=prop_test, is_iid=is_iid, num_devices=num_devices, verbose=verbose)
    else:
        if dataset == 'iris':
            iris = load_iris()
            df = pd.DataFrame(iris.data, columns=iris.feature_names)
            labels = iris.target
            return split_data(df.to_numpy(), labels, num_devices, split_train_test, prop_test, is_iid)

        if dataset == 'breast cancer':
            breast_cancer = load_breast_cancer()
            df = pd.DataFrame(breast_cancer.data, columns=breast_cancer.feature_names)
            labels = breast_cancer.target
            return split_data(df.to_numpy(), labels, num_devices, split_train_test, prop_test, is_iid)

        if dataset == 'wine':
            wine = load_wine()
            df = pd.DataFrame(wine.data, columns=wine.feature_names)
            labels = wine.target
            return split_data(df.to_numpy(), labels, num_devices, split_train_test, prop_test, is_iid)

        if dataset == 'heart disease':
            df = pd.read_csv("data/heart_disease_cleveland.csv")  # not sure how to retrieve just labels here...
            # this implementation does not use split_data for now, because it would require us to extract labels.
            if split_train_test and prop_test is not None:
                df_train, df_test = train_test_split(df, test_size=prop_test)
                if not is_iid:
                    return NotImplementedError
                else:
                    return np.array_split(df_train, num_devices), np.array_split(df_test, num_devices)
            elif split_train_test:
                df_train, df_test = train_test_split(df, test_size=.2)
                if not is_iid:
                    return NotImplementedError
                else:
                    return np.array_split(df_train, num_devices), np.array_split(df_test, num_devices)
            else:
                return np.array_split(df, num_devices)

        if dataset == 'forest types':
            cur_file = os.path.abspath(os.path.dirname(__file__))
            covtype_file = os.path.join(cur_file, 'data/forest_covertypes.csv')
            df = pd.read_csv(covtype_file)
            labels = df['Cover_Type']
            df = df.drop('Cover_Type', axis=1)
            print(df.shape)
            # this implementation does not use split_data for now, because it would require us to extract labels.
            if split_train_test and prop_test is not None:
                df_train, df_test = train_test_split(df, test_size=prop_test)
                if not is_iid:
                    return NotImplementedError
                else:
                    return np.array_split(df_train, num_devices), np.array_split(df_test, num_devices)
            elif split_train_test:
                df_train, df_test = train_test_split(df, test_size=.2)
                if not is_iid:
                    return NotImplementedError
                else:
                    return np.array_split(df_train, num_devices), np.array_split(df_test, num_devices)
            else:
                return np.array_split(df.to_numpy(), num_devices), np.array_split(labels.to_numpy(), num_devices)

        if dataset == 'dummy':
            clients_per_cluster = num_devices//clusters
            data, _ = create_dummy_data(dims=dims, clients_per_cluster=clients_per_cluster,
                                        samples_each=samples//num_devices, clusters=clusters, verbose=True)
            print(len(data))
            return data, _

        else:  # default case
            print("Generating blobs...")
            create_blobs(dims=dims, samples=samples, clusters=clusters, split_train_test=split_train_test,
                         prop_test=prop_test, is_iid=is_iid, num_devices=num_devices, verbose=verbose)

def split_data(df, labels, num_devices, split_train_test=False, prop_test=None, is_iid=True):
    if not is_iid:
        if split_train_test:
            if prop_test is not None:
                prop = prop_test
            else:
                prop = .2
            num_test = int(prop * len(df))
            order_train = np.argsort(labels[num_test:])
            order_test = np.argsort(labels[:num_test])
            df_train = df[order_train]
            df_test = df[order_test]
            exp_train_per_device = round(len(df_train)/num_devices)
            exp_test_per_device = round(len(df_test)/num_devices)
            range_sizes_train = range(exp_train_per_device - exp_train_per_device//4,
                                      exp_train_per_device + exp_train_per_device//4)
            range_sizes_test = range(exp_test_per_device - exp_test_per_device//4,
                                     exp_test_per_device + exp_test_per_device//4)
            rand_sizes_train = [random.choice(range_sizes_train)]
            rand_sizes_test = [random.choice(range_sizes_test)]
            for i in range(1, num_devices):
                rand_sizes_train.append(random.choice(range_sizes_train) + rand_sizes_train[i - 1])
                rand_sizes_test.append(random.choice(range_sizes_test) + rand_sizes_test[i - 1])
            return np.split(df_test, rand_sizes_test), np.split(df_train, rand_sizes_train), \
                np.split(labels[:num_test][order_test], rand_sizes_test), \
                np.split(labels[num_test:][order_train], rand_sizes_train)  # test, train, y_test, y_train
        else:
            order = np.argsort(labels)
            exp_records_per_device = round(len(df)/num_devices)
            range_sizes = range(exp_records_per_device - exp_records_per_device//4,
                                exp_records_per_device + exp_records_per_device//4)
            rand_sizes = [random.choice(range_sizes)]
            for i in range(1, num_devices):
                rand_sizes.append(random.choice(range_sizes) + rand_sizes[i-1])
            return np.split(df[order], rand_sizes), np.split(labels[order], rand_sizes)  # X, y
    elif is_iid:
        if split_train_test:
            if prop_test is not None:
                prop = prop_test
            else:
                prop = .2
            num_test = int(prop * len(df))
            exp_train_per_device = round((len(df)-num_test)/num_devices)
            exp_test_per_device = round(num_test/num_devices)
            range_sizes_train = range(exp_train_per_device - exp_train_per_device//4,
                                      exp_train_per_device + exp_train_per_device//4)
            range_sizes_test = range(exp_test_per_device - exp_test_per_device//4,
                                     exp_test_per_device + exp_test_per_device//4)
            rand_sizes_train = [random.choice(range_sizes_train)]
            rand_sizes_test = [random.choice(range_sizes_test)]
            for i in range(1, num_devices):
                rand_sizes_train.append(random.choice(range_sizes_train) + rand_sizes_train[i-1])
                rand_sizes_test.append(random.choice(range_sizes_test) + rand_sizes_test[i-1])
            return np.split(df[:num_test], rand_sizes_test[:-1]), np.split(df[num_test:], rand_sizes_train[:-1]), \
                np.split(labels[:num_test], rand_sizes_test), np.split(labels[num_test:], rand_sizes_train)
            # test, train, y_test, y_train
        else:
            exp_records_per_device = round(len(df) / num_devices)
            range_sizes = range(exp_records_per_device - exp_records_per_device//4,
                                exp_records_per_device + exp_records_per_device//4)
            rand_sizes = [random.choice(range_sizes)]
            for i in range(1, num_devices):
                rand_sizes.append(random.choice(range_sizes) + rand_sizes[i-1])
            return np.split(df, rand_sizes), np.split(labels, rand_sizes)  # X, y
    else:  # this case should never be reached, but we include it anyway
        exp_records_per_device = round(len(df) / num_devices)
        range_sizes = range(exp_records_per_device - exp_records_per_device//4,
                            exp_records_per_device + exp_records_per_device//4)
        rand_sizes = []
        for i in range(num_devices):
            rand_sizes.append(random.choice(range_sizes))
        return np.split(df, rand_sizes), np.split(labels, rand_sizes)  # X, y

# Function that returns the bounds (min, max) for each dimension in dataset df. Expects df to be a np.array.
# Should be a matrix describing n records having i features (dimensions).
def obtain_bounds(df):
    min_vals = df.min(axis=0)
    max_vals = df.max(axis=0)
    if isinstance(min_vals, pd.Series):
        min_vals = min_vals.to_numpy()
    if isinstance(max_vals, pd.Series):
        max_vals = max_vals.to_numpy()
    return min_vals.flatten(), max_vals.flatten()

def obtain_bounds_multiple(dfs):
    min_vals, max_vals = obtain_bounds(np.asarray(dfs[0]))
    for df in dfs[1:]:
        min_vals_df, max_vals_df = obtain_bounds(df)
        for dim in range(len(min_vals)):
            if min_vals_df[dim] < min_vals[dim]:
                min_vals[dim] = min_vals_df[dim]
            if max_vals_df[dim] > max_vals[dim]:
                max_vals[dim] = max_vals_df[dim]
    if isinstance(min_vals, pd.Series):
        min_vals = min_vals.to_numpy()
    if isinstance(max_vals, pd.Series):
        max_vals = max_vals.to_numpy()
    return min_vals, max_vals

def create_dummy_data(dims=1, clients_per_cluster=10, samples_each=10, clusters=10, scale=.5, verbose=False):
    np.random.seed(42)  # 42, 420, 4200, 42000, 420000 = 5 runs.
    num_clients = clients_per_cluster * clusters
    print(f"Number of clients set to: {num_clients}.")
    # create gaussian data set, per client one mean
    means = np.arange(1, clusters + 1)
    means = np.tile(A=means, reps=clients_per_cluster)
    noise = np.random.normal(loc=0.0, scale=scale, size=(num_clients, samples_each, dims))
    data = np.expand_dims(np.expand_dims(means, axis=1), axis=2) + noise
    if verbose:
        # print(means)
        # print(noise)
        print("dummy data shape: ", data.shape)
    data = [data[i] for i in range(num_clients)]
    return data, means

# Function to create blobs that are very clearly structured as clusters.
# Can already obtain train and test sets from this within this function.
def create_blobs(dims=2, samples=100, clusters=3, split_train_test=False, prop_test=None, is_iid=True, num_devices=3,
                 verbose=False):
    X, y = make_blobs(n_samples=samples, centers=clusters, n_features=dims, random_state=42)

    if verbose:
        print(X.shape)
        print(len(y), y)

    return split_data(X, y, num_devices, split_train_test, prop_test, is_iid)


import folium, pandas, ast
import json
# -*- coding: utf-8 -*-
locations_p = []
geos_p = []
files = 'tweets_#gopatriots.txt'
# get geo data only from rows with non-empty values
with open(files,'r') as ifile:
        for line in ifile.readlines():
            tweet = json.loads(line)
            if tweet['tweet']['geo'] is not None:
            	locations_p.append(tweet['tweet']['geo']['coordinates'])

ifile.close()

locations_h = []
files = 'tweets_#gohawks.txt'
with open(files,'r') as ifile:
        for line in ifile.readlines():
            tweet = json.loads(line)
            if tweet['tweet']['geo'] is not None:
            	locations_h.append(tweet['tweet']['geo']['coordinates'])

ifile.close()
# for location in locations:
#   # add to geos array an evaluated python literal syntax of the data
#  	geos.append(ast.literal_eval(location))

# initialize and create map
tweet_map= folium.Map(location=[52.8, -2], tiles='Mapbox Bright', zoom_start=7)

# add markers
for geo in locations_p:
	tweet_map.circle_marker(location=geo, radius=250, line_color='#E91616')

for geo in locations_h:
	tweet_map.circle_marker(location=geo, radius=250, line_color='#3186cc')

tweet_map.create_map(path='map.html')


# coding: utf-8

# In[1]:

import requests
import json
from pprint import pprint
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt

# In[2]:

def view_imdb_data_votes(season_number,episode_number):
    url="http://www.omdbapi.com/?t="
    season="&Season="+str(season_number)
    episode="&Episode="+str(episode_number)
    api_key="&apikey=7329004f"
    response=requests.get(url+"Game of Thrones" +season+episode+api_key)
    data=response.json()
    return data["imdbVotes"]

# In[3]:

def view_imdb_data_ratings(season_number,episode_number):
    url="http://www.omdbapi.com/?t="
    season="&Season="+str(season_number)
    episode="&Episode="+str(episode_number)
    api_key="&apikey=7329004f"
    response=requests.get(url+"Game of Thrones" +season+episode+api_key)
    data=response.json()
    return data["imdbRating"]

# In[4]:

#season_one votes
season_one=[]
for y in range(11):
        try:
            season_one.append(view_imdb_data_votes(1,y))
        except:
                continue

# In[5]:

season_one
for i in range(len(season_one)):
    season_one[i]=int(season_one[i])

# In[6]:

#season_two
season_two=[]
for y in range(11):
        try:
            season_two.append(view_imdb_data_votes(2,y))
        except:
                continue

# In[7]:

season_two
for i in range(len(season_two)):
    season_two[i]=int(season_two[i])

# In[8]:

#season_three
season_three=[]
for y in range(11):
    try:
        season_three.append(view_imdb_data_votes(3,y))
    except:
        continue

# In[9]:

season_three
for i in range(len(season_three)):
    season_three[i]=int(season_three[i])

# In[10]:

#season_four
season_four=[]
for y in range(11):
    try:
        season_four.append(view_imdb_data_votes(4,y))
    except:
        continue

# In[11]:

season_four
for i in range(len(season_four)):
    season_four[i]=int(season_four[i])

# In[12]:

#season_five
season_five=[]
for y in range(11):
    try:
        season_five.append(view_imdb_data_votes(5,y))
    except:
        continue

# In[13]:

season_five
for i in range(len(season_five)):
    season_five[i]=int(season_five[i])

# In[14]:

#season 6
season_six=[]
for y in range(11):
    try:
        season_six.append(view_imdb_data_votes(6,y))
    except:
        continue

# In[15]:

season_six
for i in range(len(season_six)):
    season_six[i]=int(season_six[i])

# In[16]:

#season 7
season_seven=[]
for y in range(8):
        try:
            season_seven.append(view_imdb_data_votes(7,y))
        except:
            continue

# In[17]:

for i in range(len(season_seven)):
    season_seven[i]=int(season_seven[i])

# In[18]:

votes_df=pd.DataFrame({"Season 1":season_one,
                        "Season 2":season_two,
                         "Season 3":season_three,
                          "Season 4":season_four,
                          "Season 5":season_five,
                          "Season 6":season_six,
                          })

# In[19]:

votes_df_season_seven=pd.DataFrame({"Season 7":season_seven})

# In[20]:

#now for the ratings
season_one_ratings=[]
for y in range(11):
        try:
            season_one_ratings.append(view_imdb_data_ratings(1,y))
        except:
            continue

# In[21]:

season_one_ratings
for i in range(len(season_one_ratings)):
    season_one_ratings[i]=float(season_one_ratings[i])

# In[22]:

season_two_ratings=[]
for y in range(11):
    try:
        season_two_ratings.append(view_imdb_data_ratings(2,y))
    except:
        continue

# In[23]:

season_two_ratings
for i in range(len(season_two_ratings)):
    season_two_ratings[i]=float(season_two_ratings[i])

# In[24]:

season_three_ratings=[]
for y in range(11):
    try:
        season_three_ratings.append(view_imdb_data_ratings(3,y))
    except:
        continue

# In[25]:

season_three_ratings
for i in range(len(season_three_ratings)):
    season_three_ratings[i]=float(season_three_ratings[i])

# In[26]:

season_four_ratings=[]
for y in range(11):
    try:
        season_four_ratings.append(view_imdb_data_ratings(4,y))
    except:
        continue

# In[27]:

season_four_ratings
for i in range(len(season_four_ratings)):
    season_four_ratings[i]=float(season_four_ratings[i])

# In[28]:

season_five_ratings=[]
for y in range(11):
    try:
        season_five_ratings.append(view_imdb_data_ratings(5,y))
    except:
        continue

# In[29]:

season_five_ratings
for i in range(len(season_five_ratings)):
    season_five_ratings[i]=float(season_five_ratings[i])

# In[30]:

season_six_ratings=[]
for y in range(11):
    try:
        season_six_ratings.append(view_imdb_data_ratings(6,y))
    except:
        continue

# In[31]:

season_six_ratings
for i in range(len(season_six_ratings)):
    season_six_ratings[i]=float(season_six_ratings[i])

# In[32]:

season_seven_ratings=[]
for y in range(8):
    try:
        season_seven_ratings.append(view_imdb_data_ratings(7,y))
    except:
        continue

# In[33]:

for i in range(len(season_seven_ratings)):
    season_seven_ratings[i]=float(season_seven_ratings[i])

# In[34]:

ratings_df=pd.DataFrame({"Season 1":season_one_ratings,
                         "Season 2":season_two_ratings,
                          "Season 3":season_three_ratings,
                          "Season 4":season_four_ratings,
                          "Season 5":season_five_ratings,
                          "Season 6":season_six_ratings,
                           })

# In[35]:

ratings_season_seven_df=pd.DataFrame({"Season 7":season_seven_ratings})

# In[36]:

x_axis=["Ep.1","Ep.2","Ep.3","Ep.4","Ep.5","Ep.6","Ep.7","Ep.8","Ep.9","Ep.10"]
y_axis=ratings_df["Season 1"]
plt.plot(x_axis,y_axis, label="Season 1",color="black")
y_axis=ratings_df["Season 2"]
plt.plot(x_axis,y_axis, label="Season 2", color="lightcoral")
y_axis=ratings_df["Season 3"]
plt.plot(x_axis,y_axis, label="Season 3", color="lightskyblue")
y_axis=ratings_df["Season 4"]
plt.plot(x_axis,y_axis, label="Season 4", color="red")
y_axis=ratings_df["Season 5"]
plt.plot(x_axis,y_axis, label="Season 5", color="darkblue")
y_axis=ratings_df["Season 6"]
plt.plot(x_axis,y_axis, label="Season 6", color="green")
x_axis=["Ep.1","Ep.2","Ep.3","Ep.4","Ep.5","Ep.6","Ep.7"]
y_axis=ratings_season_seven_df
plt.plot(x_axis,y_axis, label="Season 7", color="orange")
plt.legend(bbox_to_anchor=(1.05, 1), loc=2, borderaxespad=0.)
plt.title("Ratings Per Episode in Each Season")
plt.xlabel("Episode")
plt.ylabel("Rating Score")
plt.savefig("RatingsPerEpisodeinEachSeason")
plt.show()

# In[37]:

x_axis=["Ep.1","Ep.2","Ep.3","Ep.4","Ep.5","Ep.6","Ep.7","Ep.8","Ep.9","Ep.10"]
y_axis=votes_df["Season 1"]
plt.plot(x_axis,y_axis, label="Season 1",color="black")
y_axis=votes_df["Season 2"]
plt.plot(x_axis,y_axis, label="Season 2",color="lightcoral")
y_axis=votes_df["Season 3"]
plt.plot(x_axis,y_axis, label="Season 3",color="lightskyblue")
y_axis=votes_df["Season 4"]
plt.plot(x_axis,y_axis, label="Season 4",color="red")
y_axis=votes_df["Season 5"]
plt.plot(x_axis,y_axis, label="Season 5",color="purple")
y_axis=votes_df["Season 6"]
plt.plot(x_axis,y_axis, label="Season 6",color="green")
x_axis=["Ep.1","Ep.2","Ep.3","Ep.4","Ep.5","Ep.6","Ep.7"]
y_axis=votes_df_season_seven
plt.plot(x_axis,y_axis, label="Season 7",color="darkblue")
plt.title("IMdB votes per Episode by Season")
plt.xlabel("Episode Number")
plt.ylabel("Number of Votes Per Episode ")
plt.plot(x_axis,y_axis)
plt.legend()
plt.savefig("IMdBvotesperEpisodebySeason")
plt.show()

# In[38]:

avg_rating_season_one=ratings_df["Season 1"].mean()
avg_rating_season_two=ratings_df["Season 2"].mean()
avg_rating_season_three=ratings_df["Season 3"].mean()
avg_rating_season_four=ratings_df["Season 4"].mean()
avg_rating_season_five=ratings_df["Season 5"].mean()
avg_rating_season_six=ratings_df["Season 6"].mean()
avg_rating_season_seven=ratings_season_seven_df.mean()

# In[39]:

x_axis=["Season 1"]
y_axis=avg_rating_season_one
plt.bar(x_axis,y_axis)
x_axis=["Season 2"]
y_axis=avg_rating_season_two
plt.bar(x_axis,y_axis)
x_axis=["Season 3"]
y_axis=avg_rating_season_three
plt.bar(x_axis,y_axis)
x_axis=["Season 4"]
y_axis=avg_rating_season_four
plt.bar(x_axis,y_axis)
x_axis=["Season 5"]
y_axis=avg_rating_season_five
plt.bar(x_axis,y_axis)
x_axis=["Season 6"]
y_axis=avg_rating_season_six
plt.bar(x_axis,y_axis)
x_axis=["Season 7"]
y_axis=avg_rating_season_seven
plt.bar(x_axis,y_axis)
plt.ylim(6.0,10.0)
plt.title("Average Ratings Per Season")
plt.xlabel("Season")
plt.ylabel("Average Rating")
plt.xticks(rotation=45)
plt.savefig("AverageRatingsPerSeason")
plt.show()

# In[40]:

avg_votes_season_one=votes_df["Season 1"].mean()
avg_votes_season_two=votes_df["Season 2"].mean()
avg_votes_season_three=votes_df["Season 3"].mean()
avg_votes_season_four=votes_df["Season 4"].mean()
avg_votes_season_five=votes_df["Season 5"].mean()
avg_votes_season_six=votes_df["Season 6"].mean()
avg_votes_season_seven=votes_df_season_seven.mean()

# In[41]:

x_axis="Season 1"
y_axis=avg_votes_season_one
plt.bar(x_axis,y_axis)
x_axis="Season 2"
y_axis=avg_votes_season_two
plt.bar(x_axis,y_axis)
x_axis="Season 3"
y_axis=avg_votes_season_three
plt.bar(x_axis,y_axis)
x_axis="Season 4"
y_axis=avg_votes_season_four
plt.bar(x_axis,y_axis)
x_axis="Season 5"
y_axis=avg_votes_season_five
plt.bar(x_axis,y_axis)
x_axis="Season 6"
y_axis=avg_votes_season_six
plt.bar(x_axis,y_axis)
x_axis="Season 7"
y_axis=avg_votes_season_seven
plt.bar(x_axis,y_axis)
plt.xticks(rotation=45)
plt.title("Average Votes per Season")
plt.xlabel("Season")
plt.ylabel("Average Number of Votes")
plt.savefig("AverageVotesperSeason")
plt.show()


import datetime
import calendar
import configparser
import os

class Utils:
    @staticmethod
    def get_business_date():
        today = datetime.datetime.now()
        if today.isoweekday() == 6 or today.isoweekday() == 7:
            while today.isoweekday() == 6 or today.isoweekday() == 7:
                one_day = datetime.timedelta(days=1)
                today = today - one_day
        today = today.strftime("%Y-%m-%d")
        return today

    @staticmethod
    def read_properties():
        config = configparser.RawConfigParser()
        config.read(os.getcwd() + "/data/indicator.properties")
        return config


from selenium.webdriver.common.by import By
from behave import given, when, then
from selenium.webdriver.support import expected_conditions as EC
from time import sleep

ADD_TO_CART = (By.CSS_SELECTOR, "button[type='submit'].product-form__submit.button.button--secondary")
ADD_TO_CART_CONFIRM = (By.CSS_SELECTOR, "h3.label")
VIEW_CART = (By.CSS_SELECTOR, "div.button-container a[href='/cart']")

@when('Click to add product to cart')
def add_to_cart(context):
    context.app.product_detail_page.add_to_cart()
    sleep(5)

    #context.driver.find_element(*ADD_TO_CART).click()

@when("Click View my cart")
def click_view_cart(context):
    context.app.product_detail_page.click_view_cart()
    # context.driver.wait.until(EC.element_to_be_clickable(VIEW_CART)).click()
    # sleep(3)

@then('Verify that the Subtotal is shown for confirmation')
def verify_add_to_cart_confirm(context):
    context.app.product_detail_page.verify_add_to_cart_confirm()
    # expected_text = 'Subtotal'
    # actual_text = context.driver.find_element(*ADD_TO_CART_CONFIRM).text
    # assert actual_text == expected_text, f'Expected {expected_text} but got {actual_text}'


from django.contrib.auth.models import AbstractUser
from django.db import models
from django.utils.translation import gettext_lazy as _
from django.utils.functional import cached_property

from database.utils import translate_doc
from database.models.data_collections.data_collections import Collection

@translate_doc
class User(AbstractUser):
    help_text = _('''
    User Model

    People using irekua must be previously registered and should provide
    minimal personal information. This is to track contributions and to control
    access to data.

    Users can belong to collections (:model:`database.Collection`), possess
    devices (:model:`database.PhysicalDevice`), sign licences
    (:model:`database.Licence`), upload items (:model:`database.Item`),
    annotate data (:model:`database.Annotation`), and more.
    ''')

    institution = models.ForeignKey(
        'Institution',
        on_delete=models.PROTECT,
        db_column='institution_id',
        verbose_name=_('institution'),
        help_text=_('Institution to which user belongs'),
        blank=True,
        null=True)
    is_developer = models.BooleanField(
        db_column='is_developer',
        verbose_name=_('is developer'),
        help_text=_('Flag to indicate if user is a model developer'),
        blank=False,
        null=False,
        default=False)
    is_curator = models.BooleanField(
        db_column='is_curator',
        verbose_name=_('is curator'),
        help_text=_('Flag to indicate if user is a curator'),
        blank=False,
        null=False,
        default=False)
    is_model = models.BooleanField(
        db_column='is_model',
        verbose_name=_('is model'),
        help_text=_('Flag to indicate if user is an AI model'),
        blank=False,
        null=False,
        default=False)

    class Meta:
        verbose_name = _('User')
        verbose_name_plural = _('Users')
        unique_together = [
            ['email',],
        ]

    @property
    def is_special(self):
        return self.is_developer | self.is_curator | self.is_model | self.is_superuser

    @cached_property
    def is_collection_type_admin(self):
        return self.collectiontype_set.exists()

    @cached_property
    def managed_collections(self):
        queryset = Collection.objects.filter(
            collection_type__in=self.collectiontype_set.all())
        return queryset


"""
Python3.6+ only
"""
import re
from pathlib import Path

from pie import *

class env(env):
    @classmethod
    def _parse_lines(cls,ls):
        """Parses lines and returns a dict."""
        d={}
        for i,l in enumerate(ls,1):
            l=l.strip()
            # skip blank lines and comments
            if not l or l.startswith('#'): continue
            # ignore `set` and `export` and split into pre and post `=` parts
            mo=re.match(r'^(set\s+|export\s+)?(?P<key>[^=\s]+)\s*=(?P<value>.*)',l)
            if mo:
                d[mo.group('key')]=mo.group('value')
            else:
                raise Exception(f'Failed to parse line {i}: "{l}"')
        return d

    @classmethod
    def from_files(cls,*files):
        d={}
        # turn files into Path objects
        env_files=[Path(f) for f in files]
        # and filter out files that don't exist
        existing_env_files=[]
        for ef in env_files:
            if ef.exists():
                existing_env_files.append(ef)
            else:
                print(f'INFO: {ef} not found')
        # parse all existing files in order
        for p in existing_env_files:
            with p.open('r',encoding='utf-8') as fin:
                file_d=cls._parse_lines(fin.readlines())
                d.update(file_d)
        return cls(d)

    @classmethod
    def dump_env(cls):
        import os
        for k in sorted(os.environ.keys()):
            v=os.environ[k]
            print(f'{k}={v}')


import h5py
import os
import shutil
import argparse
from genome import *

parser = argparse.ArgumentParser()
parser.add_argument("read_basedir", help="base directory of resquiggled fast5 files")
parser.add_argument("output_dir", help="directory to copy files to (must exist)")
parser.add_argument("reference", help="fasta file with reference genome")
parser.add_argument("begin", help="begining of interval (inclusive)")
parser.add_argument("end", help="end of interval (exclusive)")

args = parser.parse_args()

if args.read_basedir == args.output_dir:
  print("read_basedir and output_dir must be different")
  exit(1)

begin = int(args.begin)
end = int(args.end)
if end - begin <= 0:
  print("interval must have positive length")
  exit(1)

read_files = [file for file in os.listdir(args.read_basedir) if not os.path.isdir(os.path.join(args.read_basedir, file))]
read_files = filter(lambda x : x[-6:] == ".fast5", read_files)

reference = load_fasta(args.reference)[0].bases

for read_file in read_files:
  filename = os.path.join(args.read_basedir, read_file)
  good = False
  print(filename)
  try:
    with h5py.File(filename, "r") as f:
      read_id = list(f['Raw/Reads'].keys())[0]

      alignment_meta = f['Analyses/RawGenomeCorrected_000/BaseCalled_template/Alignment'].attrs
      start_in_reference = alignment_meta['mapped_start']
      end_in_reference = alignment_meta['mapped_end']
      strand = alignment_meta['mapped_strand'].decode('ascii')
      if strand == '-':
        start_in_reference, end_in_reference = len(reference) - end_in_reference, len(reference) - start_in_reference
      if min(end_in_reference, end) - max(start_in_reference, begin) > 0:
        good = True

  except KeyError:
    continue
  if good:
    copy_name = os.path.join(args.output_dir, read_file)
    print("copying {} to {}".format(filename, copy_name))
    shutil.copy2(filename, copy_name)


from flask import Flask
from flask_restful import Api
import logging as log

from api.config.apiconf import config

from api.views import VRStats,VRTopPlaces,\
    VRClassifPlaces,VRClassifPlacesAccuracy,VRTop10Places

app = Flask(__name__)
ap = Api(app)

ap.add_resource(VRStats,                    '/api/stats')
ap.add_resource(VRTopPlaces,                '/api/top_places/<string:inp_number>')
ap.add_resource(VRTop10Places,              '/api/top_places')
ap.add_resource(VRClassifPlaces,            '/api/classify')
ap.add_resource(VRClassifPlacesAccuracy,    '/api/classif_accuracy')

if __name__ == '__main__':

    log.basicConfig(filename=config['log']['file'], level=log.DEBUG)

    app.run(debug   = bool(config['flask']['debug']),
            host    = config['flask']['host'],
            port    = int(config['flask']['port'])
            )

    log.info("Flask Restful server is started ...")


# Install Python Packages
#!pip install openai tiktoken

# Import Python Packages
import platform
import os
import openai
import tiktoken
import time

print('Python: ', platform.python_version())

# Count the Number of Tokens
def count_tokens(filename):
    encoding = tiktoken.get_encoding("gpt2")
    with open(filename, 'r') as f:
        text = f.read()

    input_ids = encoding.encode(text)
    num_tokens = len(input_ids)
    return num_tokens

# Count the Number of Tokens in a String
def count_tokens_in_string(text):
    encoding = tiktoken.get_encoding("gpt2")
    input_ids = encoding.encode(text)
    num_tokens = len(input_ids)
    return num_tokens

filename = "inputFile.txt"
num_tokens = count_tokens(filename=filename)
print("Number of tokens:  ", num_tokens)

# Break up text into chunks of 2000 tokens with an overlap of 100 tokens
def break_up_file_to_chunks(filename, chunk_size=2000, overlap=100):
    encoding = tiktoken.get_encoding("gpt2")
    with open(filename, 'r') as f:
        text = f.read()

    tokens = encoding.encode(text)
    num_tokens = len(tokens)

    chunks = []
    for i in range(0, num_tokens, chunk_size - overlap):
        chunk = tokens[i:i + chunk_size]
        chunks.append(chunk)

    return chunks

# Modified the function break_up_file_to_chunks to work with a list of strings
def break_up_text_to_chunks(text_list, chunk_size=2000, overlap=100):
    encoding = tiktoken.get_encoding("gpt2")

    tokens = [encoding.encode(text) for text in text_list]
    tokens = [token for sublist in tokens for token in sublist]  # Flatten the list
    num_tokens = len(tokens)

    chunks = []
    for i in range(0, num_tokens, chunk_size - overlap):
        chunk = tokens[i:i + chunk_size]
        chunks.append(chunk)

    return chunks

chunks = break_up_file_to_chunks(filename)
for i, chunk in enumerate(chunks):
    print(f"Chunk {i}: {len(chunk)} tokens")

# Set OpenAI API Key
os.environ["OPENAI_API_KEY"] = 'OPENAI_API_KEY goes HERE'
openai.api_key = os.getenv("OPENAI_API_KEY")

# Recursive function to handle API rate limits and large texts
def summarize_text(text_list, max_tokens):
    if count_tokens_in_string(str(text_list)) > max_tokens:
        text_list = break_up_text_to_chunks(text_list)

        summary_list = []
        for text_chunk in text_list:
            prompt_request = "Summarize this long summary section: " + encoding.decode(text_chunk)

            try:
                response = openai.Completion.create(
                    model="text-davinci-003",
                    prompt=prompt_request,
                    temperature=.5,
                    max_tokens=max_tokens,
                    top_p=1,
                    frequency_penalty=0,
                    presence_penalty=0
                )
                summary_list.append(response["choices"][0]["text"].strip())
                time.sleep(1)  # Add a delay between each API request to avoid hitting rate limits
            except openai.api_resources.completion.CompletionError as e:
                if e.args[0]['error']['message'] == 'Rate limit exceeded':
                    print('Rate limit exceeded. Waiting for 60 seconds.')
                    time.sleep(60)
                    return summarize_text(text_list, max_tokens)
                elif e.args[0]['error']['message'] == 'Token limit exceeded':
                    print('Token limit exceeded. Breaking the text into smaller chunks.')
                    text_chunks = break_up_text_to_chunks([text_list])
                    summarized_text = []
                    for chunk in text_chunks:
                        summarized_text.append(summarize_text(encoding.decode(chunk), max_tokens))
                    return ' '.join(summarized_text)

        return summarize_text(summary_list, max_tokens)  # Recursive call to handle the case where the summarized text still exceeds the maximum token limit
    else:
        prompt_request = "Consolidate these paper summaries: " + str(text_list)

        try:
            response = openai.Completion.create(
                model="text-davinci-003",
                prompt=prompt_request,
                temperature=.5,
                max_tokens=max_tokens,
                top_p=1,
                frequency_penalty=0,
                presence_penalty=0
            )
            return response["choices"][0]["text"].strip()
        except openai.api_resources.completion.CompletionError as e:
            if e.args[0]['error']['message'] == 'Rate limit exceeded':
                print('Rate limit exceeded. Waiting for 60 seconds.')
                time.sleep(60)
                return summarize_text(text_list, max_tokens)
            elif e.args[0]['error']['message'] == 'Token limit exceeded':
                print('Token limit exceeded. Breaking the text into smaller chunks.')
                text_chunks = break_up_text_to_chunks([text_list])
                summarized_text = []
                for chunk in text_chunks:
                    summarized_text.append(summarize_text(encoding.decode(chunk), max_tokens))
                return ' '.join(summarized_text)

# Summarize the text one chunk at a time
prompt_response = []
encoding = tiktoken.get_encoding("gpt2")
chunks = break_up_file_to_chunks(filename)

for i, chunk in enumerate(chunks):
    prompt_request = "Summarize this partial section of a paper: " + encoding.decode(chunks[i])
    summary = summarize_text(prompt_request, 2000)
    prompt_response.append(summary)

    #Print to the user the partial section summaries
    print("Summary of each part ",i,": ",summary)

#print("These are the aggregated chunk summaries:\n")
#print(prompt_response)

# Consolidate the summaries
prompt_request = "Consolidate these paper summaries: " + ' '.join(prompt_response)
paper_summary = summarize_text(prompt_request, 2000)

# Summary of Summaries
print("This is the final overall summary: \n")
print(paper_summary)


from unittest.mock import MagicMock, patch

import torch.nn as nn

from mmcv.device.mlu import MLUDataParallel, MLUDistributedDataParallel
from mmcv.parallel import is_module_wrapper
from mmcv.utils import IS_MLU_AVAILABLE

def mock(*args, **kwargs):
    pass

@patch('torch.distributed._broadcast_coalesced', mock)
@patch('torch.distributed.broadcast', mock)
@patch('torch.nn.parallel.DistributedDataParallel._ddp_init_helper', mock)
def test_is_module_wrapper():

    class Model(nn.Module):

        def __init__(self):
            super().__init__()
            self.conv = nn.Conv2d(2, 2, 1)

        def forward(self, x):
            return self.conv(x)

    model = Model()
    assert not is_module_wrapper(model)

    if IS_MLU_AVAILABLE:
        mludp = MLUDataParallel(model)
        assert is_module_wrapper(mludp)

        mluddp = MLUDistributedDataParallel(model, process_group=MagicMock())
        assert is_module_wrapper(mluddp)


# Activate
#   |- Linear
#   |- ReLU
#   |- Sigmoid
#   |- Softmax
#   |- Tanh
# Regularize
#   |- L2
#   |- Dropout
# Initialize (variance)
#   |- Constant
#   |- He
#   |- Xavier
# Optimize
#   |- EMA
#   |- RMSprop
#   |- Adam
# Normalization/ standardization
# Grad checking

import numpy as np
import gc
import matplotlib.pyplot as plt

class Activate:
    """
    Following activation functions are defined under this class
    (1) Linear
    (2) ReLU (Rectified Linear Unit)
    (3) Sigmoid
    (4) Softmax
    (5) Tanh (Hyperbolic tangent)
    """

    def linear(self, x):
        """
        Linear activation function (pass-through).
        Returns nothing but the the input vector itself.
        """
        return x

    def relu(self, x, max_value=None, threshold=0):
        """
        Rectified linear unit.
        With default values, it returns element-wise `max(x, 0)`.
        Otherwise:
        `relu(x) = max_value` for `x >= max_value`,
        `relu(x) = x` for `threshold <= x < max_value`,

        Parameters
        ----------
        x : ndarray
        max_value: float, default = None
        threshold : float, default = 0
        """

        output = np.maximum(x, threshold)
        output = np.minimum(output, max_value)

        return output

    def sigmoid(self, x):
        """
        Sigmoid activation function,
            `sigmoid(x) = 1 / (1 + exp(-x))`.

        The sigmoid function always returns a value between 0 and 1.

        For example:
            x = [-20, -1.0, 0.0, 1.0, 20]
            output = [2.06e-09, 2.689e-01, 5.00e-01, 7.31e-01, 1.0]
        """
        output = 1 / (1 + np.exp(-x))
        return output

    def softmax(self, x, axis=-1):
        """
        Softmax converts a vector of values to a probability distribution. It can
        be viewed as a higher-dimensional generalization of the sigmoid function.

        Parameters
        ----------
        x : ndarray of shape ()
        axis : int, default=-1
            axis along which the softmax normalization is applied.

        Returns
        -------
        output : ndarray of shape ()
            Output of softmax transformation (all values must be non-negative
            and sum to 1).
        """

        norm = np.sum(np.exp(x))
        output = np.exp(x)/norm

        # assert all the values are non-negative
        assert all(output > 0)
        # All the elements of the output vector sum to 1.
        assert np.sum(output) == 1.0

        return output

    def tanh(self, x):
        """
        Hyperbolic tangent activation function.

        Returns:
            ndarray of same shape and dtype as those of input `x`.
        """
        return np.tanh(x)

# ----- Methods useful for Convolutional Neural Networks (CNN) ---- #
def conv_dims(dim: int, f: int, pad: int, stride: int):
    """
    Arguments:
        dim -- int; dim of the input image
        f -- int; dim of the filter/ weight (square) matrix
        pad -- int; padding level
        stride -- int; stride parameter

    Returns:
        dim -- dim of the output layer after convolution
    """

    dim = 1 + int((dim - f + 2 * pad) / stride)

    return dim

def zero_pad(image, pad: int, demo=False):
    """
    Pad the images with zeros

    Parameters:
        image -- ndarray; of shape (m, nH, nW, nc) representing a vector of m images
        pad -- int; amount of padding around height, width dimensions of each image
        demo -- bool; show the image pixels before and after padding

    Returns:
        im_pad -- padded image of shape (m, nH + 2*pad, nW + 2*pad, nc)

    Raises:
        ValueError -- Input dimension must be (m, nH, nW, nc)
    """

    # Check the input format
    if len(image.shape) < 4:
        raise ValueError("Input dimensions not of the form (m, nh, nw, nc).")

    im_pad = np.pad(image, ((0, 0), (pad, pad), (pad, pad), (0, 0)),
                    mode='constant', constant_values=(0, 0))

    # If 'demo' requested then show image before & after padding
    if demo:
        fig, ax = plt.subplots(1, 2)
        ax[0].set_title('Original Image')
        ax[0].imshow(image[0, :, :, 0])
        ax[1].set_title('Padded Image')
        ax[1].imshow(im_pad[0, :, :, 0])
        plt.show()

    return im_pad

def conv_block(im_block, kernel, bias):
    """
    Convolve the filter with a single block matrix of the same size.

    Parameters:
        im_block -- ndarray, slice of input image of shape (f, f, nC_prev)
        kernel -- ndarray, Weight parameters of the filter matrix of shape (f, f, nC_prev)
        bias -- float, Bias parameters - matrix of shape (1, 1, 1)

    Returns:
        conv_im -- float, result of convolution with (kernel, bias)
    """

    # Element-wise product between im_block and kernel.
    s = np.multiply(im_block, kernel)
    # Sum over all entries of the volume s and add the bias term.
    conv_im = np.sum(s) + float(bias)

    return conv_im

def conv_full(image, kernel, bias, stride, pad, demo=False):
    """
    Implements the convolution operation on the full input image. This is done
    by repeating 'conv_block' method on the entire image.

    Arguments:
        image -- output activations of the previous layer,
            ndarray of shape (m, nH_prev, nW_prev, nC_prev)
        kernel -- Weights, ndarray of shape (f, f, nC_prev, nC)
        bias -- Biases, ndarray of shape (1, 1, 1, nC)
        stride -- int; stride parameter
        pad -- int; padding parameter
        demo -- bool; show the image pixels before and after convolution

    Returns:
        im_out -- convolved output, numpy array of shape (m, nH, nW, nC)
    """

    # Retrieve the shapes of the matrices
    (m, nh_prev, nw_prev, nc_prev) = image.shape
    # nc = num channels in the output layer = num filters
    (f, f, nc_prev, nc) = kernel.shape

    # Compute the number of dims in height and width of the output
    nh = conv_dims(nh_prev, f, pad, stride)
    nw = conv_dims(nw_prev, f, pad, stride)

    # The convolved output image is initialized by zeros
    im_out = np.zeros(shape=(m, nh, nw, nc))

    # Pad the input image before convolution begins and overwrite
    image = zero_pad(image, pad, demo=False)

    for i in range(m):  # loop over the training examples
        im_i = image[i, :, :, :]

        for h in range(nh):  # loop over the vertical axis of the matrix
            top = h * stride
            bottom = top + f

            for w in range(nw):  # loop over the horizontal axis of the matrix
                left = w * stride
                right = left + f

                for c in range(nc):  # loop over the channels
                    im_block = im_i[top:bottom, left:right, :]
                    weights = kernel[:, :, :, c]
                    biases = bias[:, :, :, c]
                    # Convolve the image block
                    im_out[i, h, w, c] = conv_block(im_block, weights, biases)

    # Making sure the output shape is correct
    assert (im_out.shape == (m, nh, nw, nc))

    # If 'demo' requested then show image before & after convolution
    if demo:
        fig, ax = plt.subplots(1, 2)
        ax[0].set_title('Original Image (%ix%ix%i)'
                        % (nh_prev + 2 * pad, nw_prev + 2 * pad, nc_prev))
        ax[0].imshow(image[0, :, :, 0])
        ax[1].set_title('Convolved Image (%ix%ix%i)' % (nh, nw, nc))
        ax[1].imshow(im_out[0, :, :, 0])
        plt.show()

    # if input matrix is large enough it's good to deallocate memory
    del image
    gc.collect()

    return im_out

def pooling(image, f: int, stride: int, mode='max', demo=False):
    """
    Implements the convolution operation on the full input image. This is done
    by repeating 'conv_block' method on the entire image.

    Arguments:
        image -- output activations of the previous layer,
            ndarray of shape (m, nH_prev, nW_prev, nC_prev)
        f -- int; dim of the filter/ weight (square) matrix
        stride -- int; stride parameter
        mode -- 'max' for max pooling; 'avg' for average pooling
        demo -- bool; show the image pixels before and after pooling

    Returns:
        im_out -- pooled output, ndarray of shape (m, nH, nW, nC)

    Exceptions:
        KeyError -- raised if 'mode' key is incorrectly specified.
    """

    # Retrieve the shapes of the input
    (m, nh_prev, nw_prev, nc_prev) = image.shape

    # Compute the number of dims in height and width of the output
    nh = conv_dims(nh_prev, f, 0, stride)  # pooling doesn't need padding
    nw = conv_dims(nw_prev, f, 0, stride)
    nc = nc_prev

    # The convolved output image is initialized by zeros
    im_out = np.zeros(shape=(m, nh, nw, nc))

    for i in range(m):  # loop over the training examples
        im_i = image[i, :, :, :]

        for h in range(nh):  # loop over the vertical axis of the matrix
            top = h * stride
            bottom = top + f

            for w in range(nw):  # loop over the horizontal axis of the matrix
                left = w * stride
                right = left + f

                for c in range(nc):  # loop over the channels
                    im_block = im_i[top:bottom, left:right, c]

                    if mode == 'max':
                        im_out[i, h, w, c] = np.max(im_block)
                    elif mode == "avg":
                        im_out[i, h, w, c] = np.mean(im_block)
                    else:
                        raise KeyError("'mode' key unrecognized, use 'avg' or 'max'.")

    # Making sure the output shape is correct
    assert (im_out.shape == (m, nh, nw, nc))

    # If 'demo' requested then show image before & after convolution
    if demo:
        fig, ax = plt.subplots(1, 2)
        ax[0].set_title('Original Image')
        ax[0].imshow(image[0, :, :, 0])
        ax[1].set_title('%s-pooled Image' % mode)
        ax[1].imshow(im_out[0, :, :, 0])
        plt.show()

    del image
    gc.collect()

    return im_out

# def forward_prop(self, X):
#   CONV2D -> RELU -> MAX_POOL -> CONV2D -> RELU -> MAX_POOL -> FLATTEN -> FULLY_CONNECTED
#   CONV2D: stride of 1, padding 'SAME'
#     Z1 = None
#     # RELU
#     A1 = None
#     # MAX_POOL: window 8x8, stride 8, padding 'SAME'
#     P1 = None
#     # CONV2D: filters W2, stride 1, padding 'SAME'
#     Z2 = None
#     # RELU
#     A2 = None
#     # MAX_POOL: window 4x4, stride 4, padding 'SAME'
#     P2 = None
#     # FLATTEN
#     F = None
#     # FULLY-CONNECTED without non-linear activation function (not not call softmax).
#     # 6 neurons in output layer. Hint: one of the arguments should be "activation_fn=None"
#     Z3 = None --> return Z3 (a linear unit) as a 'self' object.

# ----- Speeding methods for Artificial Neural Networks (ANN) ---- #

#
# def init_var_scale(num_hidden_units, key, const=0.01):
#     # Good for ReLU
#     if key == 'He':
#         # pass the number of hidden units in the previous layer
#         return np.sqrt(2. / num_hidden_units)
#
#     # Good for Sigmoid or Tanh
#     elif key == 'Xavier':
#         # pass the number of hidden units in the previous layer
#         return np.sqrt(1. / num_hidden_units)
#
#     # If not sure, just use a constant variance
#     else:
#         return const
#
#
# def accuracy(y_orig, y_pred):
#     return round(np.mean(y_orig == y_pred) * 100, 4)
#
#
# def activate(x, key):
#
#     if key == 'sigmoid':
#         a_func = 1 / (1 + np.exp(-x))
#         a_grad = np.multiply(a_func, 1-a_func)
#
#     elif key == 'tanh':
#         a_func = np.tanh(x)
#         a_grad = 1 - np.power(a_func, 2)
#
#     elif key == 'ReLU':
#         a_func = np.maximum(0, x)
#         a_grad = np.heaviside(x, 0)  # x==0 returns 0
#
#     else:
#         raise KeyError("Invalid activation key. "
#                        "Choose from 'tanh', 'sigmoid', 'ReLU'")
#
#     return a_func, a_grad
#
#
# def train_test(A, B, test_size=0.2):
#
#     nums = A.shape[1]
#     frac = round(nums * (1 - test_size))
#
#     # Shuffle the index array and then map that to X, Y
#     idx = np.arange(nums)
#     np.random.shuffle(idx)
#     A = A[:, idx]
#     B = B[:, idx]
#
#     return A[:, :frac], A[:, frac:], B[:, :frac], B[:, frac:]
#
#
# def set_bias_as_weight(shape):
#     return shape[0] + 1, shape[1]
#
#
# def add_bias(vector):
#     return np.hstack([vector, np.ones((vector.shape[0], 1))])
#
#
# def sigmoid(z):
#     return 1 / (1 + np.exp(-z))
#
#
# def shuffle_vectors(x, y):
#     rd = np.arange(len(x))
#     np.random.shuffle(rd)
#     x = x[rd]
#     y = y[rd]
#     return x, y
#
#
# def _stable_clip(x):
#     """Used to avoid numerical inestability when"""
#     return np.clip(x, 1e-7, 1 - 1e-7)
#
#
# def mean_squared_error(ypred, ytrue):
#     return (ypred - ytrue) * ypred * (1 - ypred)
#
#
# def cross_entropy(ypred, ytrue, binary=True):
#     # return -ytrue * np.log(_stable_clip(ypred)) -\
#     #         (1 - ytrue) * np.log(1 - _stable_clip(ypred))
#     return _stable_clip(ypred) - ytrue


import requests, uuid, json, argparse, sys, os
import langcodes

def main():
    # get credentials
    credentials = get_Credentials()
    key = credentials["key"]
    endpoint = credentials["endpoint"]
    location = credentials["location"]

    # If program is run without any command-line arguments
    if len(sys.argv) == 1:
        sys.exit("Usage: python project.py [-f  FILE] [-t TO] \n MISSING FILE AND LANGUAGE!")

    #parsing the arguments to get file and language information
    try:
        parsed_data = parse_arguments()
        File = parsed_data["File"]
        if File != None and os.path.splitext(File)[1] != ".txt":
            sys.exit("The only supported file format is \".txt\"")
        translation_language = parsed_data["translation_language"]
        if File is None:
            while True:
                try:
                    print(live_translator(key, endpoint, location, translation_language))
                except EOFError:
                    print("\nBye, Have a nice day!")
                    return

        else:
            print(file_translator(key, endpoint, location, File, translation_language))

    except KeyError:
        sys.exit("Usage: python project.py [-f  FILE] [-t TO]")

    # When the language name couldn't be resolved
    except LookupError:
        sys.exit("UNRECOGNIZED/INVALID LANGUAGE")

    # When File provided doesn't exist
    except FileNotFoundError:
        sys.exit("FILE DOESN'T EXIST")

def get_Credentials():
    from config import AZURE_KEY, endpoint, location
    return {"key": AZURE_KEY, "endpoint": endpoint, "location" : location}

def parse_arguments():
    # Creating an argument parser
    parser = argparse.ArgumentParser(description="Tranlate text from one language to another")
    parser.add_argument("-f", "--file", help='Path to the input file')
    parser.add_argument("-t", "--to", help = "translation language")
    args = parser.parse_args()

    #getting translation language and input file from arguments
    input_file = args.file
    translation_language = args.to

    # if the language is not given return the default language 'en'
    if translation_language is None:
        translation_language_code = "en"
    else:
        translation_language_code = langcodes.find(translation_language.lower()).language
    return {"File" : input_file, "translation_language" : translation_language_code}

def file_translator(key, endpoint, location, File, translation_language):
    with open(File, 'r') as file:
        text = file.read()
    path = '/translate'
    constructed_url = endpoint + path

    params = {
        'api-version': '3.0',
        'to': [translation_language]
    }

    headers = {
        'Ocp-Apim-Subscription-Key': key,
        # location required if you're using a multi-service or regional (not global) resource.
        'Ocp-Apim-Subscription-Region': location,
        'Content-type': 'application/json',
        'X-ClientTraceId': str(uuid.uuid4())
    }

    # You can pass more than one object in body.
    body = [{
        'text': text
    }]

    request = requests.post(constructed_url, params=params, headers=headers, json=body)
    response = request.json()

    translations = response[0]['translations']
    translated_text = [translation['text'] for translation in translations]

    # Create the output file name
    output_file = f"translated_{translation_language}.txt"

    # Write the translated content to the output file
    with open(output_file, 'w') as file:
        file.write(translated_text[0])
    return f"Translation completed. Translated content saved to: {output_file}"

def live_translator(key, endpoint, location, translation_language="en"):
    text = input("Text: ")
    path = '/translate'
    constructed_url = endpoint + path

    params = {
        'api-version': '3.0',
        'to': [translation_language]
    }

    headers = {
        'Ocp-Apim-Subscription-Key': key,
        # location required if you're using a multi-service or regional (not global) resource.
        'Ocp-Apim-Subscription-Region': location,
        'Content-type': 'application/json',
        'X-ClientTraceId': str(uuid.uuid4())
    }

    # You can pass more than one object in body.
    body = [{
        'text': text
    }]

    request = requests.post(constructed_url, params=params, headers=headers, json=body)
    response = request.json()

    translations = response[0]['translations']
    translated_text = [translation['text'] for translation in translations]
    return translated_text;

if __name__ == "__main__":
    main()


import numpy as np
import pandas as pd
from tabulate import tabulate

df = pd.read_excel('Database.xlsx')
df2 = pd.read_excel('Daftar Pickup.xlsx')
df_baru = df.dropna()
Harga = df_baru.drop('kode', axis =1)
Harga2 = df2.drop('No', axis =1)

#untuk fungsi cekKota dan ceKotaAsal, dilakukan pencarian apakah input ada di dalam database, loop akan diulang sampai
#data yang diinput valid
#Yunita
def jenis_paket():
  while True:
    try:
      paket = int(input("Masukkan nomor jenis pengiriman (Contoh : 1)\t: "))
      if paket == 1:
        return paket, "Reguler"
      elif paket == 2:
        return paket, "Cepat"
      elif paket == 3:
        return paket, "Kargo"
      else:
        raise ValueError

    except ValueError:
      print('Masukkan pilihan yang valid')

def cekKota():
    while True:
      tujuan = input("Masukkan kode kota tujuan (Contoh : Jakarta)\t: ")
      tujuan = tujuan.lower()
      cek = tujuan in df.kota.unique()
      if cek == True:
        return tujuan
        break
      else:
        print("Kota tujuan tidak terdaftar, silahkan masukkan kembali")

#Kiki
def cekKotaAsal():
    while True:
      pickup = input("Masukkan kota Pickup (Contoh : Surakarta): ")
      pickup = pickup.capitalize()
      cek = pickup in df2.tempat.unique()
      if cek == True:
        return pickup
        break
      else:
        print("Kota pickup tidak terdaftar, silahkan masukkan kembali")

#pengolahan data menggunakan pandas, yakni dengan mencari lokasi harga ekspedisi, dengan data yang diinput
#berupa kota asal/kota tujuan. Untuk biaya ongkir kargo/truk yang kurang dari 25kg akan dianggap 25kg dengan biaya
#sepersepuluh dari yang ditentukan, jika lebih maka kemudian baru diberikan kelipatan sebesar sepersepuluh dari
#biaya ongkir yang ditentukan oleh database. Untuk paket cepat, biaya akan dikenakan 5x lipat dari yang tertera di
#database, untuk fee akan dikenakan biaya untuk kelipatan 10kg pertama, dan akan ditambah sepersepuluh dari database per
#kilogramnya
#Yasmin
def hitungongkir(kota, berat, ekspedisi, fee, jenis_paket):
  if jenis_paket == 1:
    berat_asli = berat
  elif jenis_paket == 2:
    berat_asli = berat*5
  elif jenis_paket == 3:
    berat_floor = berat//25
    if berat_floor >= 1:
      berat_asli = berat_floor + ((berat%25)/25)
    else:
      berat_asli = 1

  harga_ongkir = (Harga.loc[df['kota'] == kota, ekspedisi].iloc[0])*berat_asli
  fee = (Harga2.loc[df2['tempat'] == fee, ekspedisi].iloc[0]) * ((berat//10)+1)
  total = harga_ongkir + fee
  return total

#melakukan olah data dengan melakukan pengurutan dari yang termurah hingga termahal, numpy digunakan untuk memberikan
#index dari angka 1-5
#Yasmin
def rekomendasi(ekspedisi, harga2):

    tampilan = {'Ekpedisi' : ekspedisi,
                 'Harga': harga2}
    df_tampil = pd.DataFrame(tampilan, index = np.arange(1, 6))
    dft = df_tampil.sort_values(by = 'Harga')
    dft.insert(0,'No',[1,2,3,4,5])
    dft.index = np.arange(1,6)
    dft = tabulate(dft, headers=dft.columns, showindex=False)
    return(dft)


# -----------------------------------------------------------
#Cafedev.vn - Kênh thông tin IT hàng đầu Việt Nam
#@author cafedevn
#Contact: cafedevn@gmail.com
#Fanpage: https://www.facebook.com/cafedevn
#Group: https://www.facebook.com/groups/cafedev.vn/
#Instagram: https://instagram.com/cafedevn
#Twitter: https://twitter.com/CafedeVn
#Linkedin: https://www.linkedin.com/in/cafe-dev-407054199/
#Pinterest: https://www.pinterest.com/cafedevvn/
#YouTube: https://www.youtube.com/channel/UCE7zpY_SlHGEgo67pHxqIoA/
# -----------------------------------------------------------

import json
from pprint import*

def doc_noi_dung_json(filename):
    data_file = open(filename, encoding = "utf-8")
    data = json.load(data_file)
    data_file.close()
    return data

if __name__ == '__main__':
    url_data = 'du_lieu/QLCT_1.json'
    noi_dung = doc_noi_dung_json(url_data)
    #pprint(noi_dung) # Show content json
    cong_ty  = noi_dung['CONG_TY'][0] # Lay cong ty dau tien
    don_vi   = noi_dung['DON_VI']
    tong_so_nv = 0

    print('Ten cong ty:', cong_ty['Ten'])
    print('Dia chi cong ty: ', cong_ty['Dia_chi'])
    print(' Tong so nhanz vien: ')

2 bt voi json/baitap doc json/read_json_file_thong_ke.py