import json
import time
import tempfile
import botocore

from boto3.dynamodb.conditions import Key
from boto3.dynamodb.types import TypeDeserializer
from sys import maxsize
import cloud.shortuuid as shortuuid

def get_boto3_session(credentials):
    import boto3
    bundle = credentials['aws']
    access_key = bundle['access_key']
    secret_key = bundle['secret_key']
    region_name = bundle.get('region', 'ap-northeast-2')
    session = boto3.Session(
        aws_access_key_id=access_key,
        aws_secret_access_key=secret_key,
        region_name=region_name,
    )
    return session

class APIGateway:
    stage_name = 'prod_aws_interface'

    def __init__(self, boto3_session):
        self.region = boto3_session.region_name
        self.client = boto3_session.client('apigateway')
        self.lambda_client = boto3_session.client('lambda')
        self.iam_client = IAM(boto3_session)

    def get_rest_api_id(self, rest_api_name):
        rest_api_id = None
        apis = self.get_rest_apis().get('items', [])
        for api in apis:
            if api['name'] == rest_api_name:
                rest_api_id = api['id']
                break
        if not rest_api_id:
            response = self.create_rest_api(rest_api_name)
            rest_api_id = response['id']
        return rest_api_id

    def delete_rest_api_by_name(self, rest_api_name):
        try:
            rest_api_id = self.get_rest_api_id(rest_api_name)
            response = self.client.delete_rest_api(
                restApiId=rest_api_id
            )
            return response
        except BaseException as ex:
            print(ex)
            return None

    def get_root_resource_id(self, rest_api_id):
        resources = self.get_resources(rest_api_id).get('items', [])
        parent_id = None
        for res in resources:
            if res['path'] == '/':
                parent_id = res['id']
        return parent_id

    def get_lambda_function_resource_id(self, rest_api_id, lambda_func_name):
        resources = self.get_resources(rest_api_id).get('items', [])
        resource_id = None
        for res in resources:
            if res.get('pathPart') == lambda_func_name:
                resource_id = res['id']
        return resource_id

    def get_rest_api_url(self, cloud_api_name):
        base_url = 'https://{}.execute-api.{}.amazonaws.com/{}/{}'
        api_id = self.get_rest_api_id(cloud_api_name)
        region = self.region
        stage = self.stage_name
        url = base_url.format(api_id, region, stage, cloud_api_name)
        return url

    def connect_with_lambda(self, cloud_api_name, lambda_func_name):
        aws_region = self.region
        api_client = self.client
        aws_lambda = self.lambda_client

        # Find existing rest api
        rest_api_id = self.get_rest_api_id(cloud_api_name)
        root_resource_id = self.get_root_resource_id(rest_api_id)
        resource_id = self.get_lambda_function_resource_id(rest_api_id, lambda_func_name)

        stage_name = self.stage_name

        if not resource_id:
            resource_id = api_client.create_resource(
                restApiId=rest_api_id,
                parentId=root_resource_id,  # resource id for the Base API path
                pathPart=lambda_func_name
            )['id']

        self.put_method(rest_api_id, resource_id, 'POST')

        lambda_version = aws_lambda.meta.service_model.api_version

        aws_account_id = self.iam_client.get_account_id()

        uri_data = {
            "aws-region": aws_region,
            "api-version": lambda_version,
            "aws-acct-id": aws_account_id,
            "lambda-function-name": lambda_func_name,
        }
        uri = self.get_uri(uri_data)

        integration_response_param = {
            'method.response.header.Access-Control-Allow-Headers': '\'Content-Type,X-Amz-Date,Authorization,X-Api-Key,X-Amz-Security-Token,X-Requested-With\'',
            'method.response.header.Access-Control-Allow-Methods': '\'POST,OPTIONS\'',
            'method.response.header.Access-Control-Allow-Origin': '\'*\''
        }
        method_response_param = {
            'method.response.header.Access-Control-Allow-Headers': False,
            'method.response.header.Access-Control-Allow-Origin': False,
            'method.response.header.Access-Control-Allow-Methods': False,
            'method.response.header.X-Requested-With': False,
        }

        # create integration
        self.put_integration(rest_api_id, resource_id, 'POST', uri)
        self.put_integration_response(rest_api_id, resource_id, 'POST')
        self.put_method_response(rest_api_id, resource_id, 'POST', method_response_param)

        uri_data['aws-api-id'] = rest_api_id
        post_source_arn = self.get_source_arn(uri_data, 'POST')

        print('put_permission post'.center(80, '-'))
        self.put_permission(lambda_func_name, post_source_arn)

        # CORS OPTION
        self.put_method(rest_api_id, resource_id, 'OPTIONS')
        self.put_method_response(rest_api_id, resource_id, 'OPTIONS', method_response_param)
        self.put_integration(rest_api_id, resource_id, 'OPTIONS', uri)
        self.put_integration_response(rest_api_id, resource_id, 'OPTIONS', integration_response_param)

        print('create_deployment'.center(80, '-'))
        api_client.create_deployment(
            restApiId=rest_api_id,
            stageName=stage_name,
        )

    def put_method(self, rest_api_id, resource_id, method_type, auth_type='NONE'):
        try:
            response = self.client.put_method(
                restApiId=rest_api_id,
                resourceId=resource_id,
                httpMethod=method_type,
                authorizationType=auth_type,
                apiKeyRequired=False,
            )
        except BaseException as ex:
            print(ex)
            return None
        return response

    def put_method_response(self, rest_api_id, resource_id, method_type, response_parameters=dict()):
        try:
            response = self.client.put_method_response(
                restApiId=rest_api_id,
                resourceId=resource_id,
                httpMethod=method_type,
                statusCode="200",
                responseParameters=response_parameters,
            )
        except BaseException as ex:
            response = None
            print(ex)
        return response

    def get_uri(self, uri_data):
        uri = "arn:aws:apigateway:{aws-region}:lambda:path/{api-version}/functions/arn:aws:lambda:{aws-region}:" \
               "{aws-acct-id}:function:{lambda-function-name}/invocations".format(**uri_data)
        return uri

    def put_integration(self, rest_api_id, resource_id, method_type, uri):
        integration_resp = self.client.put_integration(
            restApiId=rest_api_id,
            resourceId=resource_id,
            httpMethod=method_type,
            type="AWS",
            integrationHttpMethod=method_type,
            uri=uri,
        )
        return integration_resp

    def put_integration_response(self, rest_api_id, resource_id, method_type, response_parameters=dict()):
        response = self.client.put_integration_response(
            restApiId=rest_api_id,
            resourceId=resource_id,
            httpMethod=method_type,
            statusCode="200",
            selectionPattern=".*",
            responseParameters=response_parameters,
        )
        return response

    def get_source_arn(self, uri_data, method_type):
        method_type = 'POST'
        arn = "arn:aws:execute-api:{aws-region}:{aws-acct-id}:{aws-api-id}/*/" + method_type + "/{lambda-function-name}"
        arn = arn.format(**uri_data)
        return arn

    def put_permission(self, lambda_func_name, source_arn):
        statement_id = 'state{}'.format(lambda_func_name)

        try:
            _ = self.lambda_client.remove_permission(
                FunctionName=lambda_func_name,
                StatementId=statement_id,
            )
        except Exception:
            print('Failed to remove permissions for {}'.format(lambda_func_name))
            pass

        try:
            self.lambda_client.add_permission(
                FunctionName=lambda_func_name,
                StatementId=statement_id,
                Action="lambda:InvokeFunction",
                Principal="apigateway.amazonaws.com",
                SourceArn=source_arn
            )
        except Exception:
            raise Exception('Failed to put permissions for {}'.format(lambda_func_name))

    def get_method(self, rest_api_id, resource_id, method_type='POST'):
        response = self.client.get_method(
            restApiId=rest_api_id,
            resourceId=resource_id,
            httpMethod=method_type
        )
        return response

    def get_rest_apis(self):
        response = self.client.get_rest_apis(
            limit=100
        )
        return response

    def create_rest_api(self, api_name):
        response = self.client.create_rest_api(
            name=api_name,
            endpointConfiguration={
                'types': [
                    'EDGE'
                ]
            }
        )
        return response

    def create_resource(self, rest_api_id, parent_id, path_part):
        response = self.client.create_resource(
            restApiId=rest_api_id,
            parentId=parent_id,
            pathPart=path_part
        )
        return response

    def get_resources(self, rest_api_id):
        response = self.client.get_resources(
            restApiId=rest_api_id,
            limit=100,
        )
        return response

    def delete_rest_api(self, rest_api_id):
        return self.client.delete_rest_api(
            restApiId=rest_api_id
        )

    def get_method_response(self, rest_api_id, resource_id, method_type, status_code):
        response = self.client.get_method_response(
            restApiId=rest_api_id,
            resourceId=resource_id,
            httpMethod=method_type,
            statusCode=status_code
        )
        return response

class DynamoDB:
    def __init__(self, boto3_session):
        self.client = boto3_session.client('dynamodb')
        self.resource = boto3_session.resource('dynamodb')

    def init_table(self, table_name):
        self.create_table(table_name)
        # self.update_table(table_name, index={
        #     'hash_key': 'partition',
        #     'hash_key_type': 'S',
        #     'sort_key': 'creationDate',
        #     'sort_key_type': 'N'
        # })
        # self.update_table(table_name, index={
        #     'hash_key': 'invertedQuery',
        #     'hash_key_type': 'S',
        #     'sort_key': 'creationDate',
        #     'sort_key_type': 'N'
        # })

    def create_table(self, table_name):
        try:
            response = self.client.create_table(
                AttributeDefinitions=[
                    {
                        'AttributeName': 'id',
                        'AttributeType': 'S'
                    }, {
                        'AttributeName': 'partition',
                        'AttributeType': 'S'
                    }, {
                        'AttributeName': 'invertedQuery',
                        'AttributeType': 'S'
                    }, {
                        'AttributeName': 'creationDate',
                        'AttributeType': 'N'
                    }
                ],
                TableName=table_name,
                KeySchema=[
                    {
                        'AttributeName': 'id',
                        'KeyType': 'HASH'
                    },
                ],
                BillingMode='PAY_PER_REQUEST',
                StreamSpecification={
                    'StreamEnabled': True,
                    'StreamViewType': 'KEYS_ONLY'
                },
                GlobalSecondaryIndexes=[
                    {
                        'IndexName': 'partition-creationDate',
                        'KeySchema': [
                            {
                                'AttributeName': 'partition',
                                'KeyType': 'HASH'
                            }, {
                                'AttributeName': 'creationDate',
                                'KeyType': 'RANGE'
                            },
                        ],
                        'Projection': {
                            'ProjectionType': 'ALL'
                        }
                    }, {
                        'IndexName': 'invertedQuery-creationDate',
                        'KeySchema': [
                            {
                                'AttributeName': 'invertedQuery',
                                'KeyType': 'HASH'
                            }, {
                                'AttributeName': 'creationDate',
                                'KeyType': 'RANGE'
                            },
                        ],
                        'Projection': {
                            'ProjectionType': 'ALL'
                        }
                    },
                ]
            )
            print('CREATING TABLE...')
            self.client.get_waiter('table_exists').wait(TableName=table_name)
            return response
        except Exception as ex:
            print(ex)
            return None

    def update_table(self, table_name, index):
        attr_updates = []
        index_updates = []
        hash_key = index['hash_key']
        hash_key_type = index['hash_key_type']
        sort_key = index.get('sort_key', None)
        sort_key_type = index.get('sort_key_type', None)
        key_schema = [
            {
                'AttributeName': hash_key,
                'KeyType': 'HASH'
            }
        ]
        if sort_key:
            index_name = hash_key + '-' + sort_key
            key_schema.append({
                'AttributeName': sort_key,
                'KeyType': 'RANGE'
            })
        else:
            index_name = hash_key
        index_create = {
            'Create': {
                'IndexName': index_name,
                'KeySchema': key_schema,
                'Projection': {
                    'ProjectionType': 'ALL'
                }
            }
        }
        hash_key_update = {
            'AttributeName': hash_key,
            'AttributeType': hash_key_type
        }
        index_updates.append(index_create)
        attr_updates.append(hash_key_update)
        if sort_key:
            sort_key_update = {
                'AttributeName': sort_key,
                'AttributeType': sort_key_type
            }
            attr_updates.append(sort_key_update)

        while True:
            try:
                response = self.client.update_table(
                    AttributeDefinitions=attr_updates,
                    TableName=table_name,
                    GlobalSecondaryIndexUpdates=index_updates
                )
                return response
            except Exception as e:
                print(e)
                return e

    def delete_table(self, name):
        try:
            response = self.client.delete_table(
                TableName=name
            )
            return response
        except BaseException as ex:
            print(ex)
            return None

    def create_partition(self, table_name, partition):
        item = {
            'name': partition
        }
        response = self.put_item(table_name, 'partition-list', item, partition, indexing=False)
        return response

    def get_partition(self, table_name, partition):
        response = self.get_item(table_name, partition)
        return response.get('Item', None)

    def delete_partition(self, table_name, partition):
        return self.delete_item(table_name, partition)

    def get_partitions(self, table_name):
        return self.get_items_in_partition(table_name, 'partition-list', limit=maxsize)

    def delete_item(self, table_name, item_id):
        item = self.get_item(table_name, item_id)
        partition = item.get('Item', {}).get('partition', None)
        if not partition:
            print('It cannot be removed. table_name: {}, item_id: {}'.format(table_name, item_id))
            return False
        response = self.client.delete_item(
            TableName=table_name,
            Key={
                'id': {
                    'S': item_id
                }
            }
        )
        self._add_item_count(table_name, '{}-count'.format(partition), value_to_add=-1)
        self._delete_inverted_query(table_name, item_id)
        return response

    def get_item(self, table_name, item_id):
        table = self.resource.Table(table_name)
        item = table.get_item(Key={
            'id': item_id
        })
        return item

    def put_item(self, table_name, partition, item, item_id=None, creation_date=None, indexing=True):
        if not item_id:
            item_id = str(shortuuid.uuid())
        if not creation_date:
            creation_date = int(time.time())
        table = self.resource.Table(table_name)
        item['id'] = item_id
        item['creationDate'] = creation_date
        item['partition'] = partition
        response = table.put_item(
            Item=item,
        )
        self._add_item_count(table_name, '{}-count'.format(partition))
        if indexing:
            self._delete_inverted_query(table_name, item_id)
            self._put_inverted_query(table_name, partition, item)
        return response

    def get_items(self, table_name, item_ids):
        keys = list([{'id': {'S': item_id}} for item_id in item_ids])
        response = self.client.batch_get_item(
            RequestItems={
                table_name: {
                    'Keys': keys,
                    'ConsistentRead': True
                }
            }
        )
        type_deserializer = TypeDeserializer()
        items = response['Responses'][table_name]
        for item in items:
            for key, value in item.items():
                value = type_deserializer.deserialize(value)
                item[key] = value

        return {'Items': items}

    def get_items_in_partition(self, table_name, partition, start_key=None, limit=100, reverse=False):
        scan_index_forward = not reverse
        index_name = 'partition-creationDate'
        table = self.resource.Table(table_name)
        self.get_items_eq_hash_key(table_name, index_name, 'partition', partition, start_key, limit)
        if not limit:
            limit = maxsize
        if start_key:
            response = table.query(
                IndexName=index_name,
                Limit=limit,
                ConsistentRead=False,
                ExclusiveStartKey=start_key,
                KeyConditionExpression=Key('partition').eq(partition),
                ScanIndexForward=scan_index_forward,
            )
        else:
            response = table.query(
                IndexName=index_name,
                Limit=limit,
                ConsistentRead=False,
                KeyConditionExpression=Key('partition').eq(partition),
                ScanIndexForward=scan_index_forward,
            )
        return response

    def get_inverted_queries(self, table_name, partition, field, operand, operation, start_key=None, limit=100, reverse=False):
        if operation == 'in' or operation == 'eq':
            hash_key_name = 'invertedQuery'
            sort_key_name = 'creationDate'
            hash_key = '{}-{}-{}-{}'.format(partition, field, operand, operation)
            index_name = '{}-{}'.format(hash_key_name, sort_key_name)
            response = self.get_items_eq_hash_key(table_name, index_name, hash_key_name, hash_key, start_key, limit, reverse)
            return response
        else:
            raise BaseException('an operation is must be <in> or <eq>')

    def get_items_eq_hash_key(self, table_name, index_name, hash_key_name, hash_key_value,
                              start_key=None, limit=100, reverse=False):
        key_expression = Key(hash_key_name).eq(hash_key_value)
        response = self.get_items_with_key_expression(table_name, index_name, key_expression, start_key, limit, reverse)
        return response

    def get_items_with_key_expression(self, table_name, index_name, key_expression,
                                      start_key=None, limit=100, reverse=False):
        scan_index_forward = not reverse
        table = self.resource.Table(table_name)
        if start_key:
            response = table.query(
                IndexName=index_name,
                Limit=limit,
                ConsistentRead=False,
                ExclusiveStartKey=start_key,
                KeyConditionExpression=key_expression,
                ScanIndexForward=scan_index_forward,
            )
        else:
            response = table.query(
                IndexName=index_name,
                Limit=limit,
                ConsistentRead=False,
                KeyConditionExpression=key_expression,
                ScanIndexForward=scan_index_forward,
            )
        return response

    def update_item(self, table_name, item_id, item):
        table = self.resource.Table(table_name)
        update_date = int(time.time())
        item['id'] = item_id
        item['_update_date'] = update_date
        response = table.put_item(
            TableName=table_name,
            Item=item,
        )
        partition = item.get('partition')
        self._delete_inverted_query(table_name, item_id)
        self._put_inverted_query(table_name, partition, item)
        return response

    def _put_item_count(self, table_name, count_id, value):
        response = self.put_item(table_name, 'meta_info', {'count': value}, item_id=count_id)
        return response

    def _add_item_count(self, table_name, count_id, value_to_add=1):
        response = self.client.update_item(
            ExpressionAttributeNames={
                '#A': 'count',
            },
            ExpressionAttributeValues={
                ':v': {
                    'N': str(value_to_add),
                }
            },
            Key={
                'id': {
                    'S': count_id,
                }
            },
            ReturnValues='ALL_NEW',
            TableName=table_name,
            UpdateExpression='ADD #A :v',
        )
        return response

    def get_item_count(self, table_name, count_id):
        response = self.get_item(table_name, count_id)
        return response

    def _eq_operands(self, value):
        value = str(value)
        return [value]

    def _put_inverted_query(self, table_name, partition, item):
        table = self.resource.Table(table_name)
        item_id = item.get('id')
        creation_date = item.get('creationDate', int(time.time()))
        with table.batch_writer() as batch:
            for field, value in item.items():
                for operand in self._eq_operands(value):
                    self._put_inverted_query_field(batch, partition, field, operand, 'eq', item_id, creation_date)

    def _put_inverted_query_field(self, table, partition, field, operand, operation, item_id, creation_date):
        _invertedQuery = '{}-{}-{}-{}'.format(partition, field, operand, operation)
        query = {
            'id': 'query-{}'.format(shortuuid.uuid()),
            'partition': 'index-{}'.format(item_id),
            'invertedQuery': _invertedQuery,
            'creationDate': creation_date,
            'item_id': item_id,
        }
        response = table.put_item(
            Item=query,
        )
        return response

    def _delete_inverted_query(self, table_name, item_id):
        table = self.resource.Table(table_name)
        items = self.get_items_in_partition(table_name, 'index-{}'.format(item_id), limit=maxsize).get('Items', [])
        with table.batch_writer() as batch:
            for item in items:
                inverted_query_id = item.get('id', None)
                batch.delete_item(
                    Key={
                        'id': inverted_query_id
                    }
                )

class Lambda:
    def __init__(self, boto3_session):
        self.client = boto3_session.client('lambda')

    def create_function(self, name, description, runtime, role_arn, handler, zip_file):
        response = self.client.create_function(
            FunctionName=name,
            Runtime=runtime,
            Role=role_arn,
            Handler=handler,
            Code={
                'ZipFile': zip_file
            },
            Description=description,
            Timeout=128,
            MemorySize=1024,
            Publish=True,
            TracingConfig={
                'Mode': 'Active'
            },
        )
        return response

    def update_function_code(self, name, zip_file):
        response = self.client.update_function_code(
            FunctionName=name,
            ZipFile=zip_file,
            Publish=True
        )
        return response

    def delete_function(self, name):
        try:
            response = self.client.delete_function(
                FunctionName=name,
            )
            return response
        except BaseException as ex:
            print(ex)
            return None

    def invoke_function(self, name, payload_bytes):
        response = self.client.invoke(
            FunctionName=name,
            InvocationType='RequestResponse',
            Payload=payload_bytes,
        )
        return response

class S3:
    def __init__(self, boto3_session):
        self.client = boto3_session.client('s3')
        self.resource = boto3_session.resource('s3')
        self.region = boto3_session.region_name

    @classmethod
    def to_dns_name(cls, bucket_name):
        def f(c):
            if c.isupper():
                return 'c.{}'.format(c.lower())
            else:
                return c
        bucket_name = [f(c) for c in bucket_name]
        bucket_name = ''.join(bucket_name)
        return bucket_name

    def init_bucket(self, bucket_name):
        try:
            self.create_bucket(bucket_name)
            print('create_bucket success')
        except Exception as ex:
            print(ex)

    def create_bucket(self, bucket_name):
        bucket_name = self.to_dns_name(bucket_name)
        response = self.client.create_bucket(
            ACL='private',
            Bucket=bucket_name,
            CreateBucketConfiguration={
                'LocationConstraint': self.region
            },
        )
        return response

    def upload_bin(self, bucket_name, file_name, binary):
        bucket_name = self.to_dns_name(bucket_name)
        with tempfile.TemporaryFile() as tmp:
            tmp.write(binary)
            tmp.seek(0)
            response = self.client.upload_fileobj(tmp, bucket_name, file_name)
            return response

    def delete_bin(self, bucket_name, file_name):
        bucket_name = self.to_dns_name(bucket_name)
        return self.resource.Object(bucket_name, file_name).delete()

    def download_bin(self, bucket_name, file_name):
        bucket_name = self.to_dns_name(bucket_name)
        try:
            with tempfile.NamedTemporaryFile() as data:
                self.client.download_fileobj(bucket_name, file_name, data)
                data.seek(0)
                return data.read()
        except botocore.exceptions.ClientError as e:
            if e.response['Error']['Code'] == "404":
                print("The object does not exist.")
                return None
            else:
                raise

    def delete_bucket(self, bucket_name):
        try:
            response = self.client.delete_bucket(
                Bucket=bucket_name
            )
            return response
        except BaseException as ex:
            print(ex)
            return None

class IAM:
    policy_arns = [
        'arn:aws:iam::aws:policy/AWSLambdaExecute',
        'arn:aws:iam::aws:policy/AmazonDynamoDBFullAccess',
        'arn:aws:iam::aws:policy/AmazonS3FullAccess',
        'arn:aws:iam::aws:policy/AWSXrayFullAccess',
    ]

    def __init__(self, boto3_session):
        self.client = boto3_session.client('iam')
        self.resource = boto3_session.resource('iam')

    def create_role_and_attach_policies(self, role_name):
        self.create_role(role_name)
        self.attach_policies(role_name, self.policy_arns)
        return self.get_role_arn(role_name)

    def get_role_arn(self, role_name):
        role = self.resource.Role(role_name)
        role_arn = role.arn
        return role_arn

    def delete_role(self, role_name):
        try:
            response = self.client.delete_role(
                RoleName=role_name
            )
            return response
        except BaseException as ex:
            print(ex)
            return None

    def create_role(self, role_name):
        assume_role_policy_document = {
            "Version": "2012-10-17",
            "Statement": [
                {
                    "Effect": "Allow",
                    "Principal": {
                        "Service": "lambda.amazonaws.com"
                    },
                    "Action": "sts:AssumeRole"
                }
            ]
        }
        assume_role_policy_document = json.dumps(assume_role_policy_document)
        try:
            response = self.client.create_role(
                Path='/',
                RoleName=role_name,
                AssumeRolePolicyDocument=assume_role_policy_document,
            )
        except:
            print('Already have a role', role_name)
            return None
        return response

    def attach_policies(self, role_name, policy_arns):
        for policy_arn in policy_arns:
            self.attach_policy(role_name, policy_arn)

    def attach_policy(self, role_name, policy_arn):
        try:
            response = self.client.attach_role_policy(
                RoleName=role_name,
                PolicyArn=policy_arn
            )
        except Exception as e:
            print('Failed to attach policy: {} by: {}'.format(role_name, e))
            return None
        return response

    def detach_all_policies(self, role_name):
        for policy_arn in self.policy_arns:
            self.detach_policy(role_name, policy_arn)

    def detach_policy(self, role_name, policy_arn):
        try:
            response = self.client.detach_role_policy(
                RoleName=role_name,
                PolicyArn=policy_arn
            )
            return response
        except BaseException as ex:
            print(ex)
            return None

    def get_account_id(self):
        account_id = self.resource.CurrentUser().arn.split(':')[4]
        return account_id

class CostExplorer:
    def __init__(self, boto3_session):
        self.client = boto3_session.client('ce', 'us-east-1')

    def get_cost_and_usage(self, start, end):
        response = self.client.get_cost_and_usage(
            TimePeriod={
                'Start': start,
                'End': end
            },
            Granularity='MONTHLY',
            Metrics=['AmortizedCost'],
            GroupBy=[
                {
                    'Type': 'DIMENSION',
                    'Key': 'SERVICE'
                },
            ],
        )
        return response

    def get_cost(self, start, end):
        response = self.client.get_cost_and_usage(
            TimePeriod={
                'Start': start,
                'End': end
            },
            Granularity='MONTHLY',
            Metrics=['BLENDED_COST']
        )
        return response


import wx
import wx.grid as  gridlib
from drumsT_SYS.SQLite_lib import School_Class

class PanelTwo(wx.Panel):
    """
    Show a grid with tabular data.
    It was inspired on codes from:
    http://www.blog.pythonlibrary.org/2013/10/31/wxpython-how-to-get-selected-cells-in-a-grid/
    http://www.blog.pythonlibrary.org/2010/04/04/wxpython-grid-tips-and-tricks/
    http://www.blog.pythonlibrary.org/2010/03/18/wxpython-an-introduction-to-grids/
    Official Documents:
    http://wxpython.org/Phoenix/docs/html/grid.Grid.html
    """
    def __init__(self, parent, nameSur, IDclass, path_db):
        """
        Display a list with data of all previous lessons of
        the student in object and relating to school
        year selected only
        """
        wx.Panel.__init__(self, parent, -1, style=wx.TAB_TRAVERSAL)
        #### set attributes:
        self.currentlySelectedCell = (0, 0) # row, col default
        self.rowEdit = None # tracking what row is was edited
        self.newsEdit = [] # list of all item edited
        self.backUp = [] # last backup for recovery
        self.index = 0 # how many items (rows)
        self.path_db = path_db
        self.IDclass = IDclass
        self.IDlesson = None

        self.InitUI()

    def InitUI(self):
        """
        Start with widget and panel setup
        """
        self.editBtn = wx.Button(self, wx.ID_ANY, ("Changes"))
        self.rollbackBtn = wx.Button(self, wx.ID_ANY, ("Rollback"))
        self.applyBtn = wx.Button(self, wx.ID_ANY, ("Apply Commit"))
        self.myGrid = gridlib.Grid(self)
        #### properties:
        self.myGrid.EnableEditing(False) # make all in read only
        self.myGrid.CreateGrid(150, 15)
        self.myGrid.SetColLabelValue(0, "ID lesson")
        self.myGrid.SetColLabelValue(1, "ID class")
        self.myGrid.SetColLabelValue(2, "Attendances")
        self.myGrid.SetColLabelValue(3, "Lesson Date")
        self.myGrid.SetColLabelValue(4, "Chart Reading")
        self.myGrid.SetColLabelValue(5, "Hands/foots Setting")
        self.myGrid.SetColLabelValue(6, "Rudiments")
        self.myGrid.SetColLabelValue(7, "Coordination")
        self.myGrid.SetColLabelValue(8, "Styles")
        self.myGrid.SetColLabelValue(9, "Minus One")
        self.myGrid.SetColLabelValue(10, "Other-1")
        self.myGrid.SetColLabelValue(11, "Other-2")
        self.myGrid.SetColLabelValue(12, "Other-3")
        self.myGrid.SetColLabelValue(13, "Votes")
        self.myGrid.SetColLabelValue(14, "Note/Reminder")
        #### set columns 0-1-2 in read only
        # see above address: www.../wxpython-an-introduction-to-grids/
        #attr = gridlib.GridCellAttr()
        #attr.SetReadOnly(True)
        #self.myGrid.SetColAttr(0, attr)
        #self.myGrid.SetColAttr(1, attr)
        #self.myGrid.SetColAttr(2, attr)
        ## oppure: self.myGrid.SetReadOnly(3, 3, True)
        #### properties
        self.editBtn.SetToolTipString("Changes text or value into the "
                                     "cells and append")
        self.rollbackBtn.SetToolTipString("Rollback to the last state or first "
                                     "to the last 'Apply-Commit'")
        self.applyBtn.SetFont(wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD, 0, ""))
        self.applyBtn.SetForegroundColour('#ff3f15')
        self.applyBtn.SetToolTipString("Make an update and commit new "
                                       "changes into database")
        self.editBtn.Disable()
        self.rollbackBtn.Disable()
        self.applyBtn.Disable()
        #### go to popular the grid:
        self.setting()
        #### Build Layout:
        sizer = wx.BoxSizer(wx.VERTICAL)
        gridSiz = wx.GridSizer(1,3,0,40)
        sizer.Add(self.myGrid, 1, wx.EXPAND, 5)
        sizer.Add(gridSiz, 0, wx.ALL, 5)
        gridSiz.Add(self.editBtn, 0, wx.ALL, 5)
        gridSiz.Add(self.rollbackBtn, 0, wx.ALL, 5)
        gridSiz.Add(self.applyBtn, 0, wx.ALL, 5)
        self.SetSizer(sizer)
        sizer.Fit(self)
        #### binding
        self.myGrid.Bind(gridlib.EVT_GRID_SELECT_CELL, self.onSingleSelect)
        self.Bind(wx.EVT_BUTTON, self.editCells, self.editBtn)
        self.Bind(wx.EVT_BUTTON, self.restroreLast, self.rollbackBtn)
        self.Bind(wx.EVT_BUTTON, self.makeChange, self.applyBtn)
    #-------------------------
    def setting(self):
        """
        Set properties and set the grid cells with values
        of the query.
        """
        lessons = School_Class().showInTable(self.IDclass, self.path_db)
        for n, item in enumerate(lessons):
            self.index += 1
            #------------IDlesson
            self.myGrid.SetCellValue(n , 0, str(item[0]))
            self.myGrid.SetCellAlignment(n, 0, wx.ALIGN_CENTRE, wx.ALIGN_CENTRE)
            #------------IDclass
            self.myGrid.SetCellValue(n , 1, str(item[1])) # IDclass
            self.myGrid.SetCellAlignment(n, 1, wx.ALIGN_CENTRE, wx.ALIGN_CENTRE)
            #------------attendances
            self.myGrid.SetCellValue(n , 2, item[2])
            if item[2] == 'All Present':
                self.myGrid.SetCellTextColour(n, 2, '#516c1a')
            elif item[2] == 'Student is absent':
                self.myGrid.SetCellTextColour(n, 2, wx.RED)
            elif item[2] == 'Teacher is absent':
                self.myGrid.SetCellTextColour(n, 2, '#e1cf37')
            self.myGrid.SetCellFont(n, 2, wx.Font(10, wx.DEFAULT, wx.NORMAL, wx.BOLD))
            self.myGrid.SetCellAlignment(n, 2, wx.ALIGN_CENTRE, wx.ALIGN_CENTRE)
            #-----------date
            self.myGrid.SetCellValue(n , 3, item[3])# date
            self.myGrid.SetCellBackgroundColour(n, 3, '#deffb4')
            #-----------
            if item[4] == 'NONE':
                self.myGrid.SetCellValue(n, 4, '')
            else:
                self.myGrid.SetCellValue(n , 4, item[4]) # reading

            if item[5] == 'NONE':
                self.myGrid.SetCellValue(n, 5, '')
            else:
                self.myGrid.SetCellValue(n , 5, item[5]) # setting

            if item[6] == 'NONE':
                self.myGrid.SetCellValue(n, 6, '')
            else:
                self.myGrid.SetCellValue(n , 6, item[6]) # rudiments

            if item[7] == 'NONE':
                self.myGrid.SetCellValue(n, 7, '')
            else:
                self.myGrid.SetCellValue(n , 7, item[7]) # coordination

            if item[8] == 'NONE':
                self.myGrid.SetCellValue(n, 8, '')
            else:
                self.myGrid.SetCellValue(n , 8, item[8]) # styles

            if item[9] == 'NONE':
                self.myGrid.SetCellValue(n, 9, '')
            else:
                self.myGrid.SetCellValue(n , 9, item[9]) # minusone

            if item[10] == 'NONE':
                self.myGrid.SetCellValue(n, 10, '')
            else:
                self.myGrid.SetCellValue(n , 10, item[10]) # other1

            if item[11] == 'NONE':
                self.myGrid.SetCellValue(n, 11, '')
            else:
                self.myGrid.SetCellValue(n , 11, item[11]) # other2

            self.myGrid.SetCellValue(n , 12, item[12]) # other3
            if item[12] == 'NONE':
                self.myGrid.SetCellValue(n, 12, '')

            if item[13] == 'NONE':
                self.myGrid.SetCellValue(n, 13, '')
            else:
                self.myGrid.SetCellValue(n , 13, item[13]) # votes

            if item[14] == 'NONE':
                self.myGrid.SetCellValue(n , 14, '')
            else:
                self.myGrid.SetCellValue(n , 14, item[14]) # notes
            self.myGrid.SetCellBackgroundColour(n, 14, '#fffa9a')

        self.myGrid.AutoSizeColumns(setAsMin=True) # resize all columns
        self.myGrid.AutoSizeRows(setAsMin=True) # resize all rows
    #--------------------------------------------------------------------#
    #--------------------------------EVENT-------------------------------#
    def editCells(self, event):
        """
        Make editable the columns in the row where the
        cell is selected only
        """
        row = self.currentlySelectedCell[0]
        col = self.currentlySelectedCell[1]
        val = self.myGrid.GetCellValue(row,col)

        dlg = wx.TextEntryDialog(self, 'Insert a new string:',
                                 "Change cell value",val,
                                 style=wx.TE_MULTILINE|wx.OK|wx.CANCEL
                                 )
        choices = ["All Present","Student is absent",
                   "Teacher is absent"
                   ]
        choiceDlg = wx.SingleChoiceDialog(self, "Change Attendance",
                                          "Choices",choices
                                          )
        if self.rowEdit is None or self.rowEdit == row:
            if col == 0 or col == 1:
                wx.MessageBox("This column can not be changed",
                'Change Not Allowed', wx.ICON_EXCLAMATION, self)
                return

            if self.IDlesson not in self.backUp:
                del self.backUp[:] # first clear list
                for n in range(15):
                    i = self.myGrid.GetCellValue(row, n)
                    self.backUp.append(i)

            if col == 2:
                if choiceDlg.ShowModal() == wx.ID_OK:
                    ret = choiceDlg.GetStringSelection()
                    dlg.Destroy()
                else:
                    return
            else:
                if dlg.ShowModal() == wx.ID_OK:
                    ret = dlg.GetValue()
                    dlg.Destroy()
                else:
                    return

            self.myGrid.SetCellValue(row , col, ret)

            del self.newsEdit[:] # first clear list
            for n in range(15):
                i = self.myGrid.GetCellValue(row, n)
                self.newsEdit.append(i)

            self.rowEdit = row
            self.rollbackBtn.Enable()
            self.applyBtn.Enable()
        else:
            msg = ("Before to edit cells in others rows, you must\n"
                   "push  'Apply Commit' button for render changes\n"
                   "into the edited columns selected in gray.\n\n"
                   "Instead, if you want to remove any change push\n"
                   "'Uncommit Last' button")
            self.myGrid.SelectRow(self.rowEdit, addToSelected=True)
            wx.MessageBox(msg, 'Change Not Allowed', wx.ICON_EXCLAMATION, self)
    #----------------------------------------------------------------------
    def restroreLast(self, event):
        """
        Retrieve last change and reset attributes. The data
        retrieving of previous setting it is restored.
        WARNING: this not restore after a apply-commit
        """
        for n, item in enumerate(self.backUp):
            self.myGrid.SetCellValue(self.rowEdit , n, self.backUp[n])
        self.editBtn.Disable()
        self.rollbackBtn.Disable()
        self.applyBtn.Disable()
        self.rowEdit = None
        del self.newsEdit[:]
        del self.backUp[:]
        self.IDlesson = None
    #----------------------------------------------------------------------
    def makeChange(self, event):
        """
        Allow to save changes in db (table Lesson)
        """
        for n, item in enumerate(self.newsEdit):# if empty str fill out with NONE str
            if item.strip() == '':
                self.newsEdit[n] = 'NONE'

        change = School_Class().change_lesson_items(self.newsEdit, self.path_db)

        if change[0]:
            wx.MessageBox(change[1], 'Error', wx.ICON_ERROR, self)
            return

        self.editBtn.Disable()
        self.rollbackBtn.Disable()
        self.applyBtn.Disable()
        self.rowEdit = None
        del self.newsEdit[:]
        del self.backUp[:]
        self.IDlesson = None

        self.index = 0
        self.setting()
        wx.MessageBox("Successfull storing !", "Success", wx.OK, self)
        #----------------------------------------------------------------------
    def onSingleSelect(self, event):
        """
        Get the selection of a single cell by clicking or
        moving the selection with the arrow keys
        """
        self.currentlySelectedCell = (event.GetRow(),
                                    event.GetCol())
        self.IDlesson = self.myGrid.GetCellValue(self.currentlySelectedCell[0],
                                                 0)
        if event.GetRow() >= self.index:
            self.editBtn.Disable()
            return
        else:
            self.editBtn.Enable()
        event.Skip()
    #----------------------------------------------------------------------


import unittest
from app import create_app

from fractions import Fraction
from flask_pymongo import PyMongo
from sum import sum
from mockupdb import go, MockupDB, OpQuery

class TestOther(unittest.TestCase):
    def test_list_int(self):
        """
        Test that it can sum a list of integers
        """
        data = [1, 2, 3]
        result = sum(data)
        self.assertEqual(result,6)

    def test_list_fraction(self):
        """
        Test sums fractions
        """
        data = [Fraction(1,4), Fraction(1,4), Fraction(2,5)]
        result = sum(data)
        self.assertEqual(result,Fraction(9,10))

    def test_auto_pass(self):
        pass

    def test_code_error(self):
        with self.assertRaises(NameError):
            some_method()

class TestDb(unittest.TestCase):
    def setUp(self):
        self.server = MockupDB(auto_ismaster={"maxWireVersion": 3})
        self.server.run()
        app = create_app("config_default.TestConfig",self.server.uri+"/test")
        self.app = app.test_client()

    def test_home_status(self):
        result = self.app.get('/')

        self.assertEqual(result.status_code,200)
    def test_home_data(self):
        result = self.app.get('/')
        attrs = vars(result)

        self.assertGreater(len(result.data),0,"Page Length Should not be 0")

    def test_api_home(self):

        future = go(self.app.get,"/api/")
        request = self.server.receives(OpQuery)
        request.reply({"test":"t"});
        http_response = future()
        print(http_response.get_data(as_text=True))
        self.assertIn(b"api",http_response.get_data())

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


# part of the ASTA project to align wav2vec and cgn with nw
# further analysis done here.

import glob
import random
import os
from utils import needleman_wunch as nw
# from text.models import Textgrid

cgn_wav2vec_dir = '/vol/tensusers3/mbentum/cgn_wav2vec/'
cgn_align = '/vol/tensusers3/mbentum/cgn_wav2vec_align/'

def table_filenames():
    fn = glob.glob(cgn_wav2vec_dir + '*.table')
    return fn

def text_filename():
    fn = glob.glob(cgn_wav2vec_dir + '*.txt')
    return fn

def load_table(filename):
    with open(filename) as fin:
        t = fin.read()
    temp= [x.split('\t') for x in t.split('\n') if x]
    table = []
    for grapheme, start, end in temp:
        table.append([grapheme,float(start), float(end)])
    return table

def load_text(filename):
    with open(filename) as fin:
        t = fin.read()
    return t

def table_filename_to_cgn_id(f):
    cgn_id = f.split('/')[-1].split('.')[0]
    return cgn_id

def make_alignments():
    fn = table_filenames()
    random.shuffle(fn)
    for f in fn:
        cgn_id = table_filename_to_cgn_id(f)
        align_filename = cgn_align + cgn_id
        if os.path.isfile(align_filename):
            print('skiping',cgn_id)
            continue
        print('handling',cgn_id)
        Align(cgn_id)

class Align:
    def __init__(self,cgn_id):
        self.cgn_id = cgn_id
        self.textgrid = Textgrid.objects.get(cgn_id = cgn_id)
        self.awd_words = self.textgrid.word_set.all()
        self.awd_text = ' '.join([w.awd_word for w in self.awd_words])
        self._set_wav2vec_table_and_text()
        self._set_align()

    def _set_wav2vec_table_and_text(self):
        self.wav2vec_base_filename = cgn_wav2vec_dir + self.textgrid.cgn_id
        self.wav2vec_table=load_table(self.wav2vec_base_filename+'.table')
        self.wav2vec_text=load_text(self.wav2vec_base_filename+'.txt')

    def _set_align(self):
        self.align_filename = cgn_align + self.cgn_id
        if os.path.isfile(self.align_filename):
            with open(self.align_filename) as fin:
                self.align = fin.read()
        else:
            self.align = nw.nw(self.awd_text, self.wav2vec_text)
            with open(self.align_filename, 'w') as fout:
                fout.write(self.align)


from classes.weapons.weapon import Weapon
from tools.math_ops import normalize_victor
import time
from classes.creatures.bullet import Bullet

class TihiyPistolet(Weapon):
    def __init__(self, hero, name='Тихий пистолет', damage=6, recharge_time=0.5, max_bullets=150):
        super().__init__(hero, name, damage, recharge_time, max_bullets, description='Очень тихий но слабый пистолет')

class AutomatBobby(Weapon):
    def __init__(self, hero, name='Автомат Бобби', damage=4, recharge_time=0.1, max_bullets=300):
        super().__init__(hero, name, damage, recharge_time, max_bullets)

class Dvoostvolka(Weapon):
    def __init__(self, hero, name='Двустволка', damage=5, distance=5, recharge_time=1, max_bullets=70):
        super().__init__(hero, name, damage, recharge_time, max_bullets)

    def shoot(self, x, y, bullets):
        if self.bullets > 0:
            if time.time() - self.last_shoot_time >= self.recharge_time:
                vector = [x - self.hero.x, y - self.hero.y]
                perp1 = normalize_victor([-vector[1], vector[0]], 5)
                perp2 = normalize_victor([vector[1], -vector[0]], 5)

                bullets.append(Bullet.spawn(self.hero.x + perp1[0], self.hero.y + perp1[1], vector, 7, damage=self.damage))
                bullets.append(Bullet.spawn(self.hero.x + perp2[0], self.hero.y + perp2[1], vector, 7, damage=self.damage))
                self.last_shoot_time = time.time()
                self.bullets -= 2

store = {
    'weapons': [
        {
            'weapon': TihiyPistolet(None),
            'price': 120
        },
        {
            'weapon': AutomatBobby(None),
            'price': 250
        },
        {
            'weapon': Dvoostvolka(None),
            'price': 200
        }
    ]
}


import collections
import statistics as st

def load():
    with open("inputs/10.txt") as f:
        return tuple(tuple(c.strip()) for c in f.readlines())

def points_a(c):
    return {
        ")": 3,
        "]": 57,
        "}": 1197,
        ">": 25137,
    }[c]

def points_b(c):
    return {
        ")": 1,
        "]": 2,
        "}": 3,
        ">": 4,
    }[c]

def opening():
    return tuple(pairs().keys())

def closing():
    return tuple(pairs().values())

def pairs():
    return dict(
        (
            ("(", ")"),
            ("[", "]"),
            ("{", "}"),
            ("<", ">"),
        )
    )

def balanced(row):
    stack = collections.deque()
    illegal = []
    for op in row:
        if op in opening():
            stack.append(op)
        else:
            if stack and op != pairs()[stack[-1]]:
                illegal.append(op)
            if stack:
                stack.pop()
    return illegal

def close(row):
    row = list(row)
    while True:
        n = None
        for idx in range(len(row) - 1):
            if row[idx] in opening() and pairs()[row[idx]] == row[idx + 1]:
                n = idx
                break
        if n is not None:
            del row[idx + 1]
            del row[idx]
        if n is None:
            return "".join(pairs()[r] for r in reversed(row))

def b():
    for row in load():
        if not balanced(row):
            acc = 0
            for char in close(row):
                acc *= 5
                acc += points_b(char)
            yield acc

print("a:", sum(sum(points_a(i) for i in balanced(row)) for row in load()))
print("b:", st.median(b()))


# title: database updater for Jokic triple double tracker and predictor

# importing some helpful dataframe and sql libraries
import pandas as pd
import duckdb as db
# importing the nba_api
from nba_api.stats.static import players, teams
from nba_api.stats.endpoints import playercareerstats, playergamelog, leaguegamefinder

# setting up in-memory duckdb connection
conn = db.connect('./data/triple-double-tracker.db')

# Get Jokic player ID
jokic_id = players.find_players_by_last_name('Jokic')[0]['id']

# Get Jokic seasons
seasons_df = playercareerstats.PlayerCareerStats(
    player_id=jokic_id
).get_data_frames()[0]
seasons_list = seasons_df['SEASON_ID'].tolist()

# Jokic stats
stats_list = [playergamelog.PlayerGameLog(player_id=jokic_id, season=x).get_data_frames()[0] for x in seasons_list]
jokic_stats_df = pd.concat(stats_list)

# Update the database table
conn.execute(
    '''
    CREATE OR REPLACE TABLE main
    AS SELECT
        RIGHT(SEASON_ID, 4) AS Season,
        Player_ID AS PlayerID,
        Game_ID AS GameID,
        (
            CASE
                WHEN
                    CAST(SPLIT_PART(strftime(strptime(GAME_DATE, '%b %d, %Y'), '%m/%d'), '/', 1) AS int) < 10
                THEN
                    CAST(SPLIT_PART(strftime(strptime(GAME_DATE, '%b %d, %Y'), '%m/%d'), '/', 1) AS int) + 12
                ELSE
                    CAST(SPLIT_PART(strftime(strptime(GAME_DATE, '%b %d, %Y'), '%m/%d'), '/', 1) AS int)
            END
        ) AS GameMonth,
        (
            SPLIT_PART(strftime(strptime(GAME_DATE, '%b %d, %Y'), '%m/%d'), '/', 2)
        ) AS GameDay,
        (
            CASE
                WHEN MATCHUP LIKE '%@%' THEN 0
                WHEN MATCHUP LIKE '%vs.%' THEN 1
            END
        ) AS Location,
        (
            RIGHT(MATCHUP, 3)
        ) AS Opponent,
        WL,
        MIN AS Min,
        PTS AS Pts,
        AST AS Ast,
        REB AS Reb,
        (
            CASE
                WHEN PTS >= 10 AND AST >= 10 AND REB >= 10 THEN 1
                ELSE 0
            END
        ) AS TripleDouble

    FROM
        jokic_stats_df
    '''
)

# close the connection
conn.close()

# Print
print("Database updated")


import os
from typing import List
from sqlalchemy.orm import Session
from fastapi import(
    Depends,
    Response,
    status,
    APIRouter,
    File,
    UploadFile
)
from fastapi.responses import JSONResponse

from app.core.database import get_db

from app.api.deps import(
    allow_create_resource
)

from app.core.torrent import(
    torrentController,
    get_torrent_instance
)

router = APIRouter()

@router.post(
    '/upload',
    status_code=status.HTTP_200_OK,
    #dependencies=[Depends(allow_create_resource)]
)
async def create_upload_file(
    file: UploadFile,
    server: torrentController = Depends(get_torrent_instance)
):
    contents = await file.read()
    path_file = os.path.join(os.getcwd(), 'files', file.filename)
    if os.path.isfile(path_file) == False:
        with open(path_file, 'wb') as f:
            f.write(contents)
    data_upload = server.upload_torrent(path_file)
    return data_upload


#author:vamshi

import os
import sys
import numpy as np
import cv2
import re
import glob
from tqdm import tqdm
import pickle

#file to read

TRAIN_DIR = "../datasets/mammo_cancer/train/"
VAL_DIR  = "../data_mammo/val/"

imsize = 256

def read_imgs(data_dir,label="cancer",d="LEFT", mode="MLO"):
	'''
		returns all images in the folder with dir, mode of photo

	'''
	data = []
	if(mode==None and d!=None):
		file = "*"+d+"_"+"*"+".png"
	elif(mode==None and d==None):
		file = "*.png"
	elif(d==None and mode!=None):
		file = "*"+"_"+mode+".png"
	else:
		file = "*"+d+"_"+mode+".png"

	for file in tqdm(glob.glob(TRAIN_DIR+label+"/"+file)):
		img = cv2.imread(file,0)
		img = cv2.resize(img,(imsize,imsize),interpolation=cv2.INTER_CUBIC)

		#print(img.shape)
		#cv2.imshow('img',img)
		#cv2.waitKey(0)
		img = img.astype(int)
		img = (img.astype(np.float32)/255.0)*2.0 - 1.0
		data.append(img)
	return data

def remove_text(img):
	'''
		removes text present in the images
	'''
	#edge = cv2.Canny(img,10,200)
	#blur = cv2.GaussianBlur(img,(5,5),0)
	#ret, otsu = cv2.threshold(blur,0,255,cv2.THRESH_BINARY+cv2.THRESH_OTSU)

	#cv2.imshow('img',edge)
	#cv2.waitKey(0)
	#print(img)
	return img

cancer = read_imgs(TRAIN_DIR,label="cancer",d=None,mode=None)
print(len(cancer))
normal = read_imgs(TRAIN_DIR,label="normal",d=None,mode=None)
print(len(normal))

save_file = "../datasets/mammo_cancer/dataset_mammo_train_"+str(imsize)+".pickle"
with open(save_file,"wb") as f:
	data  = {'cancer':cancer,
		  'normal':normal}
	pickle.dump(data,f)

print(len(data))
#read_imgs(TRAIN_DIR,d="LEFT",mode="MLO")
#read_imgs(TRAIN_DIR,d="RIGHT",mode="CC")
#read_imgs(TRAIN_DIR,d="LEFT",mode="CC")


from django.shortcuts import render, redirect
from django.urls import reverse
from django.forms import ModelForm

from plus.utils.filters import FilterList
from plus.utils.pager import Pager
from django.db.models import ForeignKey, ManyToManyField
from django.http.request import QueryDict
from django.utils.safestring import mark_safe

import copy

class ChangeList():
    def __init__(self, pma, result_list):
        '''
        PlusModelAdmin对象
        :param pma:
        '''
        self.pma = pma
        self.site = pma.site
        self.request = pma.request

        self.is_edit = pma.is_edit
        self.show_checkbox_col = pma.show_checkbox_col
        self.list_display = pma.list_display
        self.filter_list = pma.filter_list

        self.model_class = pma.model_class
        self.changelist_url = pma.changelist_url
        self.action_list = pma.action_list

        all_count = result_list.count()
        query_params = copy.deepcopy(self.request.GET)
        query_params._mutable = True

        self.pager = Pager(all_counts=all_count, current_page=self.request.GET.get("page"),
                           base_url=self.changelist_url,
                           params_dict=query_params)
        self.result_list = result_list[self.pager.start_index:self.pager.stop_index]

    def option_filter_list(self):
        '''
        组合搜索
        :return:
        '''
        for option in self.filter_list:
            if option.is_func:  # 接收函数的返回值
                obj_list = option.field_or_func(self, option, self.request)
            else:
                # 获取字段（django.db.models下的字段类型）
                field = self.model_class._meta.get_field(option.field_or_func)
                if isinstance(field, ForeignKey):  # 如果是外键字段
                    # rel.model ：当前字段相关联的表
                    obj_list = FilterList(option, field.rel.model.objects.all(), self.request)
                elif isinstance(field, ManyToManyField):
                    obj_list = FilterList(option, field.rel.model.objects.all(), self.request)
                else:  # 当前model内的正常字段
                    obj_list = FilterList(option, field.model.objects.all(), self.request)

            yield obj_list

    def add_btn(self):
        """
        列表页面定制新建数据按钮
        :return:
        """
        pass
        add_url = reverse(
            '%s:%s_%s_add' % (
                self.site.namespace, self.model_class._meta.app_label, self.model_class._meta.model_name))

        _change = QueryDict(mutable=True)
        _change['_params'] = self.request.GET.urlencode()

        tpl = " 新建数据".format(
            add_url,
            _change.urlencode())
        return mark_safe(tpl)

class PlusModelAdmin(object):
    # 行是否可点击（行编辑功能）
    is_edit = False

    # 是否有行勾选按钮
    show_checkbox_col = True

    # 显示哪些字段
    list_display = "__str__"

    # 自定义的批量处理事件
    action_list = []

    def action_delete(self, request):
        pk_list = request.POST.getlist("pk")
        self.model_class.objects.filter(pk__in=pk_list).delete()
        return True

    # action_delete也是一个对象，可以自定义属性
    action_delete.title = "批量删除"

    action_list = [action_delete, ]

    # 过滤的组合条件
    filter_list = []

    # 添加或修改数据时的ModelForm对象（可以定义操作的字段，出错时的提示等）
    model_form = None

    def __init__(self, model_class, site):
        self.model_class = model_class
        self.site = site

        self.app_label = self.model_class._meta.app_label
        self.model_name = self.model_class._meta.model_name

    @property
    def urls(self):
        from django.conf.urls import url, include

        info = (self.model_class._meta.app_label, self.model_class._meta.model_name)

        # 最基本的增删改查
        urlpatterns = [
            url(r'^$', self.changelist_view, name='%s_%s_changelist' % info),
            url(r'^add/$', self.add_view, name='%s_%s_add' % info),
            url(r'^(.+)/delete/$', self.delete_view, name='%s_%s_delete' % info),
            url(r'^(.+)/change/$', self.change_view, name='%s_%s_change' % info),
        ]
        return urlpatterns

    def get_url_params(self, request):
        '''
        获取url的参数
        :param request:
        :return:
        '''

        # request.GET其类型就是一个QueryDict，所以有一个urlencode方法，获取所有的参数
        from django.http.request import QueryDict
        querydict = QueryDict(mutable=True)

        # 如果有参数，在添加完数据之后，需要跳转回原来的页面，所以需要保存之前的这些参数（name=yangzai&page=10）
        if request.GET:
            # 重新自定一个参数{"_params":'name=yangzai&page=10'}
            # 当跳转的时候，去除_params的值，和url拼接
            querydict["_params"] = request.GET.urlencode()  # name=yangzai&page=10
        else:
            querydict["_params"] = ""

        return querydict.urlencode()

    @property
    def changelist_param_url(self):
        '''
        获取数据列表页的url（带参数）
        :return:
        '''
        base_url = reverse(
            "%s:%s_%s_changelist" % (
                self.site.namespace, self.app_label, self.model_name))
        return "%s?%s" % (base_url, self.request.GET.urlencode())

    @property
    def changelist_url(self):
        '''
        获取数据列表页的url
        :return:
        '''
        return reverse(
            "%s:%s_%s_changelist" % (
                self.site.namespace, self.app_label, self.model_name))

    def get_change_list_condition(self, query_params):
        '''
        过滤不合法的查询字段
        :param query_params:
        :return:
        '''

        field_list = [item.name for item in self.model_class._meta._get_fields()]
        condition = {}
        for k in query_params:
            if k not in field_list:
                # raise Exception('条件查询字段%s不合法，合法字段为：%s' % (k, ",".join(field_list)))
                continue
            condition[k + "__in"] = query_params.getlist(k)
        return condition

    def get_model_form(self):
        '''
        生成一个默认的ModelForm
        :return:
        '''
        if self.model_form: return self.model_form

        # ModelForm可以自动生成标签
        class MyModelForm(ModelForm):
            class Meta:
                model = self.model_class
                fields = "__all__"

        return MyModelForm

    def changelist_view(self, request):
        '''
        显示数据列表
        :param request:
        :return:
        '''

        self.request = request
        result_list = self.model_class.objects.filter(**self.get_change_list_condition(request.GET))

        if request.method == "POST":
            action_event = request.POST.get("action")

            if hasattr(self, action_event):
                # 执行函数
                self_action = getattr(self, action_event)
                if self_action(request):  # 跳转原地址
                    return redirect(self.changelist_param_url)
                else:  # 跳转到数据列表首页
                    return redirect(self.changelist_url)
            else:
                return redirect(self.changelist_param_url)

        change_list = ChangeList(self, result_list)

        context = {
            'chl': change_list,
        }
        return render(request, "plus/change_list.html", context)

    def add_view(self, request):
        '''
        增加数据项
        :param request:
        :return:
        '''
        self.request = request
        if request.method == "GET":
            model_form = self.get_model_form()()
            from  django.forms.boundfield import BoundField
            return render(request, "plus/add.html", {"form": model_form, "modeladmin_obj": self})
        else:
            obj = self.get_model_form()(data=request.POST, files=request.FILES)
            _params = request.GET.get("_params")
            if obj.is_valid():
                popup_obj = obj.save()
                changelist_url = reverse(
                    "{0}:{1}_{2}_changelist".format(self.site.namespace, self.app_label, self.model_name))
                changelist_url = "%s?%s" % (changelist_url, _params)

                popup_id = request.GET.get("_popup_id")
                # 这个的话是表示这个一个新弹出的popup窗口的提交请求
                if popup_id:
                    return render(request, "plus/form_add_popup.html",
                                  {"pk": popup_obj.pk, "text": str(popup_obj), "popup_id": popup_id})
                else:
                    # 正常的请求，跳回页面
                    return redirect(changelist_url)
            else:

                return render(request, "plus/add.html", {"form": obj, "modeladmin_obj": self})

    def delete_view(self, request, pk):
        '''
        删除数据项
        :param request:
        :param pk: 删除的主键
        :return:
        '''
        obj = self.model_class.objects.filter(pk=pk).delete()
        if not obj:
            return HttpResponse("出错了")

        _params = request.GET.get("_params")
        changelist_url = reverse(
            "{0}:{1}_{2}_changelist".format(self.site.namespace, self.app_label, self.model_name))
        changelist_url = "%s?%s" % (changelist_url, _params)

        # 跳回页面
        return redirect(changelist_url)

    def change_view(self, request, pk):
        '''
        修改数据项
        :param request:
        :param pk: 删除的主键
        :return:
        '''
        obj = self.model_class.objects.filter(pk=pk).first()
        if not obj:
            return HttpResponse("出错了")

        if request.method == "GET":
            model_form = self.get_model_form()(instance=obj)
            return render(request, "plus/add.html", {"form": model_form, "modeladmin_obj": self})
        else:
            # 这里要加instance，才能去处理如果库里有就更新
            obj = self.get_model_form()(data=request.POST, files=request.FILES, instance=obj)
            _params = request.GET.get("_params")
            if obj.is_valid():
                obj.save()
                changelist_url = reverse(
                    "{0}:{1}_{2}_changelist".format(self.site.namespace, self.app_label, self.model_name))
                changelist_url = "%s?%s" % (changelist_url, _params)
                return redirect(changelist_url)
            else:
                return render(request, "plus/add.html", {"form": obj, "modeladmin_obj": self})

from django.shortcuts import HttpResponse

class PlusSite(object):
    def __init__(self):
        self._registry = {}
        self.namespace = "plus"
        self.app_name = "plus"

    def register(self, model_class, model_admin=PlusModelAdmin):
        self._registry[model_class] = model_admin(model_class, self)

    def login(self, request):
        return HttpResponse("login")

    def get_urls(self):
        from django.conf.urls import url, include

        ret = [
            url(r"^login/", self.login, name="login")
        ]

        for model_cls, model_am in self._registry.items():
            app_label = model_cls._meta.app_label
            model_name = model_cls._meta.model_name
            # 做路由分发include(model_am.urls)
            ret.append(url(r"^%s/%s/" % (app_label, model_name), include(model_am.urls)))
        return ret

    @property
    def urls(self):
        return self.get_urls(), self.app_name, self.namespace

# 始终只有一个site对象
site = PlusSite()

{'url': 'django.conf.urls.url', 'include': 'django.conf.urls.include'}


import torch
import torch.nn as nn
import torch.nn.functional as F
import torch.optim as optim
from torch.autograd import Variable
from prepare import *
import tqdm
from max_margin_loss import max_margin_loss
from evaluation import Evaluation
from lstm import *

class QA_CNN(nn.Module):

    def __init__(self, num_hidden, emb_size, embeddings, dropout_prob):
        super(QA_CNN, self).__init__()
        self.num_hidden = num_hidden
        self.emb_size = emb_size
        self.embeddings = embeddings
        self.embedding_layer = nn.Embedding(1, self.emb_size)
        self.embedding_layer.weight.data = torch.from_numpy(self.embeddings).float()
        self.dropout = nn.Dropout(dropout_prob)

        self.conv1 = nn.Conv1d(emb_size, num_hidden, 3, padding=1)
        # self.conv2 = nn.Conv1d(6, 16, 5)
        # an affine operation: y = Wx + b

    def forward(self, sent, mask):
        x = self.embedding_layer(sent.long())
        # batch_size, length = sent.size()
        x = torch.transpose(x, 2, 1)
        x = F.relu(self.dropout(self.conv1(x)))
        x = torch.transpose(x, 2, 1)
        masked = torch.mul(x, mask.unsqueeze(2).expand_as(x))
        sum_out = masked.sum(dim=1)
        count = mask.sum(dim=1).unsqueeze(1).expand_as(sum_out)
        x =  torch.div(sum_out, count)
        return x

    def num_flat_features(self, x):
        size = x.size()[1:]  # all dimensions except the batch dimension
        num_features = 1
        for s in size:
            num_features *= s
        return num_features

def main():
    batch_size = 32
    dropout_prob = 0.1
    learning_rate = 0.001
    margin = 0.2
    momentum = 0
    num_epoches = 3
    num_hidden = 667
    emb_size = 200

    params = {'num_epoches' : num_epoches, 'momentum' : momentum,
                'margin' : margin, 'learning_rate' : learning_rate,
                'batch_size' : batch_size}

    train_data = UbuntuSequentialDataSet('ubuntu_data/train_random.txt')
    dev_data = UbuntuEvaluationDataSet('ubuntu_data/dev.txt')
    test_data = UbuntuEvaluationDataSet('ubuntu_data/test.txt')

    model = QA_CNN(num_hidden, emb_size, embeddings, dropout_prob)

    print('Started Training...\n')

    is_training = True

    run_model(train_data, dev_data, model, is_training, params)

    print('\nFinished Training!\n')

    print('Started Evaluating on Dev Set...\n')

    is_training = False

    params['num_epoches'] = 1

    run_model(dev_data, None, model, is_training, params)

    print('\nFinished Evaluating on Dev Set!\n')

    print('Started Evaluating on Test Set...\n')

    is_training = False

    run_model(test_data, None, model, is_training, params)

    print('\nFinished Evaluating on Test Set!\n')

if __name__ == '__main__':
    main()


#!/usr/bin/env python
# coding: utf-8

# In[109]:

import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
import random
import os
from scipy import stats
import pickle
import xml.etree.ElementTree as ET
import json

# # Update these 2 variables

# In[93]:

# ID of mouse (example: G25)
mouse_id = "test_000"

# cellfinder_output_path = 'path/to/root/directory/of/cellfinder/output/data/'
cellfinder_output_path = "/Users/grant/Desktop/mock_df/cellfinder_output/"

# ### Create new folder in your cellfinder output folder
#

# In[105]:

# Create new folder in your cellfinder output folder
new_folder_path = cellfinder_output_path + str(mouse_id) + "_Completed_Analysis" # create the path for the new folder

if not os.path.exists(new_folder_path):
    os.makedirs(new_folder_path)
    print('folder has been created.')
    print(f'{new_folder_path}')
else:
    print('path already exists, skipping...')
    print(f'{new_folder_path}')

# ### Read in tdTomato & GFP output data from cellfinder

# In[106]:

# import cellfinder summary csv, containing cell counts and more
gfp_df = pd.read_csv(cellfinder_output_path + 'analysis/' + 'gfp_summary.csv')
tdTomato_df = pd.read_csv(cellfinder_output_path + 'analysis/' + 'tdTomato_summary.csv')

# output path for created csv
output_path_csv = new_folder_path + '/' + mouse_id + '_labled_cells.csv'

gfp_df

# # GFP Data

# In[108]:

# make list of each brain region with labeled cells
all_gfp_brain_regions = gfp_df['structure_name'].to_list()
print("All Brain Regions: " + str(len(all_gfp_brain_regions)))

# make a list of total cell count for each brain region labeled with GFP
all_gfp_brain_regions_cell_count = gfp_df['total_cells'].to_list()
print("total cells: " + str(sum(all_gfp_brain_regions_cell_count)))

# make dict of brain_regions & cell_count
all_gfp_dictionary = dict(zip(all_gfp_brain_regions, all_gfp_brain_regions_cell_count))
all_gfp_df = pd.DataFrame.from_dict(all_gfp_dictionary,orient='index')

# In[97]:

# Find all brain regions with labeled gfp cells, make gfp_df
gfp_cells_df = gfp_df[gfp_df['total_cells'] >= 1]

# make list of each brain region with labeled cells
gfp_brain_regions = gfp_cells_df['structure_name'].to_list()
gfp_brain_regions_sum = len(gfp_brain_regions)
print("GFP Brain Regions With labeled Cells: " + str(gfp_brain_regions_sum))

# make a list of total cell count for each brain region labeled with GFP
gfp_brain_regions_cell_count = gfp_cells_df['total_cells'].to_list()
gfp_labled_cells_sum = sum(gfp_brain_regions_cell_count)
print("total labeled GFP cells: " + str(gfp_labled_cells_sum ))

# make dict of brain_regions & cell_count
gfp_dictionary = dict(zip(gfp_brain_regions, gfp_brain_regions_cell_count))
gfp_df_01 = pd.DataFrame.from_dict(gfp_dictionary,orient='index')

# In[120]:

# File path to the desktop
file_path =  new_folder_path + '/gfp_brainregions_list.json'
print(file_path)

# Open a file
with open(file_path, 'w') as f:
    # Save the list to the file
    json.dump(gfp_brain_regions, f)

# In[121]:

# File path to the desktop
count_file_path =  new_folder_path + '/gfp_brainregions_count.json'
print(count_file_path)

# Open a file
with open(count_file_path, 'w') as f:
    # Save the list to the file
    json.dump(gfp_brain_regions_cell_count, f)

# # tdTomato Data

# In[98]:

# make list of each brain region with labeled cells
all_tdTomato_brain_regions = tdTomato_df['structure_name'].to_list()
print("All Brain Regions: " + str(len(all_tdTomato_brain_regions)))

# make a list of total cell count for each brain region labeled with GFP
all_tdTomato_brain_regions_cell_count = tdTomato_df['total_cells'].to_list()
print("total cells: " + str(sum(all_tdTomato_brain_regions_cell_count)))

# make dict of brain_regions & cell_count
all_tdTomato_dictionary = dict(zip(all_tdTomato_brain_regions, all_tdTomato_brain_regions_cell_count))
all_tdTomato_df = pd.DataFrame.from_dict(all_tdTomato_dictionary,orient='index')

# In[99]:

# create a dictonary of only the
# Find all brain regions with labeled gfp cells, make gfp_df
tdTomato_cells_df = tdTomato_df[tdTomato_df['total_cells'] >= 1]

# make list of each brain region with labeled cells
tdTomato_brain_regions = tdTomato_cells_df['structure_name'].to_list()
tdTomato_brain_regions_sum = len(tdTomato_brain_regions)
print("tdTomato Brain Regions With labeled Cells: " + str(tdTomato_brain_regions_sum))

# make a list of total cell count for each brain region labeled with GFP
tdTomato_brain_regions_cell_count = tdTomato_cells_df['total_cells'].to_list()
tdTomato_labled_cells_sum = sum(tdTomato_brain_regions_cell_count)
print("total labeled tdTomato cells: " + str(tdTomato_labled_cells_sum))

# make dict of brain_regions & cell_count
tdTomato_dictionary = dict(zip(tdTomato_brain_regions, tdTomato_brain_regions_cell_count))
tdTomato_df_01 = pd.DataFrame.from_dict(tdTomato_dictionary,orient='index')

# ## Create csv file with summary of gfp and tdTomato Cellcount and Brain Regions

# In[100]:

data = {'total whole-brain cell count': [gfp_labled_cells_sum, tdTomato_labled_cells_sum],
        'total brain regions': [gfp_brain_regions_sum,tdTomato_brain_regions_sum],
        'brain regions list': [gfp_brain_regions,all_tdTomato_brain_regions]}

summary_df = pd.DataFrame(data)
summary_df.rename(index={0: 'GFP'}, inplace=True)
summary_df.rename(index={1: 'tdTomato'}, inplace=True)

# Save out summary df
summary_df.to_csv(new_folder_path + '/' + mouse_id + '_summary_df.csv')

summary_df

# In[101]:

# making a df with percent of gfp cells labled compared to tdTomato
percent_labled = []
i = 0
for count in all_tdTomato_brain_regions_cell_count:
    percent_labled.append(all_gfp_brain_regions_cell_count[i] / count *100)
    i += 1

# ## df for percentage of labled gfp cells vs tdTomato cells

# In[102]:

# create df with gfp and tdTomato cell counts, and percent labled
all_gfp_df['tdTomato cell count'] = all_tdTomato_brain_regions_cell_count
all_gfp_df['percent labled gfp/tdTomato'] = percent_labled

# Add the header 'New Column Name' to column at index 0
all_gfp_df.rename(columns={gfp_df_01.columns[0]: 'gfp cell count'}, inplace=True)

# In[103]:

# Find all brain regions with labeled gfp cells, make gfp_df
labled_cells_df = all_gfp_df[all_gfp_df['gfp cell count'] >= 1]
labled_cells_df

labled_cells_df.to_csv(output_path_csv)

# In[117]:

labled_cells_df[0:20]

# # There are several ways to statistically compare the values at each index location of two lists in Python. Here are a few options:
#
# ### 1. Using the scipy library's stats.ttest_ind() function, you can perform a t-test to compare the means of the two lists at each index location. For example:

# In[614]:

t, p = stats.ttest_ind(gfp_brain_regions_cell_count, mock_tdTomato_cellcount)
print("t-statistic: ", t)
print("p-value: ", p)

# ### 2. Using the numpy library's corrcoef() function, you can calculate the correlation coefficient between the two lists at each index location. For example:

# In[615]:

corr = np.corrcoef(gfp_brain_regions_cell_count, mock_tdTomato_cellcount)[0, 1]
print("correlation coefficient: ", corr)

# ### 3.  Using the pandas library, you can create a dataframe from the two lists and use the corr() function to calculate the correlation between the two lists:

# In[616]:

df = pd.DataFrame({'list1': gfp_brain_regions_cell_count, 'list2': mock_tdTomato_cellcount})
corr = df['list1'].corr(df['list2'])
print("correlation coefficient: ", corr)

# # load voxel locations of cells

# In[81]:

data = np.load("/Users/grant/Desktop/mock_df/points.npy")

# In[84]:

print(len(data))

# # Load cell_classification data

# In[87]:

tree = ET.parse("/Users/grant/Desktop/mock_df/cell_classification.xml")
root = tree.getroot()

# In[91]:

# Iterate over child elements
for child in root:
    print(child.tag, child.attrib)

# # load all point

# In[94]:

all_points = pd.read_csv("/Users/grant/Desktop/mock_df/all_points.csv")

# In[95]:

all_points

# # load volumes

# In[97]:

volumes = pd.read_csv("/Users/grant/Desktop/mock_df/volumes.csv")

# In[98]:

volumes

# In[ ]:


from selenium import webdriver
from selenium.webdriver.common.by import By
from selenium.webdriver.chrome.service import Service
import time

s = Service(r'D:\Project\RemoteWork\selenium-test\Browsers\chromedriver.exe')
driver = webdriver.Chrome(service=s)

driver.maximize_window()
driver.get('https://lambdatest.github.io/sample-todo-app/')
time.sleep(5)

# click box
driver.find_element(by=By.NAME, value='li1').click()
driver.find_element(by=By.NAME, value='li2').click()
time.sleep(10)

# create to do
driver.find_element(by=By.ID, value='sampletodotext').send_keys('ketik sendiri')
time.sleep(5)

# click to do
driver.find_element(by=By.ID, value='addbutton').click()
time.sleep(10)

driver.close()

# agustyast@gmail.com
# Scrap131
# adidas yeez


from Bank import Bank
from Agent import Agent
from Strategies import Greedy, Cooperative, EmotionalStrategy
import matplotlib.pyplot as plt

class PublicGoods:
    def __init__(self):
        self.bank = Bank(1.5)
        self.iterations = 100
        self.agents = []

    def run(self):
        for i in range(self.iterations):
            self.bank.pay_in(self.agents)
            self.bank.multiply_deposit()
            self.bank.pay_out(self.agents)
            # for agent in self.agents:
            #     agent.get_inspired(self.agents)

        fig, ax = plt.subplots()
        ax.plot(self.agents[0].balances, alpha=0.7, label='smart')
        ax.plot(self.agents[1].balances, alpha=0.6, label='emotional')
        ax.plot(self.agents[20].balances, alpha=0.5, label='greedy')
        ax.legend(loc="upper left")
        plt.show()

    def addEmotionalAgent(self, anger=1, gratitude=1, admiration=1, name=""):
        strategy = EmotionalStrategy(anger, gratitude, admiration)
        self.agents.append(Agent(name, strategy))

    def addLearningAgent(self, name=""):
        strategy = EmotionalStrategy(is_smart=True)
        self.agents.append(Agent(name, strategy))

    def addGreedyAgent(self, name=""):
        strategy = Greedy()
        self.agents.append(Agent(name, strategy))

    def addCooperativeAgent(self, name=""):
        strategy = Cooperative()
        self.agents.append(Agent(name, strategy))

    def reset(self):
        for agent in self.agents:
            agent.reset()


from selenium import webdriver
from selenium.webdriver.chrome.options import Options
from selenium.webdriver.chrome.service import Service
from webdriver_manager.chrome import ChromeDriverManager
from opensearchpy import OpenSearch

from django.conf import settings
from django.contrib.staticfiles.testing import StaticLiveServerTestCase
from django.test import TestCase

from search_client import SearchClient
from search_client.constants import LANGUAGES, DocumentTypes
from search_client.opensearch.configuration import create_open_search_index_configuration

class BaseLiveServerTestCase(StaticLiveServerTestCase):

    selenium = None
    fixtures = ['locales-edusources', 'privacy_statements']

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        chrome_options = Options()
        chrome_options.add_argument("--headless")
        chrome_options.add_argument("--no-sandbox")
        chrome_options.add_argument("window-size=1920,1080")

        cls.selenium = webdriver.Chrome(service=Service(ChromeDriverManager().install()), options=chrome_options)
        cls.selenium.implicitly_wait(10)
        cls.explicit_wait = 300

    @classmethod
    def tearDownClass(cls):
        cls.selenium.quit()
        super().tearDownClass()

class BaseOpenSearchTestCase(TestCase):

    search = None
    instance = None
    alias_prefix = None

    @classmethod
    def index_body(cls, language):
        return create_open_search_index_configuration(language, DocumentTypes.LEARNING_MATERIAL)

    @classmethod
    def get_alias(cls, language):
        return f"{cls.alias_prefix}-{language}"

    @classmethod
    def setUpClass(cls):
        super().setUpClass()
        cls.search = OpenSearch(
            [settings.OPENSEARCH_HOST]
        )
        for language in LANGUAGES:
            cls.search.indices.create(
                cls.get_alias(language),
                ignore=400,
                body=cls.index_body('nl')
            )
        cls.instance = SearchClient(
            f"{settings.PROTOCOL}://{settings.OPENSEARCH_HOST}",
            DocumentTypes.LEARNING_MATERIAL,
            cls.alias_prefix
        )

    @classmethod
    def tearDownClass(cls):
        for language in LANGUAGES:
            cls.search.indices.delete(
                cls.get_alias(language)
            )
        cls.search.close()
        cls.instance.client.close()
        super().tearDownClass()

    fixtures = ['locales-edusources', 'privacy_statements']


from django.shortcuts import render,redirect
from django.http import HttpResponse
import datetime

x = datetime.datetime.now()
import json

def home(request):
    return render(request,'core/home.html')

def clip(request):
    key=request.POST.get("key")

    data=json.load(open('core/data.json','r',encoding='utf-8'))
    if key[:2] in data and key[2:]==x.strftime('%d%m%y'):
        finaldata=data[key[:2]]
    elif key[:2]=="xx":return redirect("https://prepinsta.com/elite/")
    else:finaldata=data['item']
    context={
        "renderdata":finaldata
    }
    return render(request,'core/yourclipboard.html',context)


import torch

def dice_similarity_coeff(y, yhat, thresholding=False):
    eps = 0.00001
    dice_th = 0.5

    # If thresholding is true, convert the estimated output to a binary image.
    if (thresholding):
        yhat[yhat > dice_th] = 1
        yhat[yhat <= dice_th] = 0

    yflat = y.contiguous().view(-1)
    yhatflat = yhat.contiguous().view(-1)

    intersection = torch.abs((yflat * yhatflat)).sum()
    y_sum = torch.sum(yflat)
    yhat_sum = torch.sum(yhatflat)

    return 1 - ((2. * intersection + eps) / (y_sum + yhat_sum + eps))


"""Charts for offer response binary classification.

Code is adapted from https://github.com/LailaSabar/Starbucks-Capstone-Challenge/blob/master/Starbucks_Capstone_notebook.ipynb
"""

import numpy as np
import pandas as pd
import seaborn as sns

import matplotlib.pyplot as plt
from sklearn.utils.multiclass import unique_labels

def plot_feature_importance(feature_imp):
    """Plot the top 10 important features
    """
    fig, ax = plt.subplots(figsize=(10, 10), nrows=1, ncols=1)
    sns.barplot(x=feature_imp.loc[0:10, 'imp_perc'],
                y=feature_imp.loc[0:10, 'feature'],
                color='#95DAC1',
                data=feature_imp)
    plt.xlabel('Percentage')
    plt.ylabel('Feature')
    plt.title('Top 10 important features')
    plt.show()

def plot_confusion_matrix(conf_matrix,
                          unique_classes,
                          normalized=False,
                          cmap=plt.cm.Greys):
    """Plots the confusion matrix.
    Normalization can be applied by setting `normalize=True`.

    Args:
        conf_matrix: confusion matrix calculated.
        unique_classes: (nd.array) unique labels from the target
        normalize: (boolean) used in chart title

    Returns:
     ax: matplotlib axes object.

    """
    np.set_printoptions(precision=2)

    if normalized:
        title = 'Normalized confusion matrix'
    else:
        title = 'Confusion matrix, without normalization'

    fig, ax = plt.subplots()
    im = ax.imshow(conf_matrix, interpolation='nearest', cmap=cmap)
    ax.figure.colorbar(im, ax=ax)
    # We want to show all ticks...
    ax.set(
        xticks=np.arange(conf_matrix.shape[1]),
        yticks=np.arange(conf_matrix.shape[0]),
        # ... and label them with the respective list entries
        xticklabels=unique_classes,
        yticklabels=unique_classes,
        title=title,
        ylabel='True label',
        xlabel='Predicted label')

    plt.setp(ax.get_xticklabels(),
             rotation=0,
             ha="right",
             rotation_mode="anchor")

    # Loop over data dimensions and create text annotations.
    fmt = '.2f' if normalized else 'd'
    thresh = conf_matrix.max() / 2.
    for i in range(conf_matrix.shape[0]):
        for j in range(conf_matrix.shape[1]):
            ax.text(j,
                    i,
                    format(conf_matrix[i, j], fmt),
                    ha="center",
                    va="center",
                    color="white" if conf_matrix[i, j] > thresh else "black")
    fig.tight_layout()
    return ax


#!/usr/bin/python
'''
This is a module docstring
'''

from pathlib import Path
import paramiko
import netifaces
from ansible.module_utils.basic import AnsibleModule

# Globals
PACKAGE_TO_INSTALL = None
ROUTER = None
USER = None
STATE = None
SSH_IDENTITY = None
CHECK_MODE = False
changed = False
UPDATE = True
DEBUG = False
response = {}

def get_router(router):
    '''
    This is a function docstring
    '''

    if router is None:
        gws = netifaces.gateways()
        return gws['default'][netifaces.AF_INET][0]
    return router

def get_ssh_key():
    '''
    This is a function docstring
    '''

    ssh_key = ''
    if SSH_IDENTITY is not None:
        print("SSH_IDENTITY = {}".format(SSH_IDENTITY))
        ssh_key = paramiko.RSAKey.from_private_key_file(SSH_IDENTITY)
    else:
        keyfile = '{}/.ssh/id_rsa'.format(str(Path.home()))
        ssh_key = paramiko.RSAKey.from_private_key_file(keyfile)
    return ssh_key

def run_command_on_router(command):
    '''
    This is a function docstring
    '''

    global ROUTER

    ssh_key = get_ssh_key()
    ssh = paramiko.SSHClient()
    ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
    ssh.connect(hostname=ROUTER, username=USER, pkey=ssh_key)

    _, ssh_stdout, ssh_stderr = ssh.exec_command(command)

    ssh_stdout_lines = ssh_stdout.read().decode('ascii').split('\n')
    ssh_stderr_lines = ssh_stderr.read().decode('ascii').split('\n')

    return (ssh_stdout_lines, ssh_stderr_lines)

def get_package_version():
    '''
    This is a function docstring
    '''

    cmd_to_execute = 'opkg status {}'.format(PACKAGE_TO_INSTALL)
    stdout, _ = run_command_on_router(cmd_to_execute)

    for line in stdout:
        if line.startswith('Version: '):
            return line.split(' ')[1]
    return None

def add_standard_debug_response(params):
    if DEBUG:
        response['module.params'] = params

def update_package_list():
    if UPDATE:
        cmd_to_execute = 'opkg update'
        _, _ = run_command_on_router(cmd_to_execute)

def main():
    '''
    This is a function docstring
    '''

    global PACKAGE_TO_INSTALL
    global ROUTER
    global USER
    global STATE
    global SSH_IDENTITY
    global CHECK_MODE
    global changed
    global UPDATE
    global DEBUG
    global response

    module = AnsibleModule(
        argument_spec={
            "pkg":          {"required": True, "type": "str"},
            "router":       {"required": False, "type": "str"},
            "user":         {"required": False, "default": "root", "type": "str"},
            "state":        {"default": "present", "choices": ['present',
                                                               'absent'], "type": 'str'},
            "version":      {"required": False, "type": "str"},
            "ssh_identity": {"required": False, "type": "str"},
            "refresh":      {"default": "False", "type": "str" },
            "debug":        {"default": "False", "type": "str" }
        },
        supports_check_mode=True
    )

    # Parse the parameters, to make the code more readable
    PACKAGE_TO_INSTALL = module.params['pkg']
    ROUTER = get_router(module.params['router'])
    USER = module.params['user']
    STATE = module.params['state']
    SSH_IDENTITY = module.params['ssh_identity']
    CHECK_MODE = module.check_mode
    changed = False
    UPDATE = module.params['refresh']
    DEBUG = module.params['debug']

    response = {}

    add_standard_debug_response(module.params)

    update_package_list()

    if STATE == 'present':
        if not CHECK_MODE:
            # We're not in check mode, so need to actually do it
            cmd_to_execute = 'opkg install {}'.format(PACKAGE_TO_INSTALL)
            stdout, _ = run_command_on_router(cmd_to_execute)
            response['reason'] = \
                'Requested state was {} and {} was either not installed or had an update' \
                .format(STATE, PACKAGE_TO_INSTALL)
            response['stdout_lines'] = stdout
            changed = True
        else:
            response['reason'] = \
                'Requested state was {} and {} was either not installed or had an update, but \
                    wasn\'t installed because check mode is enabled'.format(
                STATE, PACKAGE_TO_INSTALL)
    else:
        # State should be absent, so check if the package is installed and remove it
        if not CHECK_MODE:
            # The package is installed
            cmd_to_execute = 'opkg remove {}'.format(PACKAGE_TO_INSTALL)
            stdout, _ = run_command_on_router(cmd_to_execute)
            response['reason'] = 'Requested state was {}, so {} was removed'.format(
                STATE, PACKAGE_TO_INSTALL)
            response['stdout_lines'] = stdout
            if stdout[0].startswith('Refusing to remove essential package'):
                module.fail_json(msg=stdout[0], meta=response)
            changed = True
            if stdout[0] == "No packages removed.":
                response['reason'] = \
                    'Requested state was {}, but {} wasn\'t installed so no action was taken'\
                        .format(STATE, PACKAGE_TO_INSTALL)
                changed = False
        else:
            response['reason'] = \
                'Requested state was {}, but check mode is enabled so {} was not removed'.format(
                STATE, PACKAGE_TO_INSTALL)

    module.exit_json(changed=changed, meta=response)

if __name__ == '__main__':
    main()