from keras.layers import BatchNormalization, Conv1D, SpatialDropout1D, Dropout, Concatenate, Dense, Input, GRU, Flatten
from keras.models import Model
from keras.layers.advanced_activations import LeakyReLU

def FC(data, num_hidden, act='relu', p=None, name='', trainable=True):
    kernel_initializer_fc = 'lecun_uniform'
    if act=='leakyrelu':
        fc = Dense(num_hidden, activation='linear',
                   name='%s_%s' % (name,act),
                   kernel_initializer=kernel_initializer_fc,
                   trainable=trainable)(data) # Add any layer, with the default of a linear squashing function
        fc = LeakyReLU(alpha=.001)(fc)   # add an advanced activation
    else:
        fc = Dense(num_hidden, activation=act,
                   name='%s_%s' % (name,act),
                   kernel_initializer=kernel_initializer_fc,
                   trainable=trainable)(data)
    if not p:
        return fc
    else:
        dropout = Dropout(rate=p, name='%s_dropout' % name)(fc)
        return dropout

def model_DeepDoubleXReference(inputs, num_classes, datasets = ['cpf','sv'], hlf_input = None, scale_hidden = 1,  **kwargs):
    """
    reference 1x1 convolutional model for 'deepDoubleX'
    with recurrent layers and batch normalisation
    """

    kernel_initializer = 'he_normal'
    kernel_initializer_fc = 'lecun_uniform'

    normalizedInputs = []
    for i in range(len(inputs)):
        normedLayer = BatchNormalization(momentum=0.3,axis=-1, name = '%s_input_batchnorm'%datasets[i])(inputs[i])
        normalizedInputs.append(normedLayer)

    flattenLayers = []
    if hlf_input is not None:
        flattenLayers.append(Flatten()(normalizedInputs[hlf_input]))

    for i in range(len(inputs)):
        if i==hlf_input: continue
        ds = datasets[i]
        normalizedInput = normalizedInputs[i]
        x = Conv1D(filters=32*scale_hidden, kernel_size=(1,), strides=(1,), padding='same',
                                kernel_initializer=kernel_initializer, use_bias=False, name='%s_conv1'%ds,
                                activation = 'relu', data_format='channels_last')(normalizedInput)
        x = SpatialDropout1D(rate=0.1)(x)
        x = Conv1D(filters=32*scale_hidden, kernel_size=(1,), strides=(1,), padding='same',
                             kernel_initializer=kernel_initializer, use_bias=False, name='%s_conv2'%ds,
                             activation = 'relu', data_format='channels_last')(x)
        x = SpatialDropout1D(rate=0.1)(x)
        x = GRU(50*scale_hidden,go_backwards=True,implementation=2,name='%s_gru'%ds)(x)
        x = Dropout(rate=0.1)(x)
        flattenLayers.append(x)

    if len(datasets)>1:
        concat = Concatenate()(flattenLayers)
    else:
        concat = flattenLayers[0]

    fc = FC(concat, 100*scale_hidden, p=0.1, name='fc1')
    output = Dense(num_classes, activation='softmax', name='ID_pred', kernel_initializer=kernel_initializer_fc)(fc)

    model = Model(inputs=inputs, outputs=[output])

    return model


from django.shortcuts import render
from rest_framework.views import APIView
from rest_framework.response import Response
from rest_framework import status
from hospitalapi.serializers import HospitalSerializer, CategorySerializer
from hospitals.models import Hospital, Category

# Create your views here.
def getSuccessResponse(data, code, msg):
    response_data = {
            'message': msg,
            'status_code': code,
            'data': data,
            'error': [],
            'pagination': [],
        }
    return response_data

def getErrorResponse(error, code, msg):
    response_data = {
            'message': msg,
            'status_code': code,
            'data': [],
            'error': error,
            'pagination': [],
        }
    return response_data

class HospitalApiView(APIView):
    def get(self, request):
        if request.method != "GET":
            msg = 'Method now allow'
            return Response(getErrorResponse(msg, 405, msg))
        data = Hospital.objects.all()
        serializer = HospitalSerializer(data, many=True)
        msg = 'Hospital List'
        return Response(getSuccessResponse(serializer.data, 200, msg), status=status.HTTP_200_OK)

    def post(self, request):
        if request.method == "POST":
            req_data = {
                'full_name': request.POST.get('full_name'),
                'short_name': request.POST.get('short_name'),
                'category': 1,
                'contact': request.POST.get('contact'),
                'address': request.POST.get('address'),
            }
            serializer = HospitalSerializer(data=req_data)
            if serializer.is_valid():
                serializer.save()
                return Response(getSuccessResponse(serializer.data, 201, 'Added success'))
            else:
                return Response(getErrorResponse(serializer.errors, 400, 'Something went wrong'))
        msg = 'Method now allow'
        return Response(getErrorResponse(msg, 405, msg))

class HospitalApiIdView(APIView):
    def get_object(self, id):
        try:
            data = Hospital.objects.get(id=id)
            return data
        except Hospital.DoesNotExist:
            return None

    def get(self, request, id):
        instance = self.get_object(id)
        if not instance:
            return Response(getErrorResponse('No data', 404, 'Data not found'), status=status.HTTP_404_NOT_FOUND)
        serializer = HospitalSerializer(instance)
        return Response(getSuccessResponse(serializer.data, 200, 'Hospital detail'), status=status.HTTP_200_OK)

    def put(self, request, id):
        instance = self.get_object(id)
        if not instance:
            return Response(getErrorResponse('No data', 404, 'Data not found'), status=status.HTTP_404_NOT_FOUND)

        req_data = {
            'full_name': request.POST.get('full_name'),
            'short_name': request.POST.get('short_name'),
            'category': 1,
            'contact': request.POST.get('contact'),
            'address': request.POST.get('address'),
        }

        serializer = HospitalSerializer(data=req_data, instance=instance, partial=False)
        if serializer.is_valid():
            serializer.save()
            return Response(getSuccessResponse(serializer.data, 200, 'Data updated successfully'), status=status.HTTP_200_OK)
        else:
            return Response(getErrorResponse(serializer.errors, 400, 'Something went wrong'), status=status.HTTP_400_BAD_REQUEST)

    def delete(self, request, id):
        instance_data = self.get_object(id)
        if not instance_data:
            return Response(getErrorResponse('No data', 404, 'Data not found'), status=status.HTTP_404_NOT_FOUND)
        instance_data.delete()
        return Response(getSuccessResponse('Data deleted', 200, 'Data deleted successfully'), status=status.HTTP_200_OK)


import logging
from argparse import Namespace
from pathlib import Path
from typing import Callable, Optional

from protostar.cli import (
    LIB_PATH_ARG,
    LibPathResolver,
    ProtostarArgument,
    ProtostarCommand,
)
from protostar.cli.common_arguments import PACKAGE_ARG
from protostar.configuration_file import ConfigurationFile
from protostar.io.log_color_provider import LogColorProvider
from protostar.package_manager import extract_info_from_repo_id

from .install_package_from_repo import install_package_from_repo
from .pull_package_submodules import pull_package_submodules

EXTERNAL_DEPENDENCY_REFERENCE_DESCRIPTION = """- `GITHUB_ACCOUNT_NAME/REPO_NAME[@TAG]`
    - `OpenZeppelin/cairo-contracts@v0.4.0`
- `URL_TO_THE_REPOSITORY`
    - `https://github.com/OpenZeppelin/cairo-contracts`
- `SSH_URI`
    - `git@github.com:OpenZeppelin/cairo-contracts.git`
"""

class InstallCommand(ProtostarCommand):
    def __init__(
        self,
        project_root_path: Path,
        lib_path_resolver: LibPathResolver,
        log_color_provider: LogColorProvider,
    ) -> None:
        super().__init__()
        self._project_root_path = project_root_path
        self._lib_path_resolver = lib_path_resolver
        self._log_color_provider = log_color_provider

    @property
    def name(self) -> str:
        return "install"

    @property
    def description(self) -> str:
        return "Install a dependency as a git submodule."

    @property
    def example(self) -> Optional[str]:
        return "$ protostar install https://github.com/OpenZeppelin/cairo-contracts"

    @property
    def arguments(self):
        return [
            LIB_PATH_ARG,
            PACKAGE_ARG,
            ProtostarArgument(
                name="name",
                description="A custom package name. Use it to resolve name conflicts.",
                type="str",
            ),
        ]

    async def run(self, args: Namespace):
        logging.info("Executing install")
        try:
            self.install(
                package_name=args.package,
                libs_path=self._lib_path_resolver.resolve(args.lib_path),
                on_unknown_version=lambda: logging.warning(
                    (
                        "Fetching from the mainline. The mainline can be in the non-releasable state.\n"
                        "Installing packages without providing specific version/tag is strongly discouraged."
                    )
                ),
                alias=args.name,
            )
        except BaseException as exc:
            logging.error("Installation failed")
            raise exc
        logging.info("Installed successfully")

    def install(
        self,
        package_name: Optional[str],
        libs_path: Path,
        on_unknown_version: Callable,
        alias: Optional[str] = None,
    ) -> None:
        if package_name:
            package_info = extract_info_from_repo_id(package_name)
            if package_info.version is None:
                on_unknown_version()
            install_package_from_repo(
                alias or package_info.name,
                package_info.url,
                project_root_path=self._project_root_path,
                destination=libs_path,
                tag=package_info.version,
            )
            logging.info(ConfigurationFile.create_appending_cairo_path_suggestion())
        else:
            if not libs_path.exists():
                logging.warning(
                    "Directory %s doesn't exist.\n"
                    "Did you install any package before running this command?",
                    libs_path,
                )
                return
            pull_package_submodules(
                on_submodule_update_start=lambda package_info: logging.info(
                    "Installing %s%s%s %s(%s)%s",
                    self._log_color_provider.get_color("CYAN"),
                    package_info.name,
                    self._log_color_provider.get_color("RESET"),
                    self._log_color_provider.get_color("GRAY"),
                    package_info.url,
                    self._log_color_provider.get_color("RESET"),
                ),
                repo_dir=self._project_root_path,
                libs_dir=libs_path,
            )


from __future__ import unicode_literals

import uuid
import logging
import time
from typing import Iterable, Union, Type

from uamqp import types, constants, errors  # type: ignore
from uamqp import SendClient  # type: ignore

from azure.core.tracing import SpanKind, AbstractSpan  # type: ignore
from azure.core.settings import settings  # type: ignore

from .common import EventData, EventDataBatch
from .error import _error_handler, OperationTimeoutError, EventDataError
from ._consumer_producer_mixin import ConsumerProducerMixin

log = logging.getLogger(__name__)

def _error(outcome, condition):
    if outcome != constants.MessageSendResult.Ok:
        raise condition

def _set_partition_key(event_datas, partition_key):
    ed_iter = iter(event_datas)
    for ed in ed_iter:
        ed._set_partition_key(partition_key)  # pylint:disable=protected-access
        yield ed

def _set_trace_message(event_datas, parent_span=None):
    ed_iter = iter(event_datas)
    for ed in ed_iter:
        ed._trace_message(parent_span)  # pylint:disable=protected-access
        yield ed

class EventHubProducer(ConsumerProducerMixin):  # pylint:disable=too-many-instance-attributes
    """
    A producer responsible for transmitting EventData to a specific Event Hub,
    grouped together in batches. Depending on the options specified at creation, the producer may
    be created to allow event data to be automatically routed to an available partition or specific
    to a partition.

    Please use the method `create_producer` on `EventHubClient` for creating `EventHubProducer`.
    """
    _timeout_symbol = b'com.microsoft:timeout'

    def __init__(self, client, target, **kwargs):
        """
        Instantiate an EventHubProducer. EventHubProducer should be instantiated by calling the `create_producer` method
        in EventHubClient.

        :param client: The parent EventHubClient.
        :type client: ~azure.eventhub.client.EventHubClient.
        :param target: The URI of the EventHub to send to.
        :type target: str
        :param partition: The specific partition ID to send to. Default is None, in which case the service
         will assign to all partitions using round-robin.
        :type partition: str
        :param send_timeout: The timeout in seconds for an individual event to be sent from the time that it is
         queued. Default value is 60 seconds. If set to 0, there will be no timeout.
        :type send_timeout: float
        :param keep_alive: The time interval in seconds between pinging the connection to keep it alive during
         periods of inactivity. The default value is None, i.e. no keep alive pings.
        :type keep_alive: float
        :param auto_reconnect: Whether to automatically reconnect the producer if a retryable error occurs.
         Default value is `True`.
        :type auto_reconnect: bool
        """
        partition = kwargs.get("partition", None)
        send_timeout = kwargs.get("send_timeout", 60)
        keep_alive = kwargs.get("keep_alive", None)
        auto_reconnect = kwargs.get("auto_reconnect", True)

        super(EventHubProducer, self).__init__()
        self._max_message_size_on_link = None
        self._client = client
        self._target = target
        self._partition = partition
        self._timeout = send_timeout
        self._error = None
        self._keep_alive = keep_alive
        self._auto_reconnect = auto_reconnect
        self._retry_policy = errors.ErrorPolicy(max_retries=self._client._config.max_retries, on_error=_error_handler)  # pylint: disable=protected-access
        self._reconnect_backoff = 1
        self._name = "EHProducer-{}".format(uuid.uuid4())
        self._unsent_events = None
        if partition:
            self._target += "/Partitions/" + partition
            self._name += "-partition{}".format(partition)
        self._handler = None
        self._outcome = None
        self._condition = None
        self._link_properties = {types.AMQPSymbol(self._timeout_symbol): types.AMQPLong(int(self._timeout * 1000))}

    def _create_handler(self):
        self._handler = SendClient(
            self._target,
            auth=self._client._create_auth(),  # pylint:disable=protected-access
            debug=self._client._config.network_tracing,  # pylint:disable=protected-access
            msg_timeout=self._timeout,
            error_policy=self._retry_policy,
            keep_alive_interval=self._keep_alive,
            client_name=self._name,
            link_properties=self._link_properties,
            properties=self._client._create_properties(self._client._config.user_agent))  # pylint: disable=protected-access

    def _open_with_retry(self):
        return self._do_retryable_operation(self._open, operation_need_param=False)

    def _send_event_data(self, timeout_time=None, last_exception=None):
        if self._unsent_events:
            self._open()
            remaining_time = timeout_time - time.time()
            if remaining_time <= 0.0:
                if last_exception:
                    error = last_exception
                else:
                    error = OperationTimeoutError("send operation timed out")
                log.info("%r send operation timed out. (%r)", self._name, error)
                raise error
            self._handler._msg_timeout = remaining_time * 1000  # pylint: disable=protected-access
            self._handler.queue_message(*self._unsent_events)
            self._handler.wait()
            self._unsent_events = self._handler.pending_messages
            if self._outcome != constants.MessageSendResult.Ok:
                if self._outcome == constants.MessageSendResult.Timeout:
                    self._condition = OperationTimeoutError("send operation timed out")
                _error(self._outcome, self._condition)

    def _send_event_data_with_retry(self, timeout=None):
        return self._do_retryable_operation(self._send_event_data, timeout=timeout)

    def _on_outcome(self, outcome, condition):
        """
        Called when the outcome is received for a delivery.

        :param outcome: The outcome of the message delivery - success or failure.
        :type outcome: ~uamqp.constants.MessageSendResult
        :param condition: Detail information of the outcome.

        """
        self._outcome = outcome
        self._condition = condition

    def create_batch(self, max_size=None, partition_key=None):
        # type:(int, str) -> EventDataBatch
        """
        Create an EventDataBatch object with max size being max_size.
        The max_size should be no greater than the max allowed message size defined by the service side.

        :param max_size: The maximum size of bytes data that an EventDataBatch object can hold.
        :type max_size: int
        :param partition_key: With the given partition_key, event data will land to
         a particular partition of the Event Hub decided by the service.
        :type partition_key: str
        :return: an EventDataBatch instance
        :rtype: ~azure.eventhub.EventDataBatch
        """

        if not self._max_message_size_on_link:
            self._open_with_retry()

        if max_size and max_size > self._max_message_size_on_link:
            raise ValueError('Max message size: {} is too large, acceptable max batch size is: {} bytes.'
                             .format(max_size, self._max_message_size_on_link))

        return EventDataBatch(max_size=(max_size or self._max_message_size_on_link), partition_key=partition_key)

    def send(self, event_data, partition_key=None, timeout=None):
        # type:(Union[EventData, EventDataBatch, Iterable[EventData]], Union[str, bytes], float) -> None
        """
        Sends an event data and blocks until acknowledgement is
        received or operation times out.

        :param event_data: The event to be sent. It can be an EventData object, or iterable of EventData objects
        :type event_data: ~azure.eventhub.common.EventData, Iterator, Generator, list
        :param partition_key: With the given partition_key, event data will land to
         a particular partition of the Event Hub decided by the service. partition_key
         could be omitted if event_data is of type ~azure.eventhub.EventDataBatch.
        :type partition_key: str
        :param timeout: The maximum wait time to send the event data.
         If not specified, the default wait time specified when the producer was created will be used.
        :type timeout: float

        :raises: ~azure.eventhub.AuthenticationError, ~azure.eventhub.ConnectError, ~azure.eventhub.ConnectionLostError,
                ~azure.eventhub.EventDataError, ~azure.eventhub.EventDataSendError, ~azure.eventhub.EventHubError
        :return: None
        :rtype: None
        """
        # Tracing code
        span_impl_type = settings.tracing_implementation()  # type: Type[AbstractSpan]
        child = None
        if span_impl_type is not None:
            child = span_impl_type(name="Azure.EventHubs.send")
            child.kind = SpanKind.CLIENT  # Should be PRODUCER

        self._check_closed()
        if isinstance(event_data, EventData):
            if partition_key:
                event_data._set_partition_key(partition_key)  # pylint: disable=protected-access
            wrapper_event_data = event_data
            wrapper_event_data._trace_message(child)  # pylint: disable=protected-access
        else:
            if isinstance(event_data, EventDataBatch):  # The partition_key in the param will be omitted.
                if partition_key and partition_key != event_data._partition_key:  # pylint: disable=protected-access
                    raise EventDataError('The partition_key does not match the one of the EventDataBatch')
                wrapper_event_data = event_data  # type:ignore
            else:
                if partition_key:
                    event_data = _set_partition_key(event_data, partition_key)
                event_data = _set_trace_message(event_data, child)
                wrapper_event_data = EventDataBatch._from_batch(event_data, partition_key)  # pylint: disable=protected-access
        wrapper_event_data.message.on_send_complete = self._on_outcome
        self._unsent_events = [wrapper_event_data.message]

        if span_impl_type is not None and child is not None:
            with child:
                self._client._add_span_request_attributes(child)  # pylint: disable=protected-access
                self._send_event_data_with_retry(timeout=timeout)
        else:
            self._send_event_data_with_retry(timeout=timeout)

    def close(self):  # pylint:disable=useless-super-delegation
        # type:() -> None
        """
        Close down the handler. If the handler has already closed,
        this will be a no op.
        """
        super(EventHubProducer, self).close()


import os
import sys
from webbrowser import get

from pydantic import ValidationError
from pydantic.error_wrappers import ErrorWrapper
from dataclasses import dataclass
from typing import Sequence, Tuple
import pathlib

from bin.contentctl_project.contentctl_core.domain.entities.enums.enums import SecurityContentType
from bin.contentctl_project.contentctl_core.domain.entities.detection_tags import DetectionTags
from bin.contentctl_project.contentctl_core.application.builder.basic_builder import BasicBuilder
from bin.contentctl_project.contentctl_core.application.builder.detection_builder import DetectionBuilder
from bin.contentctl_project.contentctl_core.application.builder.story_builder import StoryBuilder
from bin.contentctl_project.contentctl_core.application.builder.director import Director
from bin.contentctl_project.contentctl_core.application.factory.utils.utils import Utils

@dataclass(frozen=True)
class BAFactoryInputDto:
    input_path: str
    basic_builder: BasicBuilder
    detection_builder: DetectionBuilder
    director: Director
    attack_enrichment: dict

@dataclass(frozen=True)
class BAFactoryOutputDto:
     detections: list

class BAFactory():
    input_dto: BAFactoryInputDto
    output_dto: BAFactoryOutputDto
    ids: dict[str,list[pathlib.Path]] = {}

    def __init__(self, output_dto: BAFactoryOutputDto) -> None:
        self.output_dto = output_dto

    def execute(self, input_dto: BAFactoryInputDto) -> None:
        self.input_dto = input_dto
        print("Creating Security Content - SSA. This may take some time...")

        validation_errors = self.createSecurityContent(SecurityContentType.detections)

        if len(validation_errors) != 0:
            print(f"There were [{len(validation_errors)}] error(s) found while parsing security_content")
            for ve in validation_errors:
                file_path = ve[0]
                error = ve[1]
                print(f'\nValidation Error for file [{file_path}]:\n{str(error)}')
            #raise(Exception("Error(s) validating Security Content"))

    def createSecurityContent(self, type: SecurityContentType) -> list[Tuple[pathlib.Path,  ValidationError]]:
        objects = []
        files = Utils.get_all_yml_files_from_directory(os.path.join(self.input_dto.input_path, 'ssa_detections'))

        validation_errors:list[Tuple[pathlib.Path,  ValidationError]] = []

        files_with_ssa = [f for f in files if f.name.startswith('ssa_')]

        already_ran = False
        progress_percent = 0
        type_string = "UNKNOWN TYPE"
        for index,file in enumerate(files_with_ssa):

            #Index + 1 because we are zero indexed, not 1 indexed.  This ensures
            # that printouts end at 100%, not some other number
            progress_percent = ((index+1)/len(files_with_ssa)) * 100

            progress_percent = ((index+1)/len(files_with_ssa)) * 100
            #try:
            type_string = "UNKNOWN TYPE"
            if type == SecurityContentType.detections:
                type_string = "Detections"
                self.input_dto.director.constructDetection(self.input_dto.detection_builder, file, [], [], [], self.input_dto.attack_enrichment, [], [])
                detection = self.input_dto.detection_builder.getObject()
                Utils.add_id(self.ids, detection, file)

                tag_and_nist_errors = []

                if detection.tags.cis20 == None:
                    error = TypeError(f"Detection Tags missing cis20 field")
                    tag_and_nist_errors.append(ErrorWrapper(error, loc="cis20"))

                if detection.tags.nist == None:
                    error = TypeError(f"Detection Tags missing nist field")
                    tag_and_nist_errors.append(ErrorWrapper(error, loc="nist"))

                if len(tag_and_nist_errors) > 0:
                    raise ValidationError( tag_and_nist_errors , DetectionTags)

                if detection.status in ["production","validation"]:
                    self.output_dto.detections.append(detection)
            else:
                raise(Exception(f"Unsupported content type: [{type}]"))

            if (sys.stdout.isatty() and sys.stdin.isatty() and sys.stderr.isatty()) or not already_ran:
                already_ran = True
                print(f"\r{f'{type_string} Progress'.rjust(23)}: [{progress_percent:3.0f}%]...", end="", flush=True)

            # except ValidationError as e:
            #     validation_errors.append((pathlib.Path(file), e))
            # except Exception as e:
            #     print(f"Unknown exception caught while Creating BA Security Content: {str(e)}")
            #     sys.exit(1)

        print(f"\r{f'{type_string} Progress'.rjust(23)}: [{progress_percent:3.0f}%]...", end="", flush=True)
        print("Done!")

        return validation_errors


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.db import models, migrations
import datetime

class Migration(migrations.Migration):

    dependencies = [
        ('traceapp', '0005_auto_20151214_0655'),
    ]

    operations = [
        migrations.CreateModel(
            name='Device',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('name', models.CharField(max_length=200)),
                ('device_id', models.CharField(max_length=200)),
                ('create_date', models.DateTimeField(default=datetime.datetime.now)),
            ],
            options={
            },
            bases=(models.Model,),
        ),
        migrations.DeleteModel(
            name='Item',
        ),
    ]


import pygame

import main
from const import *

class Game:
    def __init__(self):
        self.surface = pygame.display.set_mode((WIDTH, HEIGHT))
        self.clock = pygame.time.Clock()
        self.bg = pygame.image.load("sprites/background.png").convert_alpha()
        self.bg_rect = self.bg.get_rect()
        self.is_continue = True
        self.font = pygame.font.SysFont('Comic Sans MS', 24)

    def run(self):
        while self.is_continue:
            self.surface.fill(BLACK)
            self.surface.blit(self.bg, self.bg_rect)
            self.clock.tick(FPS)
            for event in pygame.event.get():
                mouse_pos = pygame.mouse.get_pos()
                if event.type == pygame.QUIT:
                    pygame.quit()
            sprites.draw(self.surface)
            pygame.display.flip()

def create_ground():
    for x in range(0, 1024, 32):
        ground_block = Block(blocks_sprites['Dirt'], x, 608, "dirt")
        sprites.add(ground_block)
        blocks.add(ground_block)

sprites = pygame.sprite.Group()
blocks = pygame.sprite.Group()

if __name__ == '__main__':
    g = Game()
    create_ground()


import json

from fastapi import APIRouter, Depends, HTTPException
from fastapi import UploadFile, File
from fastapi.responses import StreamingResponse

from app.database import communities_collection
from app.database import membership_collection
from app.database import token
from app.database import users_collection
from app.models.models import *

router = APIRouter()

def prepare_for_return(user: Users):
    json_obj = user.to_json()
    dictionary = json.loads(json_obj)
    del dictionary["password"]
    dictionary["id"] = dictionary["_id"]["$oid"]
    del dictionary["_id"]
    return dictionary

@router.get("/")
async def user_basic():
    return {"message": "Hello user!"}

@router.post("/register")
async def register_user(user: UserRegisterCall =
                        Depends(users_collection.check_email_exist)):
    user_db = users_collection.insert_user(user)
    # TODO: check insert succeeded, id != None
    access_token = token.create_access_token(user_db.id)
    return {"access_token": access_token,
            "token_type": "bearer",
            "user_profile": prepare_for_return(user_db)}

@router.post("/login")
async def login_user(user=Depends(users_collection.login_user)):
    access_token = token.create_access_token(user.id)
    return {"access_token": access_token,
            "token_type": "bearer",
            "user_profile": prepare_for_return(user)}

@router.get("/token")
async def validate_token(user: Users = Depends(users_collection.get_user_by_id)):
    return {}

@router.get("/me")
async def get_current_user(user: Users = Depends(users_collection.get_user_by_id)):
    return prepare_for_return(user)

@router.post("/me/upload_photo")
async def upload_user_photo(photo: UploadFile = File(...), user: Users = Depends(users_collection.get_user_by_id)):
    if user.photo:
        user.photo.delete()
    user.photo.put(photo.file, content_type=photo.content_type)
    user.save()
    return {}

@router.get("/me/photo")
async def user_photo(user: Users = Depends(users_collection.get_user_by_id)):
    photo = [user.photo.read()]
    if photo == [None]:
        raise HTTPException(status_code=400, detail="User has no photo")
    aux = user.photo.read()
    while aux:
        photo.append(aux)
        aux = user.photo.read()
    photo = iter(photo)
    return StreamingResponse(photo, media_type=user.photo.get().content_type)

@router.get("/me/challenges")
async def get_user_active_challenges(user: Users = Depends(users_collection.get_user_by_id)):
    communities = membership_collection.get_communities(str(user.id))
    response = UserChallenge(id=str(user.id))
    for community in communities:
        if community.is_joined:
            challenge = communities_collection.get_community_challenge(str(community.community_id))
            if challenge:
                response.challenges.append(UserChallenge.ChallengeBase(
                    name=challenge.name, number_of_steps=challenge.number_of_steps,
                    reward=challenge.reward, start_date=challenge.start_date,
                    end_date=challenge.end_date, id=str(challenge.id),
                    community_id=str(community.id)
                ))
    return response

@router.get("/me/communities")
async def get_current_user_communities(user: Users = Depends(users_collection.get_user_by_id)):
    communities = membership_collection.get_communities(str(user.id))
    response = UserCommunities(id=str(user.id))
    for community in communities:
        response.communities.append(UserCommunities.
                                    CommunityBase(id=community.community_id,
                                                  name=communities_collection.get_community_name(
                                                      community.community_id),
                                                  is_joined=community.is_joined))
    return response

@router.get("/me/{community_id}/add_challenge_reward")
async def update_score(community_id, user: Users = Depends(users_collection.get_user_by_id)):
    community = Community.objects(id=community_id).get()
    challenge_id = community.challenge
    membership = membership_collection.add_challenge_reward(str(user.id), community_id, challenge_id)
    json_obj = membership.to_json()
    dictionary = json.loads(json_obj)
    dictionary["id"] = dictionary["_id"]["$oid"]
    del dictionary["_id"]
    return dictionary

@router.get("/me/{community_id}/get_score")
async def get_score(community_id, user: Users = Depends(users_collection.get_user_by_id)):
    membership = Membership.objects(user_id=str(user.id), community_id=community_id).get()
    return {"Score": membership.score}

@router.post("/me/add_steps")
async def update_steps(userSteps: UserAddSteps, user: Users = Depends(users_collection.get_user_by_id)):
    current_dictionary = {**user.daily_steps}
    date_to_add = userSteps.date.date()
    key = users_collection.date_in_dict(date_to_add, current_dictionary)
    if key is not None:
        current_dictionary[key] += userSteps.steps_to_add
    else:
        current_dictionary[str(date_to_add)] = userSteps.steps_to_add

    user.daily_steps = current_dictionary
    user.save()
    users_collection.check_completed_achievements(user)
    return prepare_for_return(user)

@router.get("/me/{date}/steps")
async def get_steps_at_date(date: str, user: Users = Depends(users_collection.get_user_by_id)):
    current_dictionary = {**user.daily_steps}
    key = users_collection.date_in_dict(datetime.strptime(date, "%Y-%m-%d").date(), current_dictionary)
    if key is not None:
        return {date: current_dictionary[key]}
    else:
        raise HTTPException(status_code=400, detail="No data at this date")

@router.get("/me/achievements")
async def get_user_achievements(user: Users = Depends(users_collection.get_user_by_id)):
    return {"achievements": user.achievements}


import numpy
import Dataset
import sklearn.linear_model

class LinearRegression:
	def __init__(self):
		self.classifier = sklearn.linear_model.LinearRegression()

	def get_X_losses(self, instances):
		X = []
		losses = []
		for ins in instances:
			chosenFeature = ins.x[:, ins.y].tolist()
			X.append(chosenFeature)
			losses.append(ins.loss)
		X = numpy.asarray(X)
		losses = numpy.asarray(losses)
		return X, losses

	def train(self, trainInstances):
		X, losses = self.get_X_losses(trainInstances)
		self.classifier.fit(X, losses)

	def predict(self, testInstances):
		X, losses = self.get_X_losses(testInstances)
		prediction = self.classifier.predict(X)
		print(prediction)

if __name__ == '__main__':
	dataset = Dataset.Dataset()
	instances = dataset.read_bandit_data('../data/Brute.txt')
	regressor = LinearRegression()
	regressor.train(instances)
	regressor.predict(instances)


import matplotlib.pyplot as plt
import numpy as np

time = np.linspace(0,1,10000)
f0 = 10.0
w0 = 2*np.pi*f0
amplitude = np.sin(w0*time)

for fs in range(1,40):
    plt.clf()
    Ts = 1/fs
    print(fs)
    sampling_times = np.arange(0,1,Ts)
    samples = np.sin(w0*sampling_times)
    plt.plot(time,amplitude)
    plt.plot(sampling_times,samples,'r-*')
    plt.grid()
    plt.pause(2.0)

plt.show()


import numpy
from typing import Tuple

from towhee._types import Image
from towhee.hparam import param_scope
from towhee.functional.entity import Entity

def get_df_on_columns(self, index: Tuple[str]):
    # pylint: disable=import-outside-toplevel
    from towhee.utils.pandas_utils import pandas as pd
    def inner(entity: Entity):
        data = {}
        for feature in index:
            data[feature] = getattr(entity, feature)
        return data

    data = map(inner, self)
    df = pd.DataFrame(data)
    return df

def calc_df(df, feature: str, target: str):
    # pylint: disable=import-outside-toplevel
    from towhee.utils.pandas_utils import pandas as pd
    lst = []
    df[feature] = df[feature].fillna('NULL')

    if target:
        for i in range(df[feature].nunique()):
            val = list(df[feature].unique())[i]
            lst.append([feature,                                                         # Variable
                        val,                                                             # Value
                        df[df[feature] == val].count()[feature],                         # All
                        df[(df[feature] == val) & (df[target] == 0)].count()[feature],   # Good (think: Fraud == 0)
                        df[(df[feature] == val) & (df[target] == 1)].count()[feature]])  # Bad (think: Fraud == 1)

        data = pd.DataFrame(lst, columns=['Variable', 'Value', 'All', 'Good', 'Bad'])
        data['Share'] = data['All'] / data['All'].sum()
        data['Bad Rate'] = data['Bad'] / data['All']
        data['Distribution Good'] = (data['All'] - data['Bad']) / (data['All'].sum() - data['Bad'].sum())
        data['Distribution Bad'] = data['Bad'] / data['Bad'].sum()
        data['WoE'] = numpy.log(data['Distribution Good'] / data['Distribution Bad'])

        data = data.replace({'WoE': {numpy.inf: 0, -numpy.inf: 0}})
        data['IV'] = data['WoE'] * (data['Distribution Good'] - data['Distribution Bad'])

        data = data.sort_values(by=['Variable', 'Value'], ascending=[True, True])
        data.index = range(len(data.index))

        iv = data['IV'].sum()
        print(f'Variable: {feature}\'s IV sum is: {iv}')
        return data
    else:
        for i in range(df[feature].nunique()):
            val = list(df[feature].unique())[i]
            lst.append([feature,                                                         # Variable
                        val,                                                             # Value
                        df[df[feature] == val].count()[feature]])                         # All
        data = pd.DataFrame(lst, columns=['Variable', 'Value', 'All'])
        data['Share'] = data['All'] / data['All'].sum()
        return data

def _feature_summarize_callback(self):
    # pylint: disable=import-outside-toplevel
    from towhee.utils.pandas_utils import pandas as pd
    def wrapper(_: str, index, *arg, **kws):
        index = list(index)
        if arg:
            kws['target'], = arg

        target = None
        if 'target' in kws:
            target = kws.pop('target')
            index.append(target)

        df = get_df_on_columns(self, index)
        summarize = pd.DataFrame()
        if target:
            index.remove(target)
        for feature in index:
            data = calc_df(df, feature, target)
            summarize = summarize.append(data)

        # pylint: disable=import-outside-toplevel
        from towhee.utils import ipython_utils
        ipython_utils.display(summarize)

    return wrapper

def _plot_callback(self):
    # pylint: disable=unused-argument
    def wrapper(_: str, index, *arg, **kws):
        df = get_df_on_columns(self, index)
        if 'kind' not in kws:
            kws.update(kind='hist')
        df.plot(**kws)

    return wrapper

class DisplayMixin:
    """
    Mixin for display data.

    Example:

    >>> from towhee import DataCollection
    >>> from towhee import Entity
    >>> dc = DataCollection([Entity(a=a, b=b, c=c) for a, b, c in zip([2,1], [1,2], [0,1])])
    >>> dc.feature_summarize['a'](target='c')
    Variable: a's IV sum is: 0.0
      Variable  Value  All  Good  Bad  Share  Bad Rate  Distribution Good  Distribution Bad  WoE   IV
    0        a      1    1     0    1    0.5       1.0                0.0               1.0  0.0 -0.0
    1        a      2    1     1    0    0.5       0.0                1.0               0.0  0.0  0.0
    >>> dc.plot['a']()
    """
    def __init__(self):
        super().__init__()
        self.feature_summarize = param_scope().callholder(_feature_summarize_callback(self))
        self.plot = param_scope().callholder(_plot_callback(self))

    def as_str(self):
        return self._factory(map(str, self._iterable))

    def show(self, limit=5, header=None, tablefmt='html'):
        """
        Print the first n lines of a DataCollection.

        Args:
            limit (`int`):
                The number of lines to print. Default value is 5.
                Print all if limit is non-positive.
            header (list of `str`):
                The field names.
            tablefmt (`str`):
                The format of the output, support html, plain.
        """

        contents = [x for i, x in enumerate(self._iterable) if i < limit]

        if all(isinstance(x, Entity) for x in contents):
            header = tuple(contents[0].to_dict()) if not header else header
            data = [list(x.to_dict().values()) for x in contents]
        else:
            data = [[x] for x in contents]

        table_display(to_printable_table(data, header, tablefmt))

def table_display(table, tablefmt='html'):
    """
    Display table

    Args:
        table (`str`):
            Table in printable format, such as HTML.
        tablefmt (`str`):
            The format of the output, support html, plain.
    """
    # pylint: disable=import-outside-toplevel
    from towhee.utils import ipython_utils

    if tablefmt == 'html':
        ipython_utils.display(ipython_utils.HTML(table))
    elif tablefmt == 'plain':
        ipython_utils.display(table)
    else:
        raise ValueError('unsupported table format %s' % tablefmt)

if __name__ == '__main__':
    import doctest
    doctest.testmod(verbose=False)

def to_printable_table(data, header=None, tablefmt='html'):
    """
    Convert two dimensional data structure into printable table

    Args:
        data (`List[List]`, or `List[Dict]`):
            The data filled into table. If a list of dict is given, keys are used as column names.
        header (`Iterable[str]`):
            The name of columns defined by users.
        tablefmt (`str`):
            The format of the output, support html, plain.
    """
    header = [] if not header else header

    if tablefmt == 'html':
        return to_html_table(data, header)
    elif tablefmt == 'plain':
        return to_plain_table(data, header, tablefmt)

    raise ValueError('unsupported table format %s' % tablefmt)

def to_plain_table(data, header, tablefmt):
    """
    Convert two dimensional data structure into plain table

    Args:
        data (`List[List]`, or `List[Dict]`):
            The data filled into table. If a list of dict is given, keys are used as column names.
        header (`Iterable[str]`):
            The name of columns defined by users.
        tablefmt (`str`):
            The format of the output, support plain.
    """
    # pylint: disable=import-outside-toplevel
    from tabulate import tabulate

    tb_contents = [[_to_plain_cell(x) for x in r] for r in data]
    return tabulate(tb_contents, headers=header, tablefmt=tablefmt)

def _to_plain_cell(data):
    if isinstance(data, str):
        return _text_brief_repr(data)
    if isinstance(data, Image):
        return _image_brief_repr(data)
    elif isinstance(data, numpy.ndarray):
        return _ndarray_brief_repr(data)
    elif isinstance(data, (list, tuple)):
        if all(isinstance(x, str) for x in data):
            return _texts_brief_repr(data)
        elif all(isinstance(x, Image) for x in data):
            return _images_brief_repr(data)
        elif all(isinstance(x, numpy.ndarray) for x in data):
            return _ndarrays_brief_repr_(data)
    return _brief_repr(data)

def to_html_table(data, header):
    """
    Convert two dimensional data structure into html table

    Args:
        data (`List[List]`, or `List[Dict]`):
            The data filled into table. If a list of dict is given, keys are used as column names.
        header (`Iterable[str]`):
            The name of columns defined by users.
    """
    tb_style = 'style="border-collapse: collapse;"'
    th_style = 'style="text-align: center; font-size: 130%; border: none;"'
    td_style = 'style="text-align: center; border-right: solid 1px #D3D3D3; border-left: solid 1px #D3D3D3;"'

    trs = []
    trs.append('
' + ' '.join(['' + x + '	' for x in header]) + '
')
    for r in data:
        trs.append('
' + ' '.join(['' + _to_html_cell(x) + '	' for x in r]) + '
')
    return '
' + ' '.join(trs) + '
'

def _to_html_cell(data):
    if isinstance(data, str):
        return _text_brief_repr(data)
    if isinstance(data, Image):
        return _image_to_html_cell(data)
    elif isinstance(data, numpy.ndarray):
        return _ndarray_brief_repr(data)
    elif isinstance(data, (list, tuple)):
        if all(isinstance(x, str) for x in data):
            return _texts_brief_repr(data)
        elif all(isinstance(x, Image) for x in data):
            return _images_to_html_cell(data)
        elif all(isinstance(x, numpy.ndarray) for x in data):
            return _ndarrays_brief_repr_(data)
    return _brief_repr(data)

def _ndarray_brief_repr(array, maxlen=3):
    head_vals = [repr(v) for i, v in enumerate(array.flatten()) if i < maxlen]
    if len(array.flatten()) >= maxlen:
        head_vals.append('...')
    shape = 'shape=' + repr(array.shape)

    return '[' + ', '.join(head_vals) + '] ' + shape

def _ndarrays_brief_repr_(arrays, maxlen=3):
    return '[' + ', '.join([_ndarray_brief_repr(x, maxlen) for x in arrays]) + ']'

def _image_to_html_cell(img, width=128, height=128):
    # pylint: disable=import-outside-toplevel
    from towhee.utils.cv2_utils import cv2
    import base64

    _, img_encode = cv2.imencode('.JPEG', img)
    src = 'src="data:image/jpeg;base64,' + base64.b64encode(img_encode).decode() + '" '
    w = 'width = "' + str(width) + '" '
    h = 'height = "' + str(height) + '" '

    return ''

def _images_to_html_cell(imgs, width=128, height=128):
    return ' '.join([_image_to_html_cell(x, width, height) for x in imgs])

def _images_brief_repr(imgs):
    return '[' + ', '.join([_image_brief_repr(x) for x in imgs]) + ']'

def _image_brief_repr(img):
    return _ndarray_brief_repr(img) + ' mode=' + img.mode

def _text_brief_repr(text, maxlen=32):
    if len(text) > maxlen:
        return text[:maxlen] + '...'
    else:
        return text

def _texts_brief_repr(texts, maxlen=32):
    return '[' + ', '.join([_text_brief_repr(x, maxlen) for x in texts]) + ']'

def _brief_repr(data, maxlen=128):
    s = repr(data)
    return s[:maxlen] + '...' if len(s) > maxlen else s


#!/usr/bin/env python3

import argparse
import random
import time

import signal
import RPi.GPIO as GPIO
import os
import subprocess
from PIL import Image, ImageDraw , ImageFont
from ST7789 import ST7789

from pythonosc import udp_client

class PyGranule:
    def __init__(self):
        self.parser = argparse.ArgumentParser()
        self.parser.add_argument("--ip", default="127.0.0.1",help="The ip of the OSC server")
        self.parser.add_argument("--port", type=int, default=2112,help="The port the OSC server is listening on")
        self.args = self.parser.parse_args()
        self.client = udp_client.SimpleUDPClient(self.args.ip, self.args.port)
        self.hostfound = False

        SPI_SPEED_MHZ = 80

        self.image = Image.new("RGB", (240, 240), (0, 0, 0))
        self.draw = ImageDraw.Draw(self.image)
        # font = ImageFont.load("arial.pil")

        self.st7789 = ST7789(
            rotation=90,  # Needed to display the right way up on Pirate Audio
            port=0,       # SPI port
            cs=1,         # SPI port Chip-select channel
            dc=9,         # BCM pin used for data/command
            backlight=13,
            spi_speed_hz=SPI_SPEED_MHZ * 1000 * 1000
        )

        self.st7789.display(self.image)

        # The buttons on Pirate Audio are connected to pins 5, 6, 16 and 24
        # Boards prior to 23 January 2020 used 5, 6, 16 and 20
        # try changing 24 to 20 if your Y button doesn't work.
        self.BUTTONS = [5, 6, 16, 24]

        # These correspond to buttons A, B, X and Y respectively
        self.LABELS = ['Test Sound', 'B', 'X', 'Y']

        # Set up RPi.GPIO with the "BCM" numbering scheme
        GPIO.setmode(GPIO.BCM)

        # Buttons connect to ground when pressed, so we should set them up
        # with a "PULL UP", which weakly pulls the input signal to 3.3V.
        GPIO.setup(self.BUTTONS, GPIO.IN, pull_up_down=GPIO.PUD_UP)

        self.process = subprocess.Popen(['./PiGranuleEngine', ' --files TestSounds'],
                           stdout=subprocess.PIPE,
                           universal_newlines=True)

    def update(self):
        self.st7789.display(self.image)
    def playtest(self):
        self.client.send_message("/playtest",0)
    def search(self):
        self.client.send_message("/searchforhost",0)
    def run(self):
        output = self.process.stdout.readline()
        t = output.strip()
        self.image = Image.new("RGB", (240, 240), (0, 0, 0))
        self.draw = ImageDraw.Draw(self.image)
        # font = ImageFont.load("arial.pil")
        print("engine" +t)
        self.draw.text((10, 230),t)
        self.draw.text((100,100),"hello")
        self.update()
        # Do something else
        self.return_code = self.process.poll()
        if self.return_code is not None:
            print('RETURN CODE', self.return_code)
            # Process has finished, read rest of the output
        for output in self.process.stdout.readlines():
            t = output.strip()
            print(t)
            self.draw.text((10, 230),t)
            self.update()
            return

engine = PyGranule()

# "handle_button" will be called every time a button is pressed
# It receives one argument: the associated input pin.
def handle_button(pin):
    if pin == 5 :
        engine.playtest()
    if pin == 16:
        engine.search()

# Loop through out buttons and attach the "handle_button" function to each
# We're watching the "FALLING" edge (transition from 3.3V to Ground) and
# picking a generous bouncetime of 100ms to smooth out button presses.
for pin in engine.BUTTONS:
    GPIO.add_event_detect(pin, GPIO.FALLING, handle_button, bouncetime=100)

while True:
    engine.run()


# coding: utf-8

# # Simple Reinforcement Learning in Tensorflow Part 2: Policy Gradient Method
# This tutorial contains a simple example of how to build a policy-gradient based agent that can solve the CartPole problem. For more information, see this [Medium post](https://medium.com/@awjuliani/super-simple-reinforcement-learning-tutorial-part-2-ded33892c724#.mtwpvfi8b).
#
# For more Reinforcement Learning algorithms, including DQN and Model-based learning in Tensorflow, see my Github repo, [DeepRL-Agents](https://github.com/awjuliani/DeepRL-Agents).
#
# Parts of this tutorial are based on code by [Andrej Karpathy](https://gist.github.com/karpathy/a4166c7fe253700972fcbc77e4ea32c5) and [korymath](https://gym.openai.com/evaluations/eval_a0aVJrGSyW892vBM04HQA).

# In[10]:

import numpy as np
import pickle
import tensorflow as tf
import matplotlib.pyplot as plt
import math

# ### Loading the CartPole Environment
# If you don't already have the OpenAI gym installed, use  `pip install gym` to grab it.

# In[11]:

import gym
env = gym.make('CartPole-v0')

# What happens if we try running the environment with random actions? How well do we do? (Hint: not so well.)

# In[12]:

# env.reset()
# random_episodes = 0
# reward_sum = 0
# while random_episodes < 10:
#     env.render()
#     observation, reward, done, _ = env.step(np.random.randint(0,2))
#     reward_sum += reward
#     if done:
#         random_episodes += 1
#         print("Reward for this episode was:",reward_sum)
#         reward_sum = 0
#         env.reset()

# env.render(close=True)

# The goal of the task is to achieve a reward of 200 per episode. For every step the agent keeps the pole in the air, the agent recieves a +1 reward. By randomly choosing actions, our reward for each episode is only a couple dozen. Let's make that better with RL!

# ### Setting up our Neural Network agent
# This time we will be using a Policy neural network that takes observations, passes them through a single hidden layer, and then produces a probability of choosing a left/right movement. To learn more about this network, see [Andrej Karpathy's blog on Policy Gradient networks](http://karpathy.github.io/2016/05/31/rl/).

# In[13]:

# hyperparameters
H = 10 # number of hidden layer neurons
batch_size = 5 # every how many episodes to do a param update?
learning_rate = 1e-2 # feel free to play with this to train faster or more stably.
gamma = 0.99 # discount factor for reward

D = 4 # input dimensionality

# In[14]:

tf.reset_default_graph()

#This defines the network as it goes from taking an observation of the environment to
#giving a probability of chosing to the action of moving left or right.
observations = tf.placeholder(tf.float32, [None,D] , name="input_x")
W1 = tf.get_variable("W1", shape=[D, H],
           initializer=tf.contrib.layers.xavier_initializer())
layer1 = tf.nn.relu(tf.matmul(observations,W1))
W2 = tf.get_variable("W2", shape=[H, 1],
           initializer=tf.contrib.layers.xavier_initializer())
score = tf.matmul(layer1,W2)
probability = tf.nn.sigmoid(score)

#From here we define the parts of the network needed for learning a good policy.
tvars = tf.trainable_variables()
input_y = tf.placeholder(tf.float32,[None,1], name="input_y")
advantages = tf.placeholder(tf.float32,name="reward_signal")

# The loss function. This sends the weights in the direction of making actions
# that gave good advantage (reward over time) more likely, and actions that didn't less likely.
loglik = tf.log(input_y*(input_y - probability) + (1 - input_y)*(input_y + probability))
loss = -tf.reduce_mean(loglik * advantages)
newGrads = tf.gradients(loss,tvars)

# Once we have collected a series of gradients from multiple episodes, we apply them.
# We don't just apply gradeients after every episode in order to account for noise in the reward signal.
adam = tf.train.AdamOptimizer(learning_rate=learning_rate) # Our optimizer
W1Grad = tf.placeholder(tf.float32,name="batch_grad1") # Placeholders to send the final gradients through when we update.
W2Grad = tf.placeholder(tf.float32,name="batch_grad2")
batchGrad = [W1Grad,W2Grad]
updateGrads = adam.apply_gradients(zip(batchGrad,tvars))

# ### Advantage function
# This function allows us to weigh the rewards our agent recieves. In the context of the Cart-Pole task, we want actions that kept the pole in the air a long time to have a large reward, and actions that contributed to the pole falling to have a decreased or negative reward. We do this by weighing the rewards from the end of the episode, with actions at the end being seen as negative, since they likely contributed to the pole falling, and the episode ending. Likewise, early actions are seen as more positive, since they weren't responsible for the pole falling.

# In[15]:

def discount_rewards(r):
    """ take 1D float array of rewards and compute discounted reward """
    discounted_r = np.zeros_like(r)
    running_add = 0
    for t in reversed(range(0, r.size)):
        running_add = running_add * gamma + r[t]
        discounted_r[t] = running_add
    return discounted_r

# ### Running the Agent and Environment

# Here we run the neural network agent, and have it act in the CartPole environment.

# In[16]:

xs,hs,dlogps,drs,ys,tfps = [],[],[],[],[],[]
running_reward = None
reward_sum = 0
episode_number = 1
total_episodes = 10000
init = tf.initialize_all_variables()

# Launch the graph
try:
    with tf.Session() as sess:
        rendering = False
        sess.run(init)
        observation = env.reset() # Obtain an initial observation of the environment

        # Reset the gradient placeholder. We will collect gradients in
        # gradBuffer until we are ready to update our policy network.
        gradBuffer = sess.run(tvars)
        for ix,grad in enumerate(gradBuffer):
            gradBuffer[ix] = grad * 0

        while episode_number <= total_episodes:

            # Rendering the environment slows things down,
            # so let's only look at it once our agent is doing a good job.
            if reward_sum/batch_size > 100 or rendering == True :
                env.render()
                rendering = True

            # Make sure the observation is in a shape the network can handle.
            x = np.reshape(observation,[1,D])

            # Run the policy network and get an action to take.
            tfprob = sess.run(probability,feed_dict={observations: x})
            action = 1 if np.random.uniform() < tfprob else 0

            xs.append(x) # observation
            y = 1 if action == 0 else 0 # a "fake label"
            ys.append(y)

            # step the environment and get new measurements
            observation, reward, done, info = env.step(action)
            reward_sum += reward

            drs.append(reward) # record reward (has to be done after we call step() to get reward for previous action)

            if done:
                episode_number += 1
                # stack together all inputs, hidden states, action gradients, and rewards for this episode
                epx = np.vstack(xs)
                epy = np.vstack(ys)
                epr = np.vstack(drs)
                tfp = tfps
                xs,hs,dlogps,drs,ys,tfps = [],[],[],[],[],[] # reset array memory

                # compute the discounted reward backwards through time
                # print(discount_rewards(epr))
                discounted_epr = discount_rewards(epr)
                # size the rewards to be unit normal (helps control the gradient estimator variance)
                discounted_epr -= np.mean(discounted_epr)
                discounted_epr /= np.std(discounted_epr)

                # Get the gradient for this episode, and save it in the gradBuffer
                tGrad = sess.run(newGrads,feed_dict={observations: epx, input_y: epy, advantages: discounted_epr})
                for ix,grad in enumerate(tGrad):
                    gradBuffer[ix] += grad

                # If we have completed enough episodes, then update the policy network with our gradients.
                if episode_number % batch_size == 0:
                    sess.run(updateGrads,feed_dict={W1Grad: gradBuffer[0],W2Grad:gradBuffer[1]})
                    for ix,grad in enumerate(gradBuffer):
                        gradBuffer[ix] = grad * 0

                    # Give a summary of how well our network is doing for each batch of episodes.
                    running_reward = reward_sum if running_reward is None else running_reward * 0.99 + reward_sum * 0.01
                    print('Average reward for episode %f.  Total average reward %f.' % (reward_sum/batch_size, running_reward/batch_size))

                    if reward_sum/batch_size > 200:
                        print("Task solved in",episode_number,'episodes!')
                        break

                    reward_sum = 0

                observation = env.reset()
except KeyboardInterrupt:
    pass
finally:
    env.render(close=True)
    print(episode_number,'Episodes completed.')

# As you can see, the network not only does much better than random actions, but achieves the goal of 200 points per episode, thus solving the task!


import logging

from django.core.mail import EmailMultiAlternatives, EmailMessage
from django.core.urlresolvers import reverse
from django.conf import settings
from django.utils.encoding import smart_text

from wildlifelicensing.apps.emails.emails import TemplateEmailBase, host_reverse, pdf_host_reverse
from wildlifelicensing.apps.applications.models import ApplicationLogEntry, IDRequest, ReturnsRequest, AmendmentRequest

SYSTEM_NAME = 'Wildlife Licensing Automated Message'
MAX_SUBJECT_LENGTH = 76

logger = logging.getLogger(__name__)

def _format_application_email_subject(subject, application):
    subject = subject.format(application.reference, application.applicant.get_full_name())

    # subject can be no longer than MAX_SUBJECT_LENGTH
    if len(subject) > MAX_SUBJECT_LENGTH:
        subject = '{}..'.format(subject[:MAX_SUBJECT_LENGTH - 2])

    return subject

class ApplicationAmendmentRequestedEmail(TemplateEmailBase):
    subject = 'An amendment to your wildlife licensing application is required.'
    html_template = 'wl/emails/application_amendment_requested.html'
    txt_template = 'wl/emails/application_amendment_requested.txt'

def send_amendment_requested_email(amendment_request, request):
    application = amendment_request.application
    email = ApplicationAmendmentRequestedEmail()
    url = pdf_host_reverse('wl_applications:edit_application', args=[application.pk])

    context = {
        'amendment_request': amendment_request,
        'url': url
    }

    if amendment_request.reason:
        context['reason'] = dict(AmendmentRequest.REASON_CHOICES)[amendment_request.reason]

    if application.proxy_applicant is None:
        recipient_email = application.applicant_profile.email
    else:
        recipient_email = application.proxy_applicant.email

    msg = email.send(recipient_email, context=context)
    _log_email(msg, application=application, sender=request.user)

class ApplicationAssessmentRequestedEmail(TemplateEmailBase):
    subject = 'Wildlife licensing [{} {}]: assessment required'
    html_template = 'wl/emails/application_assessment_requested.html'
    txt_template = 'wl/emails/application_assessment_requested.txt'

    def __init__(self, application):
        self.subject = _format_application_email_subject(self.subject, application)

def send_assessment_requested_email(assessment, request):
    application = assessment.application

    email = ApplicationAssessmentRequestedEmail(application)
    url = request.build_absolute_uri(
        reverse('wl_applications:enter_conditions_assessor',
                args=[application.pk, assessment.pk])
    )
    context = {
        'url': url
    }
    msg = email.send(assessment.assessor_group.email, context=context)

    _log_email(msg, application=application, sender=request.user)

class ApplicationAssessmentAssignedEmail(TemplateEmailBase):
    subject = 'Wildlife licensing [{} {}]: assessment assigned.'
    html_template = 'wl/emails/application_assessment_assigned.html'
    txt_template = 'wl/emails/application_assessment_assigned.txt'

    def __init__(self, application):
        self.subject = _format_application_email_subject(self.subject, application)

def send_assessment_assigned_email(assessment, request):
    application = assessment.application
    assigned_assessor = assessment.assigned_assessor
    if assigned_assessor is not None and assigned_assessor.email:
        recipient = assigned_assessor.email
        email = ApplicationAssessmentAssignedEmail(application)
        url = request.build_absolute_uri(
            reverse('wl_applications:enter_conditions_assessor',
                    args=[application.pk, assessment.pk])
        )
        context = {
            'url': url
        }
        msg = email.send(recipient, context=context)

        _log_email(msg, application=application, sender=request.user)

class ApplicationAssessmentReminderEmail(TemplateEmailBase):
    subject = 'Wildlife licensing [{} {}]: Reminder - assessment required'
    html_template = 'wl/emails/application_assessment_reminder.html'
    txt_template = 'wl/emails/application_assessment_reminder.txt'

    def __init__(self, application):
        self.subject = _format_application_email_subject(self.subject, application)

def send_assessment_reminder_email(assessment, request=None):
    application = assessment.application

    email = ApplicationAssessmentReminderEmail(application)
    if request is not None:
        url = request.build_absolute_uri(
            reverse('wl_applications:enter_conditions_assessor',
                    args=(application.pk, assessment.pk))
        )
    else:
        url = host_reverse('wl_applications:enter_conditions_assessor', args=(application.pk, assessment.pk))

    context = {
        'assessor': assessment.assessor_group,
        'url': url
    }

    msg = email.send(assessment.assessor_group.email, context=context)
    sender = request.user if request is not None else None
    _log_email(msg, application=application, sender=sender)

class ApplicationAssessmentDoneEmail(TemplateEmailBase):
    subject = 'Wildlife licensing [{} {}]: assessment complete'
    html_template = 'wl/emails/application_assessment_done.html'
    txt_template = 'wl/emails/application_assessment_done.txt'

    def __init__(self, application):
        self.subject = _format_application_email_subject(self.subject, application)

def send_assessment_done_email(assessment, request):
    application = assessment.application

    email = ApplicationAssessmentDoneEmail(application)
    url = request.build_absolute_uri(
        reverse('wl_applications:enter_conditions',
                args=[application.pk])
    )
    context = {
        'assessor': request.user,
        'assessor_group': assessment.assessor_group,
        'url': url
    }
    to_email = application.assigned_officer.email if application.assigned_officer else \
        settings.EMAIL_FROM
    msg = email.send(to_email, context=context)
    _log_email(msg, application=application, sender=request.user)

class ApplicationIDUpdateRequestedEmail(TemplateEmailBase):
    subject = 'An ID update for a wildlife licensing application is required.'
    html_template = 'wl/emails/application_id_request.html'
    txt_template = 'wl/emails/application_id_request.txt'

def send_id_update_request_email(id_request, request):
    application = id_request.application
    email = ApplicationIDUpdateRequestedEmail()
    url = pdf_host_reverse('wl_main:identification')

    if id_request.reason:
        id_request.reason = dict(IDRequest.REASON_CHOICES)[id_request.reason]

    context = {
        'id_request': id_request,
        'url': url
    }

    if application.proxy_applicant is None:
        recipient_email = application.applicant_profile.email
    else:
        recipient_email = application.proxy_applicant.email

    msg = email.send(recipient_email, context=context)
    _log_email(msg, application=application, sender=request.user)

class ApplicationReturnsRequestedEmail(TemplateEmailBase):
    subject = 'Completion of returns for a wildlife licensing application is required.'
    html_template = 'wl/emails/application_returns_request.html'
    txt_template = 'wl/emails/application_returns_request.txt'

def send_returns_request_email(returns_request, request):
    application = returns_request.application
    email = ApplicationReturnsRequestedEmail()
    url = pdf_host_reverse('wl_dashboard:home')

    if returns_request.reason:
        returns_request.reason = dict(ReturnsRequest.REASON_CHOICES)[returns_request.reason]

    context = {
        'url': url,
        'returns_request': returns_request
    }

    if application.proxy_applicant is None:
        recipient_email = application.applicant_profile.email
    else:
        recipient_email = application.proxy_applicant.email

    msg = email.send(recipient_email, context=context)
    _log_email(msg, application=application, sender=request.user)

class LicenceIssuedEmail(TemplateEmailBase):
    subject = 'Your wildlife licensing licence has been issued.'
    html_template = 'wl/emails/licence_issued.html'
    txt_template = 'wl/emails/licence_issued.txt'

def send_licence_issued_email(licence, application, request, to=None, cc=None, bcc=None, additional_attachments=None):
    email = LicenceIssuedEmail()
    url = request.build_absolute_uri(
        reverse('wl_dashboard:home')
    )
    context = {
        'url': url,
        'licence': licence
    }
    if licence.licence_document is not None:
        file_name = 'WL_licence_' + smart_text(licence.licence_type.product_title)
        if licence.licence_number:
            file_name += '_' + smart_text(licence.licence_number)
        if licence.licence_sequence:
            file_name += '-' + smart_text(licence.licence_sequence)
        elif licence.start_date:
            file_name += '_' + smart_text(licence.start_date)
        file_name += '.pdf'
        attachment = (file_name, licence.licence_document.file.read(), 'application/pdf')
        attachments = [attachment]
    else:
        logger.error('The licence pk=' + licence.pk + ' has no document associated with it.')
        attachments = []
    if not to:
        to = [licence.profile.email]
    if additional_attachments and not isinstance(additional_attachments, list):
        additional_attachments = list(additional_attachments)

    other_attachments = []
    pdf_attachments = []
    if additional_attachments:
        for a in additional_attachments:
            if a.file.name.endswith('.pdf'):
                pdf_attachments.append(a)
            else:
                other_attachments.append(a)
        attachments += other_attachments
    msg = email.send(to, context=context, attachments=attachments, cc=cc, bcc=bcc)
    log_entry = _log_email(msg, application=application, sender=request.user)
    if licence.licence_document is not None:
        log_entry.documents.add(licence.licence_document)
    if additional_attachments:
        log_entry.documents.add(*other_attachments)
    return log_entry

class UserNameChangeNotificationEmail(TemplateEmailBase):
    subject = 'User has changed name and requires licence reissue.'
    html_template = 'wl/emails/user_name_change_notification.html'
    txt_template = 'wl/emails/user_name_change_notification.txt'

def send_user_name_change_notification_email(licence):
    email = UserNameChangeNotificationEmail()

    url = host_reverse('wl_applications:reissue_licence', args=(licence.pk,))

    context = {
        'licence': licence,
        'url': url
    }
    email.send(licence.issuer.email, context=context)

class ApplicationDeclinedEmail(TemplateEmailBase):
    subject = 'Wildlife licensing [{} {}]: application declined'
    html_template = 'wl/emails/application_declined.html'
    txt_template = 'wl/emails/application_declined.txt'

    def __init__(self, application):
        self.subject = _format_application_email_subject(self.subject, application)

def send_application_declined_email(declined_details, request):
    application = declined_details.application
    email = ApplicationDeclinedEmail(application)
    url = request.build_absolute_uri(reverse('wl_home')) if request else None

    reason_text = declined_details.reason or ''
    reason_html = reason_text.replace('\n', '<br/>')

    context = {
        'reason_text': reason_text,
        'reason_html': reason_html,
        'wl_home': url
    }

    if application.proxy_applicant is None:
        recipient_email = application.applicant_profile.email
    else:
        recipient_email = application.proxy_applicant.email

    msg = email.send(recipient_email, context=context)
    sender = request.user if request else settings.EMAIL_FROM
    _log_email(msg, application=application, sender=sender)
    return recipient_email

def _log_email(email_message, application, sender=None):
    if isinstance(email_message, (EmailMultiAlternatives, EmailMessage,)):
        # TODO this will log the plain text body, should we log the html instead
        text = email_message.body
        subject = email_message.subject
        fromm = smart_text(sender) if sender else smart_text(email_message.from_email)
        # the to email is normally a list
        if isinstance(email_message.to, list):
            to = ','.join(email_message.to)
        else:
            to = smart_text(email_message.to)
        # we log the cc and bcc in the same cc field of the log entry as a ',' comma separated string
        all_ccs = []
        if email_message.cc:
            all_ccs += list(email_message.cc)
        if email_message.bcc:
            all_ccs += list(email_message.bcc)
        all_ccs = ','.join(all_ccs)

    else:
        text = smart_text(email_message)
        subject = ''
        to = application.applicant.email
        fromm = smart_text(sender) if sender else SYSTEM_NAME
        all_ccs = ''

    customer = application.applicant

    staff = sender

    kwargs = {
        'subject': subject,
        'text': text,
        'application': application,
        'customer': customer,
        'staff': staff,
        'to': to,
        'fromm': fromm,
        'cc': all_ccs
    }

    email_entry = ApplicationLogEntry.objects.create(**kwargs)

    return email_entry


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

import sqlite3
import random
import datetime
import pytz
import logging
from util import utc_time_to_russian
logger = logging.getLogger('parasite_logger')

def parse_schedule_entry(entry):
    entry = list(entry)
    entry[2] = entry[2].split(',')
    return entry

class Keeper():
    def __init__(self, timezone, prefix = "default"):
        self.prefix = prefix
        self.connection = sqlite3.connect(self.prefix+'_pics.db', detect_types=sqlite3.PARSE_DECLTYPES|sqlite3.PARSE_COLNAMES)
        self.cursor = self.connection.cursor()
        self.init_schema()
        self.timezone = timezone

    def init_schema(self):
        self.cursor.execute('''CREATE TABLE IF NOT EXISTS '''+self.prefix+'''_images(id INTEGER  PRIMARY KEY, date timestamp, link text UNIQUE, path text UNIQUE, posted INTEGER)''')

        self.cursor.execute('''CREATE TABLE IF NOT EXISTS '''+self.prefix+'''_schedule(id INTEGER  PRIMARY KEY, date timestamp, image_ids text, post_type text)''')

        self.connection.commit()

    def add_image(self, values):
        # Insert a row of data
        self.cursor.executemany("INSERT INTO "+self.prefix+"_images VALUES (?, ?, ?, ?, 0)", values)
        self.connection.commit()

    def get_image(self, img_id):
        logger.debug('Getting img')
        return self.cursor.execute('select * from '+self.prefix+'_images WHERE id = '+str(img_id)).fetchone()

    def get_last_image(self):
        return self.cursor.execute('select * from '+self.prefix+'_images').fetchone()

    def dump_schedule(self):
        logger.debug('Dumping schedule')
        #schedule = self.cursor.execute('select * from '+self.prefix+'_schedule WHERE post_type = \'new\';').fetchmany()
        #for post in schedule:
        #    img_id = post[2]
        #    self.cursor.execute('UPDATE '+self.prefix+'_images SET posted = 0 WHERE  id = '+str(img_id)+';')

        self.cursor.execute('''DELETE FROM '''+self.prefix+'''_schedule;''')
        self.cursor.execute('''VACUUM;''')

        self.connection.commit()

    def delete_old_posts(self, amount):
        logger.debug('Deleting %d old posts', amount)

        paths = self.cursor.execute('''SELECT path FROM '''+self.prefix+'''_images WHERE posted = 1 ORDER BY id DESC LIMIT '''+str(amount)+''';''').fetchall()
        self.cursor.execute('''DELETE FROM '''+self.prefix+'''_images WHERE id IN (SELECT id FROM '''+self.prefix+'''_images WHERE posted = 1 ORDER BY id DESC LIMIT '''+str(amount)+''');''')
        self.connection.commit()
        logger.debug("Deleted old posts from db")
        #print(str(paths))
        return [path[0] for path in paths]

    def store_schedule(self, schedule):
        logger.debug('Storing schedule')
        values = list(schedule)
        for i in range(len(values)):
            values[i] = list(values[i])
            values[i][1] = ",".join([str(x) for x in values[i][1]])
        #print(values)
        self.cursor.executemany("INSERT INTO "+self.prefix+"_schedule VALUES (Null, ?, ?, ?)", values)
        self.connection.commit()

    def remove_from_schedule(self, post):
        logger.debug('Deleting from schedule')
        post_id = post[0]
        self.cursor.execute('''DELETE FROM '''+self.prefix+'''_schedule WHERE id = '''+str(post_id))
        self.connection.commit()

    def get_upcoming_post(self):
        sql = 'select * from '+self.prefix+'_schedule WHERE datetime(date) > datetime(\''+utc_time_to_russian(datetime.datetime.utcnow()).strftime("%Y-%m-%d %H:%M:%S")+'\') ORDER BY datetime(date)  ASC LIMIT 1 ;'
        logger.debug('SQL: %s', sql)

        post = self.cursor.execute(sql).fetchone()
        if not post:
            raise(Exception("No upcoming post"))
        logger.debug('Fetched upcoming post: %s', str(post) )
        return parse_schedule_entry(post)

    def get_pool(self, post_type):
        logger.debug('Getting pools')
        if post_type == "new":
            return self.cursor.execute('select * from '+self.prefix+'_images where posted = 0').fetchall()
        else:
            return self.cursor.execute('select * from '+self.prefix+'_images where posted = 1').fetchall()

    def set_posted(self, imgs):
        logger.debug('Setting posted')
        for img in imgs:
            img_id = img[0]
            self.cursor.execute('UPDATE '+self.prefix+'_images SET posted = 1 WHERE  id = '+str(img[0])+';')
        self.connection.commit()

    def clean_up(self):
        self.connection.close()


import datetime
import logging
import re
import shlex
import subprocess
import sys
import time
from argparse import ArgumentParser
from cmd import Cmd
from collections import OrderedDict
from random import choice
from subprocess import PIPE, SubprocessError

from colorama import Style
from veryprettytable import VeryPrettyTable

from attacks import implemented_attacks, AttackException
from attacks.printer import ConsolePrinter

class LogDict(OrderedDict):
    def __init__(*args, **kwds):
        OrderedDict.__init__(*args, **kwds)
        self, *args = args
        # event key should always be present and the first key to log
        self.setdefault("event", "unknown_event")
        self.move_to_end("event", last=False)

    def __str__(self):
        return "[{kv}]".format(
            kv=" ".join("{}=\"{}\"".format(key, value) for key, value in self.items()))

class LogDictLoggerAdapter(logging.LoggerAdapter):
    def process(self, msg, kwargs):
        msg, kwargs = super().process(msg, kwargs)
        kwargs["extra"] = kwargs["extra"].copy()
        try:
            kwargs["extra"]["log_dict"] = kwargs.pop("log_dict")
        except KeyError:
            kwargs["extra"]["log_dict"] = LogDict()
        return msg, kwargs

class ISOFormatter(logging.Formatter):
    _tz_fix = re.compile(r"([+-]\d{2})(\d{2})$")

    def format(self, record):
        self._add_isotime_to_record(record)
        return super().format(record)

    @classmethod
    def _add_isotime_to_record(cls, record):
        isotime = datetime.datetime.fromtimestamp(record.created).isoformat()
        tz = cls._tz_fix.match(time.strftime("%z"))
        if time.timezone and tz:
            offset_hrs, offset_min = tz.groups()
            isotime += f"{offset_hrs}:{offset_min}"
        else:
            isotime += "Z"
        record.__dict__["isotime"] = isotime

logger = LogDictLoggerAdapter(logging.getLogger("tbfconsole"), extra={})

def setup_logging(level, log_file=None, log_to_console=False):
    original_logger = logger.logger  # type: logging.Logger
    original_logger.setLevel(level)
    if log_file:
        handler = logging.FileHandler(filename=log_file)
        fmt = "%(isotime)s %(name)s %(levelname)s %(log_dict)s %(message)s"
        handler.setFormatter(fmt=ISOFormatter(fmt=fmt))
        original_logger.addHandler(hdlr=handler)
    if log_to_console:
        handler = logging.StreamHandler()
        fmt = "[%(levelname)s] %(log_dict)s %(message)s"
        handler.setFormatter(fmt=ISOFormatter(fmt=fmt))
        original_logger.addHandler(hdlr=handler)

class SubAttackConsole(Cmd):
    logger = logger

    def __init__(self, attack_class, **kwargs):
        super().__init__(**kwargs)
        log_dict = LogDict(event="start_attack_console", attack=attack_class.info.name)
        self.logger.debug("Start SubAttackConsole", log_dict=log_dict)
        self.attack_class = attack_class
        self.options_class = self.attack_class.options_class
        self.attack_options = self.options_class._options()
        self.attack_option_descriptions = {
            option: self.options_class.__dict__[option]
            for option in self.attack_options}
        self.attack = self.attack_class(printer=ConsolePrinter())
        self.prompt = f"attackconsole ({self.attack_class.info.name}) > "

    def precmd(self, line):
        if not self._stdin_is_a_tty():
            print(line)
        return super().precmd(line)

    def do_info(self, arg):
        print(self._headline("Attack Info"))
        v = VeryPrettyTable()
        v.align = "l"
        v.field_names = ["Name", "Description"]
        v.add_row([self.attack_class.info.name, self.attack_class.info.description])
        print(v)

    def do_options(self, arg):
        print(self._headline("Attack Options"))
        v = VeryPrettyTable()
        v.align = "l"
        v.field_names = ["Name", "Current Setting", "Description"]
        for option in self.attack_options:
            current_setting = str(self.attack.options.__getattribute__(option))
            description = self.attack_option_descriptions[option]
            v.add_row([option, current_setting, description])
        print(v)

    def do_set(self, arg):
        if len(shlex.split(arg)) == 2:
            option, value = shlex.split(arg)[:2]
            if option in self.attack_option_descriptions.keys():
                self.attack.options.__setattr__(option, value)
            else:
                print(f"*** Unknown option: {option}")
        else:
            print("*** Invalid number of option arguments\n*** Usage: set <option> <value>")

    def complete_set(self, text, line, begidx, endidx):
        opt = line.split(" ")[1].strip()
        if opt in self.attack_option_descriptions.keys():
            return [
                option
                for option in self.attack.options.__getattribute__(f"{opt}_choices")
                if option.startswith(text)
            ]
        return [option + " " for option in self.attack_option_descriptions.keys() if
                option.startswith(text)]

    def do_reset(self, _arg):
        self.attack.options._set_options_to_none()
        self.attack.options._set_defaults()

    def do_run(self, arg):
        attack_name = self.attack.info.name
        log_dict = LogDict(event="run_attack", attack=attack_name)
        log_dict.update(sorted(self.attack.options.__dict__.items()))
        self.logger.info("Run attack", log_dict=log_dict)
        try:
            self.attack.run()
        except AttackException as e:
            print(f"*** Exception: {e}")
            log_dict.update(event="attack_failed", failed_with=str(e).replace("\n", " "))
            self.logger.info("Attack failed", log_dict=log_dict)
        except KeyboardInterrupt:
            self.attack.handle_keyboard_interrupt()
        else:
            log_dict.update(event="attack_succeeded")
            self.logger.info("Attack succeeded", log_dict=log_dict)

    def do_back(self, arg):
        log_dict = LogDict(event="exit_attack_console", attack=self.attack_class.info.name)
        self.logger.debug("Exit SubAttackConsole", log_dict=log_dict)
        return True

    def do_EOF(self, arg):
        return self.do_back(arg)

    def _headline(self, h):
        return "{}{}{}{}{}".format("\n", Style.DIM, h, "\n==================\n", Style.RESET_ALL)

    def _stdin_is_a_tty(self):
        return sys.stdin.isatty()

class AttackConsole(Cmd):
    prompt = "attackconsole > "
    sub_attack_console_class = SubAttackConsole
    attack_classes = {attack_class.info.name: attack_class for attack_class in implemented_attacks}
    logger = logger

    def __init__(self, **kwargs):
        super().__init__(**kwargs)
        self.kwargs = kwargs
        log_dict = LogDict(event="start_tbf_console", attacks=",".join(self.attack_classes.keys()))
        self.logger.info("Start Console", log_dict=log_dict)

    def precmd(self, line):
        if not self._stdin_is_a_tty():
            print(line)
        return super().precmd(line)

    def do_ls(self, arg):
        print(self._headline("Attacks"))
        v = VeryPrettyTable()
        v.field_names = ["Name", "Description"]
        v.align["Name"] = "l"
        for attack_class in self.attack_classes.values():
            v.add_row([attack_class.info.name, attack_class.info.description])
        print(v.get_string(sortby="Name"))

    def do_use(self, arg):
        attack = arg
        if attack in self.attack_classes.keys():
            sub_attack_console = self.sub_attack_console_class(
                attack_class=self.attack_classes[attack], **self.kwargs)
            sub_attack_console.cmdloop()
        else:
            print(f"*** Unknown attack: {attack}")

    def complete_use(self, text, line, begidx, endidx):
        return [attack for attack in self.attack_classes.keys() if attack.startswith(text)]

    def do_sleep(self, arg):
        self.sleep(int(arg))

    def do_exit(self, arg):
        self.logger.info("Exit Console", log_dict=LogDict(event="exit_tbf_console"))
        return True

    def do_EOF(self, arg):
        return self.do_exit(arg)

    def _headline(self, h):
        return "{}{}{}{}{}".format("\n", Style.DIM, h, "\n==================\n", Style.RESET_ALL)

    def _stdin_is_a_tty(self):
        return sys.stdin.isatty()

    @staticmethod
    def sleep(secs):
        time.sleep(secs)

class IntroGenerator:
    default_fortune = ""

    def generate(self):
        fortune = self.wrap_in_cowsay(self.generate_fortune())
        intro = "\n".join([
            fortune,
            "+ -- - -= [\t BREACH Attack Console \t\t]",
            f"+ -- - -= [\t {len(implemented_attacks)} attack(s)          \t\t]",
            ""])
        return intro

    def generate_fortune(self):
        try:
            fortune = self.execute(["fortune", "-s"])
        except (SubprocessError, FileNotFoundError):
            logger.debug("No fortune found")
            return self.default_fortune
        else:
            return fortune

    def wrap_in_cowsay(self, msg):
        inappropriate_cows = ["head-in", "kiss", "sodomized", "telebears", "sodomized-sheep"]
        try:
            cows_list = self.execute(["cowsay", "-l"])
            cows = cows_list.split("\n", maxsplit=1)[1].split()
            good_cows = [c for c in cows if c not in inappropriate_cows]
            wrapped_msg = self.execute(["cowsay", "-f", choice(good_cows), msg])
        except (SubprocessError, FileNotFoundError):
            logger.debug("Could not wrap message in cowsay")
            return msg
        else:
            return wrapped_msg

    @staticmethod
    def execute(cmd_vector):
        return subprocess.run(cmd_vector, universal_newlines=True, stdout=PIPE).stdout

def parse_args(argv=None):
    parser = ArgumentParser(description="The AttackConsole")
    parser.add_argument(
        "-v", "--verbose", dest="verbose", action="store_true", default=False,
        help="Increase output verbosity")
    parser.add_argument(
        "-l", "--log-file", dest="log_file", default=None,
        help="Write logs to a file instead of writing to console")
    return parser.parse_args(args=argv)

def main(argv=None):
    args = parse_args(argv=argv)
    setup_logging(level=logging.INFO, log_file=args.log_file, log_to_console=args.verbose)
    console = AttackConsole()
    try:
        console.cmdloop(intro=IntroGenerator().generate())
    except KeyboardInterrupt:
        print("\n*** Keyboard Interrupt, closing attackconsole.")
        console.do_exit(argv)

if __name__ == '__main__':
    main()


from datetime import date

from django.contrib.auth.models import AbstractUser
from django.db import models
from django.db.models import Q
from django.utils import timezone

from core.hashids import hashids
from core.textutils import get_hashtags

import uuid

class User(AbstractUser):
    api_token = models.UUIDField(unique=True, null=True)

    def generate_api_token(self, force=False):
        if not self.api_token or force:
            self.api_token = uuid.uuid4()

    def save(self, *args, **kwargs):
        self.generate_api_token()
        super().save(*args, **kwargs)

class TaskQuerySet(models.QuerySet):

    def with_hashid(self, hashid):
        ids = hashids.decode(hashid)
        # TODO add check -- if len is 0, hashid is invalid, should raise exception
        if len(ids) == 1:
            return self.get(pk=ids[0])
        return self.filter(pk__in=ids)

    def incomplete(self):
        return self.filter(completed_at__isnull=True)

    def complete(self):
        return self.filter(completed_at__isnull=False).order_by('completed_at')

    def current(self):
        return self.incomplete().filter(
            Q(show_on__isnull=True) | Q(show_on__lte=date.today()))

    def future(self):
        return self.incomplete().filter(
            show_on__isnull=False, show_on__gt=date.today())

class Task(models.Model):

    class Meta:
        base_manager_name = 'objects'

    objects = TaskQuerySet.as_manager()
    description = models.CharField("Task", max_length=512)
    owner = models.ForeignKey(
        User, on_delete=models.CASCADE, related_name='tasks')
    created_at = models.DateTimeField(null=True, auto_now_add=True)
    completed_at = models.DateTimeField(null=True, blank=True)
    due_on = models.DateField("Due by", null=True, blank=True)
    show_on = models.DateField(
        "Hide until",
        null=True,
        blank=True,
        help_text=
        "This task will not be shown under current tasks until this date.")

    @property
    def hashid(self):
        return hashids.encode(self.pk)

    def is_complete(self):
        return self.completed_at is not None

    def is_current(self):
        return not self.is_complete() and (self.show_on is None or
                                           self.show_on <= date.today())

    def is_future(self):
        return not self.is_complete() and (self.show_on is not None and
                                           self.show_on > date.today())

    def mark_complete(self, save=True):
        """
        Mark task as completed at current time.
        Saves completion to DB until `save` is set to False.
        """
        self.completed_at = timezone.now()
        if save:
            self.save()
        return self

    def mark_current(self, save=True):
        """
        Mark task as current by removing show_on.
        Saves completion to DB until `save` is set to False.
        """
        self.show_on = None
        if save:
            self.save()
        return self

    def save(self, *args, **kwargs):  # pylint: disable=arguments-differ
        super().save(*args, **kwargs)
        self.parse_tags()

    def parse_tags(self):
        """
        Read through the description of the task and pull out any tags.
        Create Tag model objects for these and associate them.
        """
        tags = []
        text_tags = get_hashtags(self.description)
        for tag_text in text_tags:
            tag, _ = Tag.objects.get_or_create(text=tag_text)
            tags.append(tag)
        self.tags.set(tags)

    def to_dict(self):
        return {
            "hashid": self.hashid,
            "owner": str(self.owner),
            "description": self.description,
            "due_on": self.due_on,
            "hide_until": self.show_on,
            "completed_at": self.completed_at,
            "complete": self.is_complete(),
            "future": self.is_future(),
            "current": self.is_current(),
        }

class Note(models.Model):
    task = models.ForeignKey(
        to=Task, related_name='notes', on_delete=models.CASCADE)
    text = models.TextField()
    created_at = models.DateTimeField(null=True, auto_now_add=True)

    def to_dict(self):
        return {"pk": self.pk, "text": self.text, "created_at": self.created_at}

class Tag(models.Model):
    """
    Represents a tag or "hashtag" -- a free-form category that we
    can add to tasks.

    - Tags should be case-insensitive

    """

    # This should be enforced to be unique in a case-insensitive fashion
    # but we are leaving it for now.
    text = models.CharField(
        max_length=100, unique=True, help_text="Tag text (must be lowercase)")
    tasks = models.ManyToManyField(to=Task, related_name="tags")