from django.core.management.base import BaseCommand

from decimal import Decimal

from sakila import assignments

EXPECTED_RESULTS = {
    'assignment_1': 1000,
    'assignment_2': 211,
    'assignment_3': ['Mike Hillyer'],
    'assignment_4': 'ELEANOR HUNT',
    'assignment_5': 'Sports',
    'assignment_6': [(1, Decimal('33679.79')), (2, Decimal('33726.77'))],
    'assignment_7': [u'Aurora', u'London', u'Saint-Denis', u'Cape Coral'],
    'assignment_8': [
        (u'English', 1000),
        (u'Italian', 0),
        (u'Japanese', 0),
        (u'Mandarin', 0),
        (u'French', 0),
        (u'German', 0)
    ],
    'assignment_9': 'BUCKET BROTHERHOOD'
}

class Command(BaseCommand):
    help = ''

    def handle(self, *args, **options):
        for func, expected_result in EXPECTED_RESULTS.items():
            exec_result = getattr(assignments, func)()
            try:
                assert exec_result == expected_result
            except AssertionError:
                print('Test "{}" failed. Expected "{}", but got "{}"'.format(
                    func, expected_result, exec_result))
        print('All tests passing!')


from __future__ import print_function
import os
import io
import re
import sys
from setuptools import setup, find_packages
from pkg_resources import get_distribution, DistributionNotFound
import subprocess

def read(*names, **kwargs):
    with io.open(
        os.path.join(os.path.dirname(__file__), *names),
        encoding=kwargs.get("encoding", "utf8")
    ) as fp:
        return fp.read()

def get_dist(pkgname):
    try:
        return get_distribution(pkgname)
    except DistributionNotFound:
        return None

version = '0.2.3a0'
sha = 'Unknown'
package_name = os.getenv('TORCHVISION_PACKAGE_NAME', 'torchvision')

cwd = os.path.dirname(os.path.abspath(__file__))

try:
    sha = subprocess.check_output(['git', 'rev-parse', 'HEAD'], cwd=cwd).decode('ascii').strip()
except Exception:
    pass

if os.getenv('TORCHVISION_BUILD_VERSION'):
    assert os.getenv('TORCHVISION_BUILD_NUMBER') is not None
    build_number = int(os.getenv('TORCHVISION_BUILD_NUMBER'))
    version = os.getenv('TORCHVISION_BUILD_VERSION')
    if build_number > 1:
        version += '.post' + str(build_number)
elif sha != 'Unknown':
    version += '+' + sha[:7]
print("Building wheel {}-{}".format(package_name, version))

def write_version_file():
    version_path = os.path.join(cwd, 'torchvision', 'version.py')
    with open(version_path, 'w') as f:
        f.write("__version__ = '{}'\n".format(version))
        f.write("git_version = {}\n".format(repr(sha)))

write_version_file()

readme = open('README.rst').read()

pytorch_package_name = os.getenv('TORCHVISION_PYTORCH_DEPENDENCY_NAME', 'torch')

requirements = [
    'numpy',
    'six',
    pytorch_package_name,
]

pillow_ver = ' >= 4.1.1'
pillow_req = 'pillow-simd' if get_dist('pillow-simd') is not None else 'pillow'
requirements.append(pillow_req + pillow_ver)

setup(
    # Metadata
    name=package_name,
    version=version,
    author='PyTorch Core Team',
    author_email='soumith@pytorch.org',
    url='https://github.com/pytorch/vision',
    description='image and video datasets and models for torch deep learning',
    long_description=readme,
    license='BSD',

    # Package info
    packages=find_packages(exclude=('test',)),

    zip_safe=True,
    install_requires=requirements,
    extras_require={
        "scipy": ["scipy"],
    },
)


import json
import subprocess

# Get Kustomize manifests
result = subprocess.run(["bash", "-c", "kubectl kustomize manifests/env/provision"], stdout=subprocess.PIPE)

data_obj ={
    "data": result.stdout.decode("utf-8")
}
print(json.dumps(data_obj))


import sys
import argparse
import requests
import xml.etree.ElementTree as ET

JENKINS_BASE_URL = "http://localhost:8080"
JENKINS_PLUGIN_MANAGER_PATH = "pluginManager/api/xml?depth=1"
DEFAULT_CHUNK_SIZE = 20
TAGS = {
    "VERSION": "version",
    "SHORT_NAME": "shortName"
}

def main():
    arg_parser = argparse.ArgumentParser(
        prog="list-jenkins-plugins",
        description="snapshot list of installed plugins on a Jenkins instance in plugins.txt format"
    )
    arg_parser.add_argument(
        "jenkins_base_url",
        nargs="?",
        default=JENKINS_BASE_URL,
        help="Jenkins instance base url. Defaults to {}".format(JENKINS_BASE_URL)
    ),
    arg_parser.add_argument(
        "--user", "-u",
        default=""
    ),
    arg_parser.add_argument(
        "--password", "-p",
        default=""
    ),
    arg_parser.add_argument(
        "--chunk-size", "-c",
        type=int,
        default=DEFAULT_CHUNK_SIZE,
        help="Jenkins response streaming chunks size. Defaults to {} kB".format(DEFAULT_CHUNK_SIZE)
    )
    args = arg_parser.parse_args()
    return parse_xml_plugins_list(args.jenkins_base_url, args.chunk_size, (args.user, args.password))

def parse_xml_plugins_list(jenkins_base_url, chunk_size, auth):
    chunk_size = chunk_size * 1024
    xml_pull_parser = ET.XMLPullParser()
    plugins = []

    with requests.get(
            "{jenkins_base_url}/{path}".format(jenkins_base_url=jenkins_base_url, path=JENKINS_PLUGIN_MANAGER_PATH),
            auth=auth,
            stream=True
    ) as jenkins_response:
        # parse the xml plugins list a chunk at a time, a very large set of plugins may be installed
        for chunk in jenkins_response.iter_content(chunk_size):
            if chunk:
                xml_pull_parser.feed(chunk)
                try:
                    for event, element in xml_pull_parser.read_events():
                        """
                        Rely on the fact that a plugin version is always
                        encountered after its short name in <plugin> tag children
                        """
                        if TAGS["SHORT_NAME"] == element.tag:
                            plugin_line = element.text
                        elif TAGS["VERSION"] == element.tag:
                            plugins.append(plugin_line + ":" + element.text)
                            plugin_line = ""
                except ET.ParseError as parse_err:
                    print(
                        "Jenkins response is not in parsable XML format, "
                        "check your access rights to the instance: {parse_err}"
                        .format(parse_err=parse_err)
                    )
                    return 1
    for plugin in sorted(plugins):
        print(plugin)
    return 0

if "__main__" == __name__:
    sys.exit(main())


from fairseq.data import Dictionary
from fairseq.data.meta_dataset import MetaFairseqDataset
from . import FairseqTask, register_task
import torch
import os

# Represents a sine task
@register_task('meta')
class MetaTask(FairseqTask):

    @staticmethod
    def add_args(parser):
        """Add task-specific arguments to the parser."""
        parser.add_argument('data', nargs='+', help='path(s) to data directorie(s)')
        parser.add_argument('-s', '--source-lang', default='en', metavar='SRC',
                            help='source language')
        parser.add_argument('-t', '--target-lang', default='de', metavar='TARGET',
                            help='target language')

    def __init__(self, args, meta_train_tasks, meta_dev_tasks, meta_test_tasks, src_dict, tgt_dict):
        self.datasets = {}
        self.args = args
        self.meta_train_tasks = meta_train_tasks
        self.meta_dev_tasks = meta_dev_tasks
        self.meta_test_tasks = meta_test_tasks
        self.src_dict = src_dict
        self.tgt_dict = tgt_dict

    @classmethod
    def setup_task(cls, args, meta_train_tasks, meta_dev_tasks, meta_test_tasks, **kwargs):
        """Setup the task (e.g., load dictionaries).

        Args:
            args (argparse.Namespace): parsed command-line arguments
        """
        # load dictionaries
        src_dict = cls.load_dictionary(os.path.join(args.data[0], 'dict.{}.txt'.format(args.source_lang)))
        tgt_dict = cls.load_dictionary(os.path.join(args.data[0], 'dict.{}.txt'.format(args.target_lang)))
        assert src_dict.pad() == tgt_dict.pad()
        assert src_dict.eos() == tgt_dict.eos()
        assert src_dict.unk() == tgt_dict.unk()
        print('| [{}] dictionary: {} types'.format(args.source_lang, len(src_dict)))
        print('| [{}] dictionary: {} types'.format(args.target_lang, len(tgt_dict)))
        return cls(args=args, meta_train_tasks=meta_train_tasks, meta_dev_tasks=meta_dev_tasks,
                   meta_test_tasks=meta_test_tasks, src_dict=src_dict, tgt_dict=tgt_dict)

    def load_dataset(self, split, **kwargs):
        """Load a given dataset split.

        Args:
            split (str): name of the split (e.g., train, valid, test)
        """
        if split == self.args.train_subset:
            self.datasets[split] = MetaFairseqDataset(split=split, meta_tasks=self.meta_train_tasks)
        elif split == self.args.valid_subset.split(',')[0]:
            self.datasets[split] = MetaFairseqDataset(split=split, meta_tasks=self.meta_dev_tasks)
        else:
            self.datasets[split] = MetaFairseqDataset(split=split, meta_tasks=self.meta_test_tasks)

    @property
    def source_dictionary(self):
        """Return the source :class:`~fairseq.data.Dictionary`."""
        return self.src_dict

    @property
    def target_dictionary(self):
        """Return the target :class:`~fairseq.data.Dictionary`."""
        return self.tgt_dict

    def inference_step(self, generator, models, sample, prefix_tokens=None):
        assert False

    def valid_step(self, sample, model, criterion, optimizer=None):
        model.eval()
        with torch.enable_grad():
            loss, sample_size, logging_output = criterion(model, sample)
        return loss, sample_size, logging_output


"""Dependency injector declarative container."""

import six

from dependency_injector.providers import Provider
from dependency_injector.errors import Error

from .dynamic import DynamicContainer
from .utils import (
    is_container,
    deepcopy,
    _check_provider_type,
)

class DeclarativeContainerMetaClass(type):
    """Declarative inversion of control container meta class."""

    def __new__(mcs, class_name, bases, attributes):
        """Declarative container class factory."""
        cls_providers = tuple((name, provider)
                              for name, provider in six.iteritems(attributes)
                              if isinstance(provider, Provider))

        inherited_providers = tuple((name, provider)
                                    for base in bases if is_container(
                                        base) and base is not DynamicContainer
                                    for name, provider in six.iteritems(
                                        base.cls_providers))

        attributes['cls_providers'] = dict(cls_providers)
        attributes['inherited_providers'] = dict(inherited_providers)
        attributes['providers'] = dict(cls_providers + inherited_providers)

        cls = type.__new__(mcs, class_name, bases, attributes)

        for provider in six.itervalues(cls.providers):
            _check_provider_type(cls, provider)

        return cls

    def __setattr__(cls, name, value):
        """Set class attribute.

        If value of attribute is provider, it will be added into providers
        dictionary.

        :param name: Attribute's name
        :type name: str

        :param value: Attribute's value
        :type value: object

        :rtype: None
        """
        if isinstance(value, Provider):
            _check_provider_type(cls, value)
            cls.providers[name] = value
            cls.cls_providers[name] = value
        super(DeclarativeContainerMetaClass, cls).__setattr__(name, value)

    def __delattr__(cls, name):
        """Delete class attribute.

        If value of attribute is provider, it will be deleted from providers
        dictionary.

        :param name: Attribute's name
        :type name: str

        :rtype: None
        """
        if name in cls.providers and name in cls.cls_providers:
            del cls.providers[name]
            del cls.cls_providers[name]
        super(DeclarativeContainerMetaClass, cls).__delattr__(name)

@six.add_metaclass(DeclarativeContainerMetaClass)
class DeclarativeContainer(object):
    """Declarative inversion of control container.

    .. code-block:: python

        class Services(DeclarativeContainer):
            auth = providers.Factory(AuthService)
            users = providers.Factory(UsersService,
                                      auth_service=auth)
    """

    __IS_CONTAINER__ = True

    provider_type = Provider
    """Type of providers that could be placed in container.

    :type: type
    """

    instance_type = DynamicContainer
    """Type of container that is returned on instantiating declarative
    container.

    :type: type
    """

    providers = dict()
    """Read-only dictionary of all providers.

    :type: dict[str, :py:class:`dependency_injector.providers.Provider`]
    """

    cls_providers = dict()
    """Read-only dictionary of current container providers.

    :type: dict[str, :py:class:`dependency_injector.providers.Provider`]
    """

    inherited_providers = dict()
    """Read-only dictionary of inherited providers.

    :type: dict[str, :py:class:`dependency_injector.providers.Provider`]
    """

    overridden = tuple()
    """Tuple of overriding containers.

    :type: tuple[:py:class:`DeclarativeContainer`]
    """

    def __new__(cls, *args, **kwargs):
        """Constructor.

        :return: Dynamic container with copy of all providers.
        :rtype: :py:class:`DynamicContainer`
        """
        container = cls.instance_type(*args, **kwargs)
        container.provider_type = cls.provider_type

        for name, provider in six.iteritems(deepcopy(cls.providers)):
            setattr(container, name, provider)

        return container

    @classmethod
    def override(cls, overriding):
        """Override current container by overriding container.

        :param overriding: Overriding container.
        :type overriding: :py:class:`DeclarativeContainer`

        :raise: :py:exc:`dependency_injector.errors.Error` if trying to
                override container by itself or its subclasses

        :rtype: None
        """
        if issubclass(cls, overriding):
            raise Error('Container {0} could not be overridden '
                        'with itself or its subclasses'.format(cls))

        cls.overridden += (overriding,)

        for name, provider in six.iteritems(overriding.cls_providers):
            try:
                getattr(cls, name).override(provider)
            except AttributeError:
                pass

    @classmethod
    def reset_last_overriding(cls):
        """Reset last overriding provider for each container providers.

        :rtype: None
        """
        if not cls.overridden:
            raise Error('Container {0} is not overridden'.format(cls))

        cls.overridden = cls.overridden[:-1]

        for provider in six.itervalues(cls.providers):
            provider.reset_last_overriding()

    @classmethod
    def reset_override(cls):
        """Reset all overridings for each container providers.

        :rtype: None
        """
        cls.overridden = tuple()

        for provider in six.itervalues(cls.providers):
            provider.reset_override()


#!/usr/bin/env python3

"""
Implements a CBC padding oracle for AES-128-CBC.
__author__ = Eik List
__date__   = 2018-04
__copyright__ = Creative Commons CC0
"""

# ---------------------------------------------------------

import base64
from Crypto.Cipher import AES
from Crypto import Random

# ---------------------------------------------------------

class CBCPaddingOracle:
    """
    Implements a CBC padding oracle for AES-128-CBC.
    """

    def __init__(self, key: bytes):
        """
        Sets the key.
        :param key:
        """
        self.key = key

    # ---------------------------------------------------------

    def encrypt(self, initial_value: bytes, message: bytes) -> bytes:
        """
        Pads the given message to a multiple of the block length,
        computes, and returns its encryption with AES-128-CBC-XMLPad.

        :param initial_value: 16-byte initial value.
        :param message: Plaintext of arbitrary length
        :return: Ciphertext whose length is a multiple of 16 bytes, but
        always at least the length of the message.
        """

        message = self.pad(message)
        aes = AES.new(self.key, AES.MODE_CBC, initial_value)
        return aes.encrypt(message)

    # ---------------------------------------------------------

    def verify_padding(self, initial_value: bytes, ciphertext: bytes) -> bool:
        """
        Given a ciphertext, evaluates if the padding is correct.
        :param initial_value: 16-byte initial value.
        :param ciphertext: Ciphertext. Length must be multiple of 16 bytes.
        :return: True if padding is correct, and False otherwise.
        """
        aes = AES.new(self.key, AES.MODE_CBC, initial_value)
        message = aes.decrypt(ciphertext)
        padding = int.from_bytes(message[-1:], byteorder='big')

        if padding < 1 or padding > 16:
            return False

        for _ in range(padding):
            if ((int.from_bytes(message[-1:], byteorder='big')) != padding):
                return False
            message = message[:-1]

        return True

    def pad(self, message: bytes) -> bytes:
        """
        Pads the given message to a multiple of 16 bytes
        """
        diff = 16 - (len(message) % 16)
        if diff == 0:
            return message

        for _ in range(diff):
            message += bytes([diff])

        return message


import warnings
from collections import OrderedDict, defaultdict
from typing import List, Iterable, Optional, Dict
from flask_restx import fields, Api, Model

from dedoc.config import get_config
from dedoc.data_structures.annotation import Annotation
from dedoc.data_structures.paragraph_metadata import ParagraphMetadata
from dedoc.data_structures.serializable import Serializable
from dedoc.structure_constructor.annotation_merger import AnnotationMerger
from dedoc.structure_parser.heirarchy_level import HierarchyLevel
from dedoc.data_structures.line_with_meta import LineWithMeta

class TreeNode(Serializable):

    def __init__(self,
                 node_id: str,
                 text: str,
                 annotations: List[Annotation],
                 metadata: ParagraphMetadata,
                 subparagraphs: List["TreeNode"],
                 hierarchy_level: HierarchyLevel,
                 parent: Optional["TreeNode"]):
        """
        TreeNode helps to represent document as recursive tree structure. It has parent node (None for root ot the tree)
        and list of children nodes (empty list for list node)
        :param node_id: node id is unique in one document
        :param text: text of node
        :param annotations: some metadata related to the part of the text (as font size)
        :param metadata: metadata refers to entire node (as node type)
        :param subparagraphs: list of child of this node
        :param hierarchy_level: helps to define the position of this node in the document tree
        :param parent: parent node (None for root, not none for other nodes)
        """
        self.node_id = node_id
        self.text = text
        self.annotations = annotations
        self.metadata = metadata
        self.subparagraphs = subparagraphs
        self.hierarchy_level = hierarchy_level
        self.parent = parent

    def to_dict(self, old_version: bool) -> dict:
        res = OrderedDict()
        res["node_id"] = self.node_id
        res["text"] = self.text
        res["annotations"] = [annotation.to_dict(old_version) for annotation in self.annotations]
        res["metadata"] = self.metadata.to_dict(old_version)
        res["subparagraphs"] = [node.to_dict(old_version) for node in self.subparagraphs]
        return res

    @staticmethod
    def get_api_dict(api: Api, depth: int = 0, name: str = 'TreeNode') -> Model:
        return api.model(name, {
            'node_id': fields.String(description="Document element identifier. It is unique within one tree (i.e. "
                                                 "there will be no other such node_id in this tree, but in attachment "
                                                 "it may occur) The identifier has the form 0.2.1 where each number "
                                                 "means a serial number at the corresponding level of the hierarchy.",
                                     required=True,
                                     example="0.2.1"
                                     ),
            'text': fields.String(description="text of node", required=True, example="Закон"),
            'annotations': fields.List(fields.Nested(Annotation.get_api_dict(api),
                                                     description="Text annotations "
                                                                 "(font, size, bold, italic and etc)")),
            'metadata': fields.Nested(ParagraphMetadata.get_api_dict(api),
                                      skip_none=True,
                                      allow_null=False,
                                      description="Paragraph meta information"),
            'subparagraphs': fields.List(fields.Nested(api.model('others_TreeNode', {})),
                                         description="Node childes (with type 'TreeNode') of structure tree")
            if depth == get_config()['recursion_deep_subparagraphs']
            else fields.List(fields.Nested(TreeNode.get_api_dict(api,
                                                                 depth=depth + 1,
                                                                 name='refTreeNode' + str(depth))),
                             description="Node childes (with type 'TreeNode') of structure tree")
        })

    @staticmethod
    def create(lines: List[LineWithMeta] = None) -> "TreeNode":
        """
        Creates a root node with given text
        :param lines: this lines should be the title of the document (or should be empty for documents without title)
        :return: root of the document tree
        """
        page_id = 0 if len(lines) == 0 else min((line.metadata.page_id for line in lines))
        line_id = 0 if len(lines) == 0 else min((line.metadata.line_id for line in lines))

        texts = (line.line for line in lines)
        annotations = []
        text_length = 0
        for line in lines:
            annotations.extend(TreeNode.__shift_annotations(line=line, text_length=text_length))
            text_length += len(line.line)
        text = "".join(texts)
        metadata = ParagraphMetadata(
            paragraph_type="root",
            page_id=page_id,
            line_id=line_id,
            predicted_classes=None)
        return TreeNode("0",
                        text,
                        annotations=annotations,
                        metadata=metadata,
                        subparagraphs=[],
                        hierarchy_level=HierarchyLevel.create_root(),
                        parent=None)

    def add_child(self, line: LineWithMeta) -> "TreeNode":
        """
        Create a new tree node - children of the given node from given line. Return newly created node
        :param line: Line with meta, new node will be built from this line
        :return: return created node (child of the self)
        """
        new_node = TreeNode(
            node_id=self.node_id + ".{}".format(len(self.subparagraphs)),
            text=line.line,
            annotations=line.annotations,
            metadata=line.metadata,
            subparagraphs=[],
            hierarchy_level=line.hierarchy_level,
            parent=self
        )
        self.subparagraphs.append(new_node)
        return new_node

    def add_text(self, line: LineWithMeta):
        """
        add the text and annotations from given line, text is separated with \n
        :param line: line with text to add
        :return:
        """
        text_length = len(self.text)
        new_annotations = self.__shift_annotations(line, text_length)

        self.text += line.line
        self.annotations.extend(new_annotations)

    @staticmethod
    def __shift_annotations(line: LineWithMeta, text_length: int) -> List[Annotation]:
        new_annotations = []
        for annotation in line.annotations:
            new_annotation = Annotation(start=annotation.start + text_length,
                                        end=annotation.end + text_length,
                                        name=annotation.name,
                                        value=annotation.value)
            new_annotations.append(new_annotation)
        return new_annotations

    def get_root(self):
        """
        :return: return root of the tree
        """
        node = self
        while node.parent is not None:
            node = node.parent
        return node

    def merge_annotations(self):
        root = self.get_root()
        stack = [root]
        merger = AnnotationMerger()
        while len(stack) > 0:
            node = stack.pop()
            node.annotations = merger.merge_annotations(node.annotations, node.text)
            for sub_node in node.subparagraphs:
                stack.append(sub_node)


"""Module with wrapper class for XGBoost model and its associated data class"""

from typing import List, Tuple, Optional, Union, Sequence, Callable
import os
from functools import reduce
import pandas as pd
import numpy as np
from sklearn.pipeline import make_pipeline, Pipeline
from sklearn.preprocessing import StandardScaler
from sklearn.externals import joblib
from sklearn.base import BaseEstimator
from xgboost import XGBRegressor

from server.types import FeatureFunctionType
from server.data_processors import (
    TeamDataStacker,
    FeatureBuilder,
    OppoFeatureBuilder
)
from server.data_processors.feature_functions import (
    add_last_week_result,
    add_last_week_score,
    add_cum_percent,
    add_cum_win_points,
    add_rolling_last_week_win_rate,
    add_ladder_position,
    add_win_streak,
    add_out_of_state,
    add_travel_distance,
    add_last_week_goals,
    add_last_week_behinds,
)
from server.data_processors import FitzroyDataReader

YearsType = Tuple[Optional[int], Optional[int]]

PROJECT_PATH: str = os.path.abspath(
    os.path.join(os.path.dirname(__file__), '../../../')
)

COL_TRANSLATIONS = {
    'home_points': 'home_score',
    'away_points': 'away_score',
    'margin': 'home_margin',
    'season': 'year'
}
INDEX_COLS = ['team', 'year', 'round_number']
REQUIRED_COLS: List[str] = ['year', 'score', 'oppo_score']
FEATURE_FUNCS: Sequence[FeatureFunctionType] = [
    add_out_of_state,
    add_travel_distance,
    add_last_week_goals,
    add_last_week_behinds,
    add_last_week_result,
    add_last_week_score,
    add_cum_win_points,
    add_rolling_last_week_win_rate,
    add_win_streak
]
DATA_TRANSFORMERS: List[FeatureFunctionType] = [
    TeamDataStacker(index_cols=INDEX_COLS).transform,
    FeatureBuilder(feature_funcs=FEATURE_FUNCS).transform,
    OppoFeatureBuilder(
        match_cols=['team', 'year', 'round_number', 'score', 'oppo_score',
                    'out_of_state', 'at_home', 'oppo_team', 'venue', 'round_type']
    ).transform,
    # Features dependent on oppo columns
    FeatureBuilder(
        feature_funcs=[add_cum_percent, add_ladder_position]
    ).transform
]
DATA_READERS: List[Callable] = [FitzroyDataReader().match_results]

np.random.seed(42)

class MatchXGB():
    """Create pipeline for for fitting/predicting with lasso model.

    Attributes:
        _pipeline (sklearn.pipeline.Pipeline): Scikit Learn pipeline
            with transformers & Lasso estimator.
        name (string): Name of final estimator in the pipeline ('XGBoost').
    """

    def __init__(self) -> None:
        self._pipeline: Pipeline = make_pipeline(
            StandardScaler(), XGBRegressor()
        )

    @property
    def name(self) -> str:
        return self.__last_estimator()[0]

    def fit(self, X: pd.DataFrame, y: pd.Series) -> None:
        """Fit estimator to the data.

        Args:
            X (pandas.DataFrame): Data features.
            y (pandas.Series): Data labels.

        Returns:
            None.
        """

        self._pipeline.fit(X, y)

    def predict(self, X: pd.DataFrame) -> pd.Series:
        """Make predictions base on the data input.

        Args:
            X (pandas.DataFrame): Data features.

        Returns:
            pandas.Series: Estimator predictions.
        """

        y_pred = self._pipeline.predict(X)

        return pd.Series(y_pred, name='predicted_margin', index=X.index)

    def save(self,
             filepath: str = (f'{PROJECT_PATH}/server/ml_models/match_xgb/'
                              'match_xgb_model.pkl')) -> None:
        """Save the pipeline as a pickle file.

        Args:
            filepath (string): The path where the pickle file is saved.

        Returns:
            None.
        """

        joblib.dump(self._pipeline, filepath)

    def load(self,
             filepath: str = (f'{PROJECT_PATH}/server/ml_models/match_xgb/'
                              'match_xgb_model.pkl')) -> None:
        """Load the pipeline from a pickle file.

        Args:
            filepath (string): The path to the file to laod.

        Returns:
            None.
        """

        self._pipeline = joblib.load(filepath)

    def __last_estimator(self) -> Tuple[str, BaseEstimator]:
        return self._pipeline.steps[-1]

class MatchXGBData():
    """Load and clean data for the XGB pipeline.

    Args:
        data_transformers (list[callable]): Functions that receive, transform,
            and return data frames.
        train_years (tuple[integer or None]): Minimum and maximum (inclusive) years
            for the training data.
        test_years (tuple[ingeter or None]): Minimum and maximum (inclusive) years
            for the test data.

    Attributes:
        data (pandas.DataFrame): Cleaned, unfiltered data frame.
        train_years (tuple[integer or None]): Minimum and maximum (inclusive) years
            for the training data.
        test_years (tuple[ingeter or None]): Minimum and maximum (inclusive) years
            for the test data.
    """

    def __init__(self,
                 data_readers: List[Callable] = DATA_READERS,
                 data_transformers: List[FeatureFunctionType] = DATA_TRANSFORMERS,
                 train_years: YearsType = (None, 2015),
                 test_years: YearsType = (2016, 2016)) -> None:
        self._train_years = train_years
        self._test_years = test_years

        # Need to reverse the transformation steps, because composition makes the output
        # of each new function the argument for the previous
        compose_all = reduce(
            self.__compose_two, reversed(data_transformers), lambda x: x
        )

        data_frame = (data_readers[0]()
                      .rename(columns=COL_TRANSLATIONS)
                      .drop(['round', 'game', 'date'], axis=1))

        # There was some sort of round-robin finals round in 1897 and figuring out
        # a way to clean it up that makes sense is more trouble than just dropping a few rows
        data_frame = data_frame[(data_frame['year'] != 1897) &
                                (data_frame['round_number'] != 15)]

        self.data = compose_all(data_frame).drop('venue', axis=1).dropna()

    def train_data(self) -> Tuple[pd.DataFrame, pd.DataFrame]:
        """Filter data by year to produce training data.

        Returns:
            Tuple[pandas.DataFrame]: Training features and labels.
        """

        data_train = self.data[
            (self.data['year'] >= self.__train_min()) &
            (self.data['year'] <= self.__train_max())
        ]

        X_train = self.__X(data_train)
        y_train = self.__y(data_train)

        return X_train, y_train

    def test_data(self) -> Tuple[pd.DataFrame, pd.DataFrame]:
        """Filter data by year to produce test data.

        Returns:
            Tuple[pandas.DataFrame]: Test features and labels.
        """

        data_test = self.data[
            (self.data['year'] >= self.__test_min()) &
            (self.data['year'] <= self.__test_max())
        ]
        X_test = self.__X(data_test)
        y_test = self.__y(data_test)

        return X_test, y_test

    @property
    def train_years(self) -> YearsType:
        return self._train_years

    @train_years.setter
    def train_years(self, years: YearsType) -> None:
        self._train_years = years

    @property
    def test_years(self) -> YearsType:
        return self._test_years

    @test_years.setter
    def test_years(self, years: YearsType) -> None:
        self._test_years = years

    def __train_min(self) -> Union[int, float]:
        return self._train_years[0] or np.NINF

    def __train_max(self) -> Union[int, float]:
        return self._train_years[1] or np.Inf

    def __test_min(self) -> Union[int, float]:
        return self._test_years[0] or np.NINF

    def __test_max(self) -> Union[int, float]:
        return self._test_years[1] or np.Inf

    def __X(self, data_frame: pd.DataFrame) -> pd.DataFrame:
        data_dummies = pd.get_dummies(self.data.select_dtypes('O'))
        X_data = pd.get_dummies(
            data_frame.drop(['score', 'oppo_score'], axis=1)
        )

        # Have to get missing dummy columns, because train & test years can have different
        # teams/venues, resulting in data mismatch when trying to predict with a model
        missing_cols = np.setdiff1d(data_dummies.columns, X_data.columns)
        missing_df = pd.DataFrame(
            {missing_col: 0 for missing_col in missing_cols}, index=X_data.index
        )

        return pd.concat([X_data, missing_df], axis=1).astype(float)

    @staticmethod
    def __compose_two(composed_func: FeatureFunctionType,
                      func_element: FeatureFunctionType) -> FeatureFunctionType:
        return lambda x: composed_func(func_element(x))

    @staticmethod
    def __y(data_frame: pd.DataFrame) -> pd.Series:
        return data_frame['score'] - data_frame['oppo_score']


from ml_gym.models.nn.net import NNModel
from typing import Dict
import torch
from transformers import AutoConfig, AutoModelForMaskedLM

class BERTLM(NNModel):

    def __init__(self, prediction_publication_key: str, bert_version: str = "bert-base-uncased"):
        super().__init__()
        self.prediction_publication_key = prediction_publication_key
        config = AutoConfig.from_pretrained(bert_version)
        self.model = AutoModelForMaskedLM.from_config(config)

    def forward_impl(self, inputs: torch.Tensor) -> Dict[str, torch.Tensor]:
        outputs = self.model(inputs)
        output_dict = {self.prediction_publication_key: outputs.logits}
        return output_dict

    def forward(self, inputs: torch.Tensor) -> Dict[str, torch.Tensor]:
        return self.forward_impl(inputs)

if __name__ == '__main__':
    from datasets import load_from_disk
    from transformers import DataCollatorForLanguageModeling, BertTokenizerFast
    from torch.utils.data import DataLoader

    tokenizer = BertTokenizerFast(tokenizer_file="/scratch/max/mlgym/example/transformer/tokenizers/trained_wiki_tokenizer/tokenizer.json")
    chunked_tokenized_dataset = load_from_disk("example/transformer/preprocessed_datasets/chunked_tokenized_dataset_train")
    mlm_probability = 0.15
    batch_size = 30

    data_collator = DataCollatorForLanguageModeling(tokenizer=tokenizer, mlm_probability=mlm_probability, pad_to_multiple_of=8)

    train_dataloader = DataLoader(chunked_tokenized_dataset, shuffle=True, batch_size=batch_size, collate_fn=data_collator)

    sample = next(iter(train_dataloader))
    model = BERTLM("")
    prediction = model(sample["input_ids"])
    print("")


import os
import re
import sys
import platform
import subprocess
from distutils.version import LooseVersion
from setuptools import setup, Extension
from setuptools.command.build_ext import build_ext

class CMakeExtension(Extension):
    def __init__(self, name, sourcedir=''):
        Extension.__init__(self, name, sources=[])
        self.sourcedir = os.path.abspath(sourcedir)

class CMakeBuild(build_ext):
    def run(self):
        try:
            out = subprocess.check_output(['cmake', '--version'])
        except OSError:
            raise RuntimeError(
                "CMake must be installed to build the following extensions: " +
                ", ".join(e.name for e in self.extensions))

        if platform.system() == "Windows":
            cmake_version = LooseVersion(re.search(r'version\s*([\d.]+)',
                                                   out.decode()).group(1))
            if cmake_version < '3.1.0':
                raise RuntimeError("CMake >= 3.1.0 is required on Windows")

        for ext in self.extensions:
            self.build_extension(ext)

    def build_extension(self, ext):
        extdir = os.path.abspath(
            os.path.dirname(self.get_ext_fullpath(ext.name)))
        cmake_args = ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY=' + extdir,
                      '-DPYTHON_EXECUTABLE=' + sys.executable]

        cfg = 'Debug' if self.debug else 'Release'
        build_args = ['--config', cfg]

        if platform.system() == "Windows":
            cmake_args += ['-DCMAKE_LIBRARY_OUTPUT_DIRECTORY_{}={}'.format(
                cfg.upper(),
                extdir)]
            if sys.maxsize > 2**32:
                cmake_args += ['-A', 'x64']
            build_args += ['--', '/m']
        else:
            cmake_args += ['-DCMAKE_BUILD_TYPE=' + cfg]
            build_args += ['--', '-j2']

        env = os.environ.copy()
        env['CXXFLAGS'] = '{} -DVERSION_INFO=\\"{}\\"'.format(
            env.get('CXXFLAGS', ''),
            self.distribution.get_version())
        if not os.path.exists(self.build_temp):
            os.makedirs(self.build_temp)
        subprocess.check_call(['cmake', ext.sourcedir] + cmake_args,
                              cwd=self.build_temp, env=env)
        subprocess.check_call(['cmake', '--build', '.'] + build_args,
                              cwd=self.build_temp)
        print()  # Add an empty line for cleaner output

requirements = [
                   'numpy>=1.16.5',
               ]

test_requirements = [
                        'numpy>=1.16.5',
                    ]

long_description = "Python library for sGMRFmix model for anomaly detection in time-series data. sGMRFmix is short for sparse mixture of Gaussian Markov Random Fields. This is essentially a C++ (and python) port of the R package `sGMRFmix` to make it run faster for larger datasets."

setup(
    name='sgmrfmix',
    version='0.1',
    author='Anand K Subramanian',
    author_email='anandkrish894@gmail.com',
    url='https://github.com/AntixK/sGMRFmix',
    description='Python library for sparse Gaussian Markov Random Field mixtures for anomaly detection',
    long_description=long_description,
    packages=['sgmrfmix'],
    ext_modules=[CMakeExtension('_sgmrfmix')],
    cmdclass=dict(build_ext=CMakeBuild),
    install_requires=requirements,
    tests_require=test_requirements,
    zip_safe=False,
    classifiers=[
        "Programming Language :: Python :: 3",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
        "Topic :: Scientific/Engineering",
    ],
    python_requires='>=3.6', # For Python thread specific storage API
)


import os
from collections import Counter

from redis import StrictRedis

from streamparse import Bolt

class WordCountBolt(Bolt):
    outputs = ['word', 'count']

    def initialize(self, conf, ctx):
        self.counter = Counter()
        self.pid = os.getpid()
        self.total = 0

    def _increment(self, word, inc_by):
        self.counter[word] += inc_by
        self.total += inc_by

    def process(self, tup):
        word = tup.values[0]
        self._increment(word, 10 if word == "dog" else 1)
        if self.total % 1000 == 0:
            self.logger.info("counted [{:,}] words [pid={}]".format(self.total,
                                                                    self.pid))
        self.emit([word, self.counter[word]])

class RedisWordCountBolt(WordCountBolt):
    def initialize(self, conf, ctx):
        self.pid = os.getpid()
        self.redis = StrictRedis()
        self.total = 0

    def _increment(self, word, inc_by):
        self.total += inc_by
        self.redis.zincrby("words", word, inc_by)


import collections
from typing import List

class Solution:
    def findAnagrams(self, s: str, p: str) -> List[int]:
        if not p or len(p) > len(s): return []

        p_hash = collections.Counter(p)
        m, n, desired, formed = len(s), len(p), len(p_hash), 0
        s_hash = collections.defaultdict(int)
        result = []

        for j in range(n):
            c = s[j]
            s_hash[c] += 1
            if c in p_hash and p_hash[c] == s_hash[c]: formed += 1

        if formed == desired: result.append(0)

        r = n
        while r < m:
            l = r - n + 1 # get 1st char in n size window
            out_c, in_c = s[l - 1], s[r]

            if out_c in p_hash and p_hash[out_c] == s_hash[out_c]: formed -= 1
            s_hash[out_c] -= 1

            s_hash[in_c] += 1
            if in_c in p_hash and p_hash[in_c] == s_hash[in_c]: formed += 1

            if formed == desired: result.append(l)
            r += 1

        return result

# 438. Find All Anagrams in a String
# https://leetcode.com/problems/find-all-anagrams-in-a-string/description/

# 'aabc' 'abc'

# formed = 2
# desired = 3

# "aab"
# {
#     a: 1
#     b: 1

# }

# "ab"

# { a:1
#   b:1
# }

# "cbaebabacd"
# "abc"


from selenium.webdriver.common.by import By
from selenium.webdriver.support.ui import WebDriverWait
from selenium.webdriver.support import expected_conditions as EC
from selenium.webdriver.common.keys import Keys
from time import *
import sys
sys.path.append('..')
from TestModel import BasePage, Functions

class Search(BasePage.BaseClass):

    def click_createanewone_button(self):
        WebDriverWait(self.driver, 15, 0.5).until(EC.element_to_be_clickable((By.XPATH, "//div[@ng-if='allowAccountCreation']/a"))).click()

    def input_searchkeyword(self, keyword):
        sleep(2)
        WebDriverWait(self.driver, 15, 0.5).until(EC.presence_of_element_located((By.XPATH, "//input[@type='search']"))).send_keys(keyword)
        sleep(1)
        self.driver.find_element_by_xpath("//input[@type='search']").send_keys(Keys.ENTER)
        Functions.wait_element_visible(self.driver, By.XPATH, "//h3[@class ='modal-title']")
        Functions.wait_element_not_visible(self.driver, By.XPATH, "//h3[@class ='modal-title']")

    def click_view_button(self):
        js = "var q=document.documentElement.scrollTop=10000"
        self.driver.execute_script(js)
        WebDriverWait(self.driver, 20, 0.5).until(EC.visibility_of_element_located((By.XPATH, "//button[@class='secondary-button desktop-only medium']"))).click()
        Functions.wait_element_visible(self.driver, By.XPATH, "//h3[@class ='modal-title']")
        Functions.wait_element_not_visible(self.driver, By.XPATH, "//h3[@class ='modal-title']")
        if(Functions.wait_element_visible(self.driver, By.XPATH, "//h3[@class ='modal-title']")):
            Functions.wait_element_not_visible(self.driver, By.XPATH, "//h3[@class ='modal-title']")


"""
This class includes the principal optimization problem.
"""
__all__ = ['PrincipalProblem']

import theano
import theano.tensor as T
import itertools
import design
import numpy as np
import sys
import scipy.optimize as opt
from sepdesign._types import AgentType
from sepdesign._agent import Agent
from sepdesign._utility_functions import UtilityFunction
from sepdesign._value_functions import ValueFunction
from sepdesign._transfer_functions import TransferFunction
from sepdesign._individual_rationality import IndividualRationality
from sepdesign._function import *
import warnings
try:
    import pyipopt
except:
    warnings.warn('*** Could not find pyipopt. ***')
try:
    from pyDOE import lhs
except:
    warnings.warn('*** Could not find pyDOE. ***')

# Flattens a list of lists
flatten = lambda l: [item for sublist in l for item in sublist]

def run_and_print(func, verbosity, *args, **kwargs):
    """
    Run func(*args, **kwargs) and print something msg.
    """
    if verbosity >= 0:
        sys.stdout.write('Running ' + str(func) + '...')
    res = func(*args, **kwargs)
    if verbosity >= 0:
        sys.stdout.write(' Done!\n')
    return res

class PrincipalProblem(object):
    """
    A class representing the problem faced by the principal.

    :param u:           A utility function for the principal.
    :param v:           A value function for the system.
    :param agents:      A list of agents. Each element of the list is either.
    :param t:           The form of the transfer function.
    :param sg_level:    The sparse grid level for taking the expectation over
                        the xi's.
    :param verbosity:   The verbosity level of the class.
    """

    def __init__(self, u, v, agents, t, sg_level=6, verbosity=1):
        assert isinstance(u, UtilityFunction)
        self._u = u
        assert isinstance(v, ValueFunction)
        self._v = v
        if isinstance(agents, Agent):
            agents = [agents]
        assert isinstance(agents, list)
        for a in agents:
            assert isinstance(a, Agent)
        assert len(agents) == v.num_subsystems
        self._agents = agents
        assert isinstance(t, TransferFunction)
        self._t = t
        assert isinstance(sg_level, int)
        self._sg_level = sg_level
        assert isinstance(verbosity, int)
        self._verbosity = verbosity
        self._setup_exp_u()
        self._num_param = np.sum([a.num_types for a in self.agents]) * t.num_a
        self._compiled = False

    def _setup_exp_u(self):
        """
        Set up the following:
        + self.exp_u_raw:   The expected utility of the principal as a
                            Function of e_star and the transfer function
                            parameters a. This is a Function.
        + self.exp_u:       The expected utility of the principal as a function
                            of the transfer function parameters a. This is a
                            common Python function. It also returns the
                            gradient of the exp_u with respect to a.
        """
        # Setup the individual rationality constraints
        self._setup_irc()
        # Symbolic parameters of transfer functions (i-k)
        t_as = [[] for _ in range(self.num_agents)]
        # Symbolic optimal efforts (i-k)
        t_e_stars = [[] for _ in range(self.num_agents)]
        # Symbolic xis (i)
        t_xis = []
        # Symbolic efforts (i-k)
        t_qs = [[] for _ in range(self.num_agents)]
        t_ts = [[] for _ in range(self.num_agents)]
        for i in range(self.num_agents):
            t_xis.append(T.dvector('xi{%d}' % i))
            for k in range(self.agents[i].num_types):
                t_as[i].append(T.dvector('a{%d,%d}' % (i, k)))
                t_e_stars[i].append(T.scalar('e_stars{%d,%d}' % (i, k)))
                q_base = self.agents[i].agent_types[k].q
                t_qs[i].append(theano.clone(q_base.t_f,
                    replace={q_base.t_x[0]: t_e_stars[i][k],
                             q_base.t_x[1]: t_xis[i]}))
                t_ts[i].append(theano.clone(self.t.t_f,
            replace={self.t.t_x[0]: t_qs[i][k],
                     self.t.t_x[1]: t_as[i][k]}))
        # For all possible combinations of agent types
        # Expected utility functions
        t_sum_u_over_comb = T.zeros((1,))
        for at_comb in self._agent_type_range(): # Loop over agent type combs
            # Get the value function for this combination of types in theano:
            t_v_comb = theano.clone(self.v.t_f,
                            replace=dict((self.v.t_x[i], t_qs[i][at_comb[i]])
                                         for i in range(self.num_agents)))
            # The payoff to the principal for this combination of types
            t_pi_comb = t_v_comb - T.sum(
                    [t_ts[i][at_comb[i]] for i in range(self.num_agents)],
                                         axis=0)
            # Multiply with the probability of type happening
            p_comb = np.prod([self.agents[i].type_probabilities[at_comb[i]]
                              for i in range(self.num_agents)])
            # The utility of the principal for this combination of types
            t_u = theano.clone(self.u.t_f, replace={self.u.t_x[0]: t_pi_comb})
            # Start summing up
            t_sum_u_over_comb += p_comb * t_u
        #theano.printing.pydotprint(t_sum_u_over_comb, outfile='tmp.png')
        # Take the expectation over the Xi's numerically
        Z, w_unorm = design.sparse_grid(self.num_agents, self._sg_level, 'GH')
        Xi = Z * np.sqrt(2.0)
        w = w_unorm / np.sqrt(np.pi ** self.num_agents)
        t_tmp = theano.clone(t_sum_u_over_comb,
                    replace=dict((t_xis[i], Xi[:, i])
                                 for i in range(self.num_agents)))
        #theano.printing.pydotprint(t_tmp, outfile='tmp.png')
        # THEANO OBJECT REPRESENTING THE EXPECTED UTILITY OF THE PRINCIPAL:
        t_exp_u_raw = T.dot(w, t_tmp)
        t_e_stars_f = flatten(t_e_stars)
        t_as_f = flatten(t_as)
        self._exp_u_raw = Function(t_e_stars_f + t_as_f, t_exp_u_raw)
        # Take derivative with respect to e_stars
        self._exp_u_raw_g_e = self._exp_u_raw.grad(t_e_stars_f)
        # Take derivative with respect to the as
        self._exp_u_raw_g_a = self._exp_u_raw.grad(t_as_f)

    def compile(self):
        """
        Compile all Functions.
        """
        run_and_print(self.exp_u_raw.compile, self.verbosity)
        run_and_print(self.exp_u_raw_g_e.compile, self.verbosity)
        run_and_print(self.exp_u_raw_g_a.compile, self.verbosity)
        for i in range(self.num_agents):
            for k in range(self.agents[i].num_types):
                run_and_print(self._irc[i][k].compile, self.verbosity)
        self._compiled = True

    def evaluate(self, a):
        """
        Evaluate the expected utility of the principal along its gradient
        wrt to a.
        """
        if not self._compiled:
            raise RuntimeError('You must compile first.')
        # We will return a dictionary with the results
        res = {}
        # aas[i][k] is the transfer parameters of agent i type k
        aas = [[] for i in range(self.num_agents)]
        # e_stars[i][k] is the optimal effort of agent i type k
        e_stars = [[] for i in range(self.num_agents)]
        # e_stars_g_a[i][k] is the gradient of the optimal effort of agent i
        # type k with respect to aas[i][k]
        e_stars_g_a = [[] for i in range(self.num_agents)]
        # exp_u_pi_e_stars[i][k] is the expected utility of agent i type k
        # at e_stars[i][k] using transfer parameters aas[i][k]
        exp_u_pi_e_stars = [[] for i in range(self.num_agents)]
        count_as = 0
        for i in range(self.num_agents):
            ag_i = self.agents[i]
            a_i = a[count_as:count_as + self.t.num_a * ag_i.num_types]
            count_as += ag_i.num_types
            for k in range(ag_i.num_types):
                a_ik = a_i[k * self.t.num_a:(k+1) * self.t.num_a]
                aas[i].append(a_ik)
                res_ik = self._irc[i][k].evaluate(a_ik)
                e_stars[i].append(res_ik['e_star'])
                e_stars_g_a[i].append(res_ik['e_star_g_a'])
                exp_u_pi_e_stars[i].append(res_ik['exp_u_pi_e_star'])
        res['exp_u_pi_agents'] = exp_u_pi_e_stars
        # Flatten the list in order to pass them to the functions
        e_stars_f = flatten(e_stars)
        aas_f = flatten(aas)
        e_stars_ga_f = flatten(e_stars_g_a)
        # Evaluate the expected utility of the principal
        exp_u_pi_0 = self._exp_u_raw(*(e_stars_f + aas_f))
        res['exp_u_pi_0'] = exp_u_pi_0
        res['e_stars'] = e_stars_f
        # Evaluate derivative of exp_u_pi_0 with respect to e at e_stars and a
        exp_u_pi_0_raw_g_e = self._exp_u_raw_g_e(*(e_stars_f + aas_f))
        # Evaluate derivative of exp_u_pi_0 with respect to a at e_stars and a
        exp_u_pi_0_raw_g_a = self._exp_u_raw_g_a(*(e_stars_f + aas_f))
        # Evaluate the total derivative of exp_u_pi_0 wrt a's at e_stars and a
        d_exp_u_da_list = []
        num_agent_types = np.sum([a.num_types for a in self._agents])
        tmp = np.zeros((self.num_param,))
        for i in range(num_agent_types):
            part1 = exp_u_pi_0_raw_g_e[i] * e_stars_ga_f[i]
            part2 = exp_u_pi_0_raw_g_a[i]
            d_exp_u_da_list += [part1 + part2]
        res['d_exp_u_pi_0_da'] = np.hstack(d_exp_u_da_list)
        return res

    def optimize_contract(self, *args):
        """
        Returns the optimal contract.
        """
        # Optimization bounds
        # bnds = np.array([(0.0, 2.0) for _ in range(self.num_param)])

        n_bnds = self.num_param / self.t.num_a
        if self.t.num_a == 4:
            bnds = np.array([(0.0, 0.05), (0.0001, .5), (0.7, 1.5), (0.0, .6)]*n_bnds)
        else:
            bnds = np.array([(0.0, 0.05), (0.0001, .8), (0.7, 1.5)]*n_bnds)

        # The objective function
        def obj_fun(a, obj):
            res = obj.evaluate(a)
            return -res['exp_u_pi_0'], -res['d_exp_u_pi_0_da']

        # The participation constraints
        def part_const(a, irc_ik, i, k, num_types, num_a, count_as):
            # Extract the part of a that is relevant
            a_i    = a[count_as:count_as + num_a * num_types]
            a_ik   = a_i[k * num_a:(k+1) * num_a]
            res_ik = irc_ik.evaluate(a_ik)
            return res_ik['exp_u_pi_e_star']

        # The incentive comptability constraints
        def inc_comp_const(a, irc_ik, i, k, kf,
                            num_types, num_a, count_as):
            # Extract the part of a that is relevant
            a_i     = a[count_as:count_as + num_a * num_types]
            a_ik    = a_i[k * num_a:(k+1) * num_a]
            a_ikf   = a_i[kf * num_a:(kf+1) * num_a]
            res_ik  = irc_ik.evaluate(a_ik)
            res_ikf = irc_ik.evaluate(a_ikf)
            # res_ik >= res_ikf
            return res_ik['exp_u_pi_e_star'] - res_ikf['exp_u_pi_e_star']

        # The Jacobian of the participation constraint
        def part_const_jac(a, irc_ik, i, k, num_types, num_a, count_as):
            a_i    = a[count_as:count_as + num_a * num_types]
            a_ik   = a_i[k * num_a:(k+1) * num_a]
            res_ik = irc_ik.evaluate(a_ik)
            jac_ik = res_ik['exp_u_pi_e_star_g_a']
            jac    = np.zeros(a.shape)
            jac[count_as + num_a * k:count_as + num_a * (k + 1)] = jac_ik
            return jac

        # The incentive comptability constraints
        def inc_comp_const_jac(a, irc_ik, i, k, kf,
                                num_types, num_a, count_as):
            # Extract the part of a that is relevant
            a_i     = a[count_as:count_as + num_a * num_types]
            a_ik    = a_i[k * num_a:(k+1) * num_a]
            a_ikf   = a_i[kf * num_a:(kf+1) * num_a]
            res_ik  = irc_ik.evaluate(a_ik)
            res_ikf = irc_ik.evaluate(a_ikf)
            jac_ik  = res_ik['exp_u_pi_e_star_g_a']
            jac_ikf = res_ikf['exp_u_pi_e_star_g_a']
            jac     = np.zeros(a.shape)
            jac[count_as + num_a * k:count_as + num_a * (k + 1)] = jac_ik
            jac[count_as + num_a * kf:count_as + num_a * (kf + 1)] = -jac_ikf
            return jac

        def eval_f(a, user_data=None):
            res = self.evaluate(a)
            return -res['exp_u_pi_0']

        def eval_grad_f(a, user_data=None):
            res = self.evaluate(a)
            return np.array(-res['d_exp_u_pi_0_da']).flatten()

        def eval_g(x, user_data=None):
            part_cons = []
            count_as = 0
            for i in range(self.num_agents):
                ag_i = self.agents[i]
                for k in range(ag_i.num_types):
                    con = part_const(x, self._irc[i][k], i, k,
                                     ag_i.num_types, self.t.num_a,
                                     count_as)
                    part_cons.append(con)
                count_as += ag_i.num_types
            count_as = 0
            for i in range(self.num_agents):
                ag_i = self.agents[i]
                for k in range(ag_i.num_types):
                    for kf in range(ag_i.num_types):
                        if kf != k:
                            con = inc_comp_const(x, self._irc[i][k],i,
                                                k, kf, ag_i.num_types,
                                                self.t.num_a, count_as)
                            part_cons.append(con)
                count_as += ag_i.num_types
            return np.array(part_cons).flatten()

        nvar = self.num_param
        x_L = np.array(bnds[:,0], dtype=np.float_)
        x_U = np.array(bnds[:,1], dtype=np.float_)
        test = np.array(np.zeros(nvar))
        self.ncon = eval_g(test).shape[0]

        g_L = np.array([0.0]*self.ncon, dtype=np.float_)
        g_U = np.array([pow(10.0,20)]*self.ncon, dtype=np.float_)

        def eval_jac_g(x, flag, user_data=None):
            if flag:
                return (np.array([[_]*self.num_param for _ in range(self.ncon)]).flatten(),
                        np.array(list(np.arange(self.num_param))*self.ncon))
            else:
                part_cons = []
                count_as = 0
                for i in range(self.num_agents):
                    ag_i = self.agents[i]
                    for k in range(ag_i.num_types):
                        con = part_const_jac(x, self._irc[i][k],
                                             i, k, ag_i.num_types,
                                             self.t.num_a, count_as)
                        part_cons.append(con)
                    count_as += ag_i.num_types
                count_as = 0
                for i in range(self.num_agents):
                    ag_i = self.agents[i]
                    for k in range(ag_i.num_types):
                        for kf in range(ag_i.num_types):
                            if kf != k:
                                con = inc_comp_const_jac(x,
                                                        self._irc[i][k],
                                                        i, k, kf,
                                                        ag_i.num_types,
                                                        self.t.num_a, count_as)
                                part_cons.append(con)
                    count_as += ag_i.num_types
                return np.array(part_cons).flatten()

        nlp = pyipopt.create(nvar, x_L, x_U, self.ncon, g_L, g_U,
                             self.num_param * self.ncon, nvar**2, eval_f,
                             eval_grad_f, eval_g, eval_jac_g)
        nlp.int_option('max_iter', 1000)
        nlp.int_option('print_frequency_iter',100)
        nlp.num_option('tol', 1e-6)
        # nlp.str_option('linear_solver','ma27')

        comp = 1.0e99
        x_ret = None
        x0 = np.array(np.zeros(nvar))
        if not args:
            num_restarts = 10
            samples = lhs(self.num_param, samples = num_restarts, criterion = 'c')
        elif len(args) == 1:
            num_restarts = args[0]
            samples = lhs(self.num_param, samples = num_restarts, criterion = 'c')
        else:
            num_restarts_total  = args[0]
            samples             = args[1]
            ind_seed            = np.array(args[2]).flatten()
            samples             = samples[ind_seed, :]
            num_restarts        = np.array(ind_seed).flatten().shape[0]
        samples = bnds[:,0] + samples*(bnds[:,1]-bnds[:,0])
        final_result = {}
        for i in range(num_restarts):
            print(('restart number:', i+1))
            x0 = samples[i,:]
            x, zl, zu, constraint_multipliers, obj, status = nlp.solve(x0)
            print(('status', status))
            if obj < comp:
                comp = obj
                x_ret = x
                print(x)
                final_result['x']   = x_ret
                final_result['obj'] = -obj
        return final_result

        # Test optimization

        # fun_min = 1e99
        # res_min = None
        # for n in range(num_restarts):
        #     a0 = bnds[:, 0] + (bnds[:, 1] - bnds[:, 0]) * np.random.rand(self.num_param)
        #     print n
        #     try:
        #         res = opt.minimize(obj_fun, a0, jac=True, args=(self,), method='slsqp',
        #                            bounds=bnds, constraints=part_cons, options={'disp':True})
        #         if fun_min > res['fun'] and res.success:
        #             fun_min = res['fun']
        #             res_min = res
        #             print res
        #             print '*' * 80
        #             r = self.evaluate(res_min.x)
        #             print 'contract parameters:', res_min.x
        #             print r
        #             print '*' * 80
        #     except:
        #         print 'Optimization failed.'
        # return res_min

    def _setup_irc(self):
        """
        Set up individual rationality constraints.
        """
        # Individual rationality constraints (i-k)
        irc = [[] for _ in range(self.num_agents)]
        for i in range(self.num_agents):
            for k in range(self.agents[i].num_types):
                irc[i].append(
                        IndividualRationality(self.agents[i].agent_types[k], self.t))
        self._irc = irc

    def _agent_type_range(self):
        """
        Returns an iterator over all possible combinations of agent types.
        """
        return itertools.product(*(list(range(a.num_types)) for a in self.agents))

    @property
    def verbosity(self):
        """
        Return the verbosity level of the class.
        """
        return self._verbosity

    @property
    def exp_u_raw(self):
        """
        Get the expected utility of the principal as a Function with inputs
        e_star and the transfer function parameters a.
        """
        return self._exp_u_raw

    @property
    def exp_u_raw_g_e(self):
        """
        Return the derivative of the expected utility of the principal with
        respect to all e_stars as a function of e_star and the transfer
        function parameters a.
        """
        return self._exp_u_raw_g_e

    @property
    def exp_u_raw_g_a(self):
        """
        Return the derivative of the expected utility of the principal with
        respect to all transfer function parameters a as a function of e_star
        and a.
        """
        return self._exp_u_raw_g_a

    @property
    def num_agents(self):
        """
        Get the number of agents.
        """
        return len(self.agents)

    @property
    def agents(self):
        """
        Get the agents.
        """
        return self._agents

    @property
    def t(self):
        """
        Get the transfer function.
        """
        return self._t

    @property
    def v(self):
        """
        Get the value function.
        """
        return self._v

    @property
    def u(self):
        """
        Get the utility function of the principal.
        """
        return self._u

    @property
    def num_param(self):
        """
        Get the total number of transfer function parameters.
        """
        return self._num_param

    def __repr__(self):
        """
        Return a string representation of the class.
        """
        return 'PrincipalProblem(v=' + str(self.v) + \
                ', agents=' + str(self.agents) + \
                ', t=' + str(self.t)

if __name__ == '__main__':
    from ._quality_functions import *
    from ._cost_functions import *
    from ._utility_functions import *
    from ._transfer_functions import *
    from ._value_functions import *
    import numdifftools as nd

    # Creat an example to test the optimize_contract

    agent_type11 = AgentType(LinearQualityFunction(2., 0.1),
                            QuadraticCostFunction(0.02),
                            ExponentialUtilityFunction())

    agent_type12 = AgentType(LinearQualityFunction(1.2, 0.3),
                            QuadraticCostFunction(0.02),
                            ExponentialUtilityFunction(.0))
    agents = Agent([agent_type11])

    t = RequirementPlusIncentiveTransferFunction(gamma=30.)

    p = PrincipalProblem(ExponentialUtilityFunction(),
                        RequirementValueFunction(1, gamma=5.),
                        agents, t)
    p.compile()
    a = [1.54857533e-06, 8.96740975e-03, 1.21648850e+00, 7.43227452e-03]
    res = p.evaluate(a)
    print(res)
    quit()
    res = p.optimize_contract()
    print('evaluate the variables in the optimum point of the contract')
    print(res)
    print((p.evaluate(res['x'])))
    quit()

    # Create an agent of a specific type
    agent_type11 = AgentType(LinearQualityFunction(1.5, 0.05),
                           QuadraticCostFunction(0.0),
                           ExponentialUtilityFunction())
    agent_type12 = AgentType(LinearQualityFunction(1.5, 0.2),
                            QuadraticCostFunction(0.1),
                            ExponentialUtilityFunction(2.0))
    agent_type21 = AgentType(LinearQualityFunction(2.5, 0.1),
                            QuadraticCostFunction(0.3),
                            ExponentialUtilityFunction(1.5))
    agent_type22 = AgentType(LinearQualityFunction(1.5, 0.3),
                            QuadraticCostFunction(0.1),
                            ExponentialUtilityFunction(0.0))

    # Create the agents
    agent1 = Agent([agent_type11, agent_type12])
    agent2 = Agent([agent_type21, agent_type22])
    agents = [agent1, agent2]
    # Create a transfer function
    t = RequirementPlusIncentiveTransferFunction()

    # Create the principal's problem
    p = PrincipalProblem(ExponentialUtilityFunction(0.0),
                         RequirementValueFunction(2),
                         agents, t)

    # Compile everything
    # p.compile()

    num_xis = 10000
    xi = np.random.randn(num_xis)

    # Test 1: N=1, M=1
    agent_type = AgentType(LinearQualityFunction(2.0, 0.1),
                            QuadraticCostFunction(0.02),
                            ExponentialUtilityFunction())
    agents = Agent(agent_type)
    t = RequirementPlusIncentiveTransferFunction(gamma = 30.0)

    p = PrincipalProblem(ExponentialUtilityFunction(),
                        RequirementValueFunction(1, gamma=10.),
                        agents, t)
    p.compile()
    q1 = p.agents[0].agent_types[0].q
    v1 = p.v
    t1 = p.t
    q1.compile()
    v1.compile()
    t1.compile()
    a = [1.54857533e-06, 8.96740975e-03, 1.21648850e+00, 7.43227452e-03]
    result = p.evaluate(a)
    print(result)
    quit()
    mc = np.sum(v1(q1(result['e_stars'][0],xi)) - \
                t1(q1(result['e_stars'][0], xi), a)) / num_xis
    print('Test cases for N=1, M=1:')
    print(('expected utility check for N=1, M=1: Monte Carlo: {}, Collocation: {}'.format(mc, result['exp_u_pi_0'])))
    exp_u = p.exp_u_raw
    exp_u.compile()
    p._setup_irc
    ir1 = p._irc[0][0]
    ir1.compile()

    f1 = lambda _a: exp_u(result['e_stars'][0], _a)
    f2 = lambda _e: exp_u(_e, a)
    f3 = lambda _a: ir1.evaluate(_a)['e_star']

    gf1 = nd.Gradient(f1)
    gf2 = (f2(result['e_stars'][0]+1.0e-6)-f2(result['e_stars'][0]-1.0e-6))/(2.e-6)
    gf3 = nd.Gradient(f3)

    dexp_numerical = gf2 * gf3(a) + gf1(a)
    print(('dE[u]/da11 check for N=1, M=1: Numerical derivative: {}, AD theano: {}'.format(dexp_numerical, result['d_exp_u_pi_0_da'])))
    print('##########')
    # Test2: N=1, M=2

    agent_type11 = AgentType(LinearQualityFunction(1.2, 0.2),
                            QuadraticCostFunction(0.1),
                            ExponentialUtilityFunction(0.0))
    agent_type12 = AgentType(LinearQualityFunction(1.1, 0.3),
                            QuadraticCostFunction(0.1),
                            ExponentialUtilityFunction(2.0))
    agents = Agent([agent_type11, agent_type12])

    t = RequirementPlusIncentiveTransferFunction()
    p = PrincipalProblem(ExponentialUtilityFunction(),
                        RequirementValueFunction(1),
                        agents, t)
    p.compile()

    q1 = p.agents[0].agent_types[0].q
    q2 = p.agents[0].agent_types[1].q
    v1 = p.v
    t1 = p.t
    q1.compile()

    q2.compile()
    v1.compile()
    t1.compile()

    a1 = np.array([0.0, 0.2, 1.0, 0.05])
    a2 = np.array([0.05, 0.3, 1.0, 0.1])
    a = np.concatenate([a1, a2])
    result = p.evaluate(a)

    temp1 = 0.5*(v1(q1(result['e_stars'][0],xi)) - \
                t1(q1(result['e_stars'][0], xi), a1))
    temp2 = 0.5*(v1(q2(result['e_stars'][1],xi)) - \
                t1(q2(result['e_stars'][1], xi), a2))
    mc = np.sum(temp1 + temp2) / num_xis
    print('Test cases for N=1, M=2')
    print(('expected utility check for N=1, M=2: Monte Carlo: {}, Collocation: {}'.format(mc, result['exp_u_pi_0'])))

    exp_u = p.exp_u_raw
    exp_u.compile()
    p._setup_irc
    ir1 = p._irc[0][0]
    ir2 = p._irc[0][1]
    ir1.compile()
    ir2.compile()

    f1 = lambda _a1: exp_u(result['e_stars'][0], result['e_stars'][1], _a1, a2)
    f2 = lambda _e1, _e2: exp_u(_e1, _e2, a1, a2)
    f3 = lambda _a: ir1.evaluate(_a)['e_star']
    gf1 = nd.Gradient(f1)
    gf2 = (f2(result['e_stars'][0]+1.0e-6, result['e_stars'][1])-\
           f2(result['e_stars'][0]-1.0e-6, result['e_stars'][1]))/(2.e-6)
    gf3 = nd.Gradient(f3)
    dexp_numerical = gf2 * gf3(a1) + gf1(a1)
    print(('dE[u]/da_11 check for N=1, M=2: Numerical derivative: {}, AD theano: {}'.format(dexp_numerical, result['d_exp_u_pi_0_da'][0])))

    f1 = lambda _a2: exp_u(result['e_stars'][0], result['e_stars'][1], a1, _a2)
    f2 = lambda _e1, _e2: exp_u(_e1, _e2, a1, a2)
    f3 = lambda _a: ir2.evaluate(_a)['e_star']
    gf1 = nd.Gradient(f1)
    gf2 = (f2(result['e_stars'][0], result['e_stars'][1]+1.0e-6)-\
           f2(result['e_stars'][0], result['e_stars'][1]-1.e-6))/(2.e-6)
    gf3 = nd.Gradient(f3)
    dexp_numerical = gf2 * gf3(a2) + gf1(a2)
    print(('dE[u]/da_12 check for N=1, M=2: Numerical derivative: {}, AD theano: {}'.format(dexp_numerical, result['d_exp_u_pi_0_da'][1])))
    print('##########')

    # Test3: N=2, M=1

    agent_type11 = AgentType(LinearQualityFunction(1.5, 0.1),
                            QuadraticCostFunction(0.2),
                            ExponentialUtilityFunction(0.0))
    agent_type21 = AgentType(LinearQualityFunction(1.4, 0.1),
                            QuadraticCostFunction(0.1),
                            ExponentialUtilityFunction(2.0))
    agent1 = Agent(agent_type11)
    agent2 = Agent(agent_type21)
    agents = [agent1, agent2]

    t = RequirementPlusIncentiveTransferFunction()
    p = PrincipalProblem(ExponentialUtilityFunction(),
                        RequirementValueFunction(2),
                        agents, t)
    p.compile()

    q1 = p.agents[0].agent_types[0].q
    q2 = p.agents[1].agent_types[0].q
    v1 = p.v
    t1 = p.t
    q1.compile()
    q2.compile()
    v1.compile()
    t1.compile()

    a1 = np.array([0.0, 0.1, 1., 0.05])
    a2 = np.array([0.0, 0.2, 1., 0.0])
    a = np.concatenate([a1, a2])
    result = p.evaluate(a)
    xi_1 = np.random.randn(num_xis)
    xi_2 = np.random.randn(num_xis)
    temp = v1(q1(result['e_stars'][0], xi_1), q2(result['e_stars'][1], xi_2)) - \
            (t1(q1(result['e_stars'][0], xi_1), a1) + t1(q2(result['e_stars'][1], xi_2), a2))
    mc = np.sum(temp) / num_xis
    print('Test cases for N=2, M=1')
    print(('expected utility check for N=2, M=1: Monte Carlo: {}, Collocation: {}'.format(mc, result['exp_u_pi_0'])))
    quit()
    #[2.58410778e-05 1.00850982e-01 1.41734080e+00 3.03885263e-01]
    #{'d_exp_u_pi_0_da': array([-1.        , -0.73426853,  0.49732821, -0.08538814]), 'exp_u_pi_agents': [[2.5841077197397968e-05]], 'e_stars': [1.0], 'exp_u_pi_0': array(0.8999723)}


#! /usr/bin/env python3

from log.log import Logger
import random
import numpy as np

from .base_process_action import BaseProcessAction
from common.hand_card_utils import HandCardUtils
from enums.card_type_enum import CardTypeEnum

logger = Logger.getLog(__file__)

class ProcessThreeOneStrategy(BaseProcessAction):
    """
    E.g. [3334], [4443], [5556], ......
    """

    def __init__(self, hand_card_status, primary_item, **kwargs):
        super().__init__(hand_card_status, primary_item, **kwargs)

    def run(self):
        k = self.kwargs.pop('k', 1)
        exist_card = HandCardUtils.find_even_three(self.hand_card_status, k=k)
        if self.primary_item is not None:
            exist_card = list(filter(lambda x:x > self.primary_item,exist_card))
        if len(exist_card) == 0:
            logger.debug('Can not accept the card')
            return None, None, None
        rnd = random.randint(0,len(exist_card)-1)
        one_card = exist_card[rnd]
        exist_card = [one_card - ix for ix in reversed(range(k))]
        remain_card = self.__flat_card(self.hand_card_status, exist_card)
        if len(remain_card) < k:
            logger.debug('Can not accept the card')
            return None, None, None
        other_card = sorted(random.sample(remain_card, k))
        score = HandCardUtils.value_map(exist_card[-1], CardTypeEnum.CT_THREE_DOU, 3*k+k)
        put_card = list(map(lambda x:[x]*3, exist_card))
        put_card = np.reshape(put_card, (1, -1)).tolist()[0]
        put_card.extend(other_card)
        return put_card, score, exist_card[-1]

    def __flat_card(self, card_status, exclude_card):
        """
        Flatten these card
        E.g.
        card status is [0,0,0,1,3,2,2,2,0,0,0,0,0,0,0,0,1,0]
        then flatten this is [3,4,4,4,5,5,6,6,7,7,QUEEN]
        """
        flat_card = []
        for card, count in enumerate(card_status):
            if card in exclude_card:
                count -= 3
            if count > 0:
                flat_card.extend([card]*count)
        return flat_card