import util
import logging
import re
import codecs
import shutil
import glob
import os
import urllib
from sub_task import SubTask

class InvalidFileDirectory(Exception):
    """
    Raised when the the user tries to use a file or directory that we cannot find

    Attributes:
        message  --
    """

    def __init__(self, message):
        self.message = 'Cannot find the file/directory specified. ' + message

    def __str__(self):
        return repr(self.message)

class Task:
    """
       Task constructor

       :param task_config
    """

    def __init__(self, parent, task_config):
        self.id = util.short_unique_id()
        self.__parent = parent
        self.name = task_config.get('taskName')
        self.description = task_config.get('taskDescription')
        self.wd = task_config.get('workingDir')
        self.wait = task_config.get('wait')
        self.fail_tolerant = task_config.get('failTolerant')
        self.__preparation = task_config.get('preparation')
        self.__commands = task_config.get('commands')
        self.__children = []
        logging.debug('Task - Created [%s] with ID [%s].', str(self.name), str(self.id))
        logging.debug('Task - Description [%s].', str(self.description))
        children_config = task_config.get('children')
        if children_config:
            for config in children_config:
                self.__children.append(Task(self, config))
        self.sub_tasks = []

    def get_sub_tasks(self):
        # ensure we just process this method once
        if self.sub_tasks:
            return self.sub_tasks
        if self.__preparation:
            pattern = r"{0}".format(urllib.unquote(self.__preparation.get('pattern')))
            # ok, lets see what we can do
            if self.__preparation.get('filterFile'):
                filter_file = self.__preparation.get('filterFile')
                write_file = self.__preparation.get('writeFile')
                placeholder = self.__preparation.get('placeholder')
                copy = self.__preparation.get('copy')
                filter_files_found = [name for name in glob.glob(filter_file)]
                write_files_found = [name for name in glob.glob(write_file)]
                if len(filter_files_found) < 1:
                    raise InvalidFileDirectory('Task - Files were not found matching {0}.'.format(filter_file))
                logging.debug('Task - Found [%s] file(s) to filter using [%s].', str(len(filter_files_found)), str(filter_file))
                if len(write_files_found) < 1:
                    raise InvalidFileDirectory('Task - Files were not found matching {0}.'.format(write_file))
                logging.debug('Task - Found [%s] file(s) to write using [%s].', str(len(write_files_found)), str(write_file))
                # ok, it seems we have a pattern, so we should look inside each file
                if pattern:
                    # look matching regex in each line of a file
                    all_matching_lines = self.__find_in_files(filter_files_found, pattern)
                    logging.debug('Task - Found [%s] matching result(s) using [%s].', str(len(all_matching_lines)), str(pattern))
                    # look matching regex in each line of each file
                    for w_file in write_files_found:
                        for line in filter(None, all_matching_lines):
                            new_file = w_file
                            if copy:
                                # create a copy of the file with the same name plus
                                new_file = self.__create_copy(w_file)

                            # get commands to execute
                            self.sub_tasks.append(self.__replace_in_commands(new_file, line))

                            # look in side the new file for the placeholder and replace it
                            self.__replace_in_file(new_file, placeholder, line)
                else:
                    # seems you just want to filter files, lets replace them in the commands
                    for f_file in filter_files_found:
                         self.sub_tasks.append(self.__replace_in_commands(f_file, f_file))
            else:
                raise Exception('Task - Oops this shouldn\'t happen!')

        else:
            sub_task = SubTask(self)
            sub_task.add_commands(self.__commands)
            self.sub_tasks.append(sub_task)
        logging.debug('Task - This Task has been splitted in [%s] Sub Task(s).', str(len(self.sub_tasks)))
        return self.sub_tasks

    """
        Utility method to copy files

        Returns the file name of the new file copied
    """

    def __create_copy(self, file):
        new_filename = '{0}-{1}-{2}'.format(self.name, util.short_unique_id(), os.path.basename(file))
        shutil.copy2(file, new_filename)
        return new_filename

    """
        Utility method to find certain pattern in a set of files

        Returns all matching results
    """

    def __find_in_files(self, files, pattern):
        all_matching_lines = []
        for file in files:
            with open(file, "r") as f:
                all_matching_lines.extend(re.findall(pattern, f.read(), re.MULTILINE))
                f.close()
        return all_matching_lines

    """
        Utility method to generate sub tasks

        Returns the new SubTask
    """

    def __replace_in_commands(self, file, line=''):
        sub_task = SubTask(self)
        for command in self.__commands:
            # replace placeholder with actual created file
            sub_task.add_command(command.replace('$file', file).replace('$line', line))
        return sub_task

    """
        Utility method to replace a placeholder with a value in a file
    """

    def __replace_in_file(self, file, placeholder, value):
        # look in side the new file for the placeholder and replace it
        with codecs.open(file, 'r', encoding='utf8') as fr:
            text = fr.read()
            fr.close()
        # replace placeholder
        text = text.replace(placeholder, str(value))
        with codecs.open(file, 'w', encoding='utf8') as fw:
            fw.write(text)
            fw.close()

    """
        Get Guidance Tasks

        :return tasks
    """

    def get_children(self):
        return self.__children

    """
        Returns True if there are Guidance Tasks
    """

    def has_children(self):
        return len(self.__children) > 0

    """
        Returns the parent task if this task is a child, otherwise None
    """

    def get_parent(self):
        return self.__parent

    def __cmp__(self, other):
        return cmp(self.name, other.name)

    def __hash__(self):
        return hash(self.name) ^ hash(self.name)


"""Magen Client Handler handles authorization requests to Magen ID service"""
from functools import wraps
from urllib.parse import urlencode
import logging
import json
import flask
import requests
import requests.auth
import functools
from http import HTTPStatus

from magen_id_client_apis import utilities
from magen_rest_apis.rest_exception_apis import handle_specific_exception
from magen_rest_apis.rest_return_api import RestReturn
from magen_logger.logger_config import LogDefaults

LOGGER = logging.getLogger(LogDefaults.default_log_name)

__author__ = "michowdh@cisco.com"
__copyright__ = "Copyright(c) 2015, Cisco Systems, Inc."
__version__ = "0.2"
__status__ = "alpha"

class MagenClientAppHandler(object):
    """Magen Client Application Handler. Performs authorization requests to Magen ID Service"""
    DEFAULT_RESPONSE_TYPES = ['code', 'id_token', 'id_token token', 'token']
    state_key = 'oauthlib.client'

    def __init__(
            self, name,
            issuer="",
            redirect_uris=None,
            callback_uri=None,
            client_id=None,
            client_secret=None,
            response_type=None,
            default_scopes=None,
            jwt_alg=None,
    ):
        self.name = name
        self._issuer = issuer  # call setter
        self._callback_uri = callback_uri
        self._client_name = name
        self._client_id = client_id
        self._client_secret = client_secret
        self._redirect_uris = redirect_uris
        self._response_type = response_type or MagenClientAppHandler.DEFAULT_RESPONSE_TYPES
        self._default_scopes = default_scopes
        self._jwt_alg = jwt_alg
        self._authorize_url = self._issuer + '/oauth/authorize'
        self._request_id_token_url = self._issuer + '/oauth/token'
        self._tokeninfo_url = self._issuer + '/oauth/tokeninfo'

    @property
    def callback_uri(self):
        """
        This function returns the callback url

        :return: callback_url as string
        :rtype: string
        """
        return self._callback_uri

    @callback_uri.setter
    def callback_uri(self, url_string):
        """
        This function sets the callback url

        :param url_string: This parameter contains the callback url
        :type url_string: string
        """
        self._callback_uri = url_string

    @property
    def client_id(self):
        """
        This function returns the client id

        :return: client_id as string
        :rtype: string
        """
        return self._client_id

    @client_id.setter
    def client_id(self, new_id):
        """
        This function sets the client id

        :param new_id: This parameter contains the client id
        :type new_id: string
        """
        self._client_id = new_id

    @property
    def client_secret(self):
        """
        This function returns the client secret

        :return: client_secret as string
        :rtype: string
        """
        return self._client_secret

    @client_secret.setter
    def client_secret(self, new_secret):
        """
        This function sets the client secret

        :param new_secret: this parameter contains the client secret
        :type new_secret: string
        """
        self._client_secret = new_secret

    @property
    def issuer(self):
        """
        This function returns the issuer address

        :return: issuer address as string
        :rtype: string
        """
        return self._issuer

    @issuer.setter
    def issuer(self, new_issuer):
        """
        This function sets the issuer

        :param new_issuer: This parameter contains the issuer
        :type new_issuer: string
        """
        self._issuer = new_issuer
        self._authorize_url = self._issuer + '/oauth/authorize'
        self._request_id_token_url = self._issuer + '/oauth/token'
        self._tokeninfo_url = self._issuer + '/oauth/tokeninfo'

    @property
    def response_type(self):
        """
        This function returns the response_type

        :return: response_type as string
        :rtype: string
        """
        return self._response_type

    @response_type.setter
    def response_type(self, new_response_type):
        """
        This function sets the response_type

        :param new_response_type: This parameter contains response_type
        :type new_response_type: string
        """
        self._response_type = new_response_type

    def authorize(self, username=None, access_token=None, scopes='openid,profile,address', dynamic=False):
        """
        This function takes five parameters and redirects the client request to the magen_id service.

        :param username: This parameter contains the username of the user
        :param access_token: This parameter contains the Access token that comes from the user IDP
        :param scopes: This parameter contains the scope like email, profile, address, etc.
        :param dynamic: This parameter contains the flag for dynamic or non-dynamic client registration
        :type username: string
        :type access_token: string
        :type scopes: string
        :type dynamic: boolean
        """
        try:
            LOGGER.debug("_authorize_url===" + self._authorize_url)
            LOGGER.debug("username===" + username)
            LOGGER.debug("self.client_id===" + self._client_id)
            LOGGER.debug("self._callback_uri===" + self._callback_uri)
            LOGGER.debug("scopes===" + scopes)
            LOGGER.debug("dynamic mode=== " + str(dynamic))

            state = utilities.randomstr()
            nonce = utilities.randomstr()
            flask.session['state'] = state
            flask.session['nonce'] = nonce

            url = utilities.get_the_encoded_url(
                self._authorize_url + '?username=' + username + '&access_token=' + access_token +
                '&response_type=code' + '&redirect_uri=' + self._callback_uri + '&scope=' + scopes +
                '&nonce=' + flask.session['nonce'] + '&state=' + flask.session['state'])
            url = url + '&client_id=' + self._client_id
            LOGGER.debug("encoded url====" + url)
            # result = send_request(flask.redirect, url=url)
            # try:
            return flask.redirect(url)
            # except requests.exceptions.RequestException as err:
            #     return handle_specific_exception(err)
            # return RestReturn(
            #     success=True,
            #     message="Authorization Request",
            #     http_status=HTTPStatus.OK,
            #     json_body=response,
            #     response_object=response
            # )
        except Exception as error:
            LOGGER.error("ERROR: invalid url encoding: %s", error)
            # return RestReturn(
            #     success=False,
            #     message="Invalid URL encoding",
            #     json_body={"error": "Invalid url encoding"}
            # )
            return '/error'

    def process_auth_code(self):
        """

        This function does the following tasks:
            1. checkes the code and state parameter in the returned url
            2. POST submit to the magen_id service with the code, client_id,
               client_secret, redirect_uri, and grant type
            3. returns the response as json format

        :return: json data as an object
        :rtype: json object
        """
        state = flask.request.args.get('state', None)
        code = flask.request.args.get('code', None)

        if state is None:
            return {"error": "State is missing"}
        if code is None:
            return {"error": "Authorization code is missing"}

        if state == flask.session.get("state", None):
            access_token_req = {
                "code": code,
                "client_id": self._client_id,
                "client_secret": self._client_secret,
                "redirect_uri": self._callback_uri,
                "grant_type": "authorization_code",
            }
            headers = {}
            content_length = len(urlencode(access_token_req))
            access_token_req['content-length'] = str(content_length)
            try:
                response = requests.post(
                    url=self._request_id_token_url,
                    params=access_token_req,
                    headers=headers,
                    verify=False
                )
            except requests.exceptions.RequestException as err:
                return handle_specific_exception(err)
            return RestReturn(
                success=True,
                message="Process Authorization Code",
                http_status=HTTPStatus.OK,
                json_body=json.loads(response.text),
                response_object=response
            )
        return RestReturn(
            success=False,
            message="Authorization Failed",
            http_status=HTTPStatus.UNAUTHORIZED,
            json_body={"error": "You are not authorizaed. Please try again."}
        )

    def authorized_handler(self, func):
        """
        This is the decorator function for authorized handler
        """

        @wraps(func)
        def decorated(*args, **kwargs):
            data = self.process_auth_code()
            return func(*((data,) + args), **kwargs)

        return decorated

    def validate_mid_token_against_id_service(self, id_token):
        """
        This function validates the magen_id_token against the magen_id service and receives
        the detail information of the client and user

        :param id_token: This contains the magen id token
        :type: string

        return: json data as an object
        rtype: json object
        """
        LOGGER.debug('======= id_token ========%s ', id_token)
        headers = {'content-type': 'application/json'}
        partial_return = functools.partial(RestReturn, message='Validate MID token')
        try:
            response = requests.get(
                url=self._tokeninfo_url + '?id_token=' + id_token,
                headers=headers,
                verify=False
            )
        except requests.exceptions.RequestException as err:
            return handle_specific_exception(err)
        return partial_return(
            success=True,
            http_status=HTTPStatus.OK,
            json_body=response.json(),
            response_object=response
        ) if response.status_code == HTTPStatus.OK else partial_return(
            success=False,
            http_status=HTTPStatus.INTERNAL_SERVER_ERROR,
            json_body={"error": "token validation is failed"},
            response_object=None
        )


import hashlib
from typing import Tuple, Union

from django.conf import settings
from django.utils.decorators import method_decorator
from django.views.decorators.cache import cache_page

import django_filters
from drf_yasg import openapi
from drf_yasg.utils import swagger_auto_schema
from rest_framework import status
from rest_framework.filters import OrderingFilter
from rest_framework.generics import (DestroyAPIView, ListAPIView,
                                     ListCreateAPIView, RetrieveAPIView,
                                     get_object_or_404)
from rest_framework.renderers import JSONRenderer
from rest_framework.response import Response
from rest_framework.views import APIView
from web3 import Web3

from safe_transaction_service.version import __version__

from .filters import (DefaultPagination, MultisigTransactionFilter,
                      SmallPagination, TransferListFilter)
from .models import (InternalTx, ModuleTransaction, MultisigTransaction,
                     SafeContract, SafeContractDelegate, SafeMasterCopy,
                     SafeStatus)
from .serializers import (MasterCopyResponseSerializer,
                          OwnerResponseSerializer,
                          SafeBalanceResponseSerializer,
                          SafeBalanceUsdResponseSerializer,
                          SafeCollectibleResponseSerializer,
                          SafeCreationInfoResponseSerializer,
                          SafeDelegateDeleteSerializer,
                          SafeDelegateResponseSerializer,
                          SafeDelegateSerializer, SafeInfoResponseSerializer,
                          SafeModuleTransactionResponseSerializer,
                          SafeMultisigTransactionResponseSerializer,
                          SafeMultisigTransactionSerializer,
                          TransferResponseSerializer,
                          _AllTransactionsSchemaSerializer)
from .services import (BalanceServiceProvider, SafeServiceProvider,
                       TransactionServiceProvider)
from .services.collectibles_service import CollectiblesServiceProvider
from .services.safe_service import CannotGetSafeInfo

class AboutView(APIView):
    """
    Returns information and configuration of the service
    """
    renderer_classes = (JSONRenderer,)

    def get(self, request, format=None):
        content = {
            'name': 'Safe Transaction Service',
            'version': __version__,
            'api_version': self.request.version,
            'secure': self.request.is_secure(),
            'settings': {
                'ETHEREUM_NODE_URL': settings.ETHEREUM_NODE_URL,
                'ETHEREUM_TRACING_NODE_URL': settings.ETHEREUM_TRACING_NODE_URL,
                'ETH_INTERNAL_TXS_BLOCK_PROCESS_LIMIT ': settings.ETH_INTERNAL_TXS_BLOCK_PROCESS_LIMIT,
                'ETH_REORG_BLOCKS': settings.ETH_REORG_BLOCKS,
                'ETH_UNISWAP_FACTORY_ADDRESS': settings.ETH_UNISWAP_FACTORY_ADDRESS,
            }
        }
        return Response(content)

class AllTransactionsListView(ListAPIView):
    filter_backends = (django_filters.rest_framework.DjangoFilterBackend, OrderingFilter)
    pagination_class = SmallPagination
    serializer_class = _AllTransactionsSchemaSerializer  # Just for docs, not used

    _schema_queued_param = openapi.Parameter('queued', openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN, default=False,
                                             description='If `True` transactions with `nonce >= Safe current nonce` '
                                                         'are also shown')
    _schema_trusted_param = openapi.Parameter('trusted', openapi.IN_QUERY, type=openapi.TYPE_BOOLEAN, default=True,
                                              description='If `True` just trusted transactions are shown (indexed, '
                                                          'added by a delegate or with at least one confirmation)')
    _schema_200_response = openapi.Response('A list with every element with the structure of one of these transaction'
                                            'types', _AllTransactionsSchemaSerializer)

    def _parse_boolean(self, value: Union[bool, str]) -> bool:
        if value in (True, 'True', 'true', '1'):
            return True
        else:
            return False

    def get_parameters(self) -> Tuple[bool, bool]:
        """
        Parse query parameters:
        - queued: Default, True. If `queued=True` transactions with `nonce >= Safe current nonce` are also shown
        - trusted: Default, True. If `trusted=True` just trusted transactions are shown (indexed, added by a delegate
        or with at least one confirmation)
        :return: Tuple with queued, trusted
        """
        queued = self._parse_boolean(self.request.query_params.get('queued', True))
        trusted = self._parse_boolean(self.request.query_params.get('trusted', True))
        return queued, trusted

    def list(self, request, *args, **kwargs):
        transaction_service = TransactionServiceProvider()
        safe = self.kwargs['address']
        queued, trusted = self.get_parameters()
        queryset = self.filter_queryset(transaction_service.get_all_tx_hashes(safe, queued=queued, trusted=trusted))
        page = self.paginate_queryset(queryset)

        if not page:
            return self.get_paginated_response([])

        all_tx_hashes = [element['safe_tx_hash'] for element in page]
        all_txs = transaction_service.get_all_txs_from_hashes(safe, all_tx_hashes)
        all_txs_serialized = transaction_service.serialize_all_txs(all_txs)
        return self.get_paginated_response(all_txs_serialized)

    @swagger_auto_schema(responses={200: _schema_200_response,
                                    422: 'code = 1: Checksum address validation failed'},
                         manual_parameters=[_schema_queued_param, _schema_trusted_param])
    def get(self, request, *args, **kwargs):
        """
        Returns a paginated list of transactions for a Safe. The list has different structures depending on the
        transaction type:
        - Multisig Transactions for a Safe. `tx_type=MULTISIG_TRANSACTION`. If the query parameter `queued=False` is
        set only the transactions with `safe nonce < current Safe nonce` will be displayed. By default, only the
        `trusted` transactions will be displayed (transactions indexed, with at least one confirmation or proposed
        by a delegate). If you need that behaviour to be disabled set the query parameter `trusted=False`
        - Module Transactions for a Safe. `tx_type=MODULE_TRANSACTION`
        - Incoming Transfers of Ether/ERC20 Tokens/ERC721 Tokens. `tx_type=ETHEREUM_TRANSACTION`
        """
        address = kwargs['address']
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY, data={'code': 1,
                                                                               'message': 'Checksum address validation failed',
                                                                               'arguments': [address]})

        response = super().get(request, *args, **kwargs)
        response.setdefault('ETag', 'W/' + hashlib.md5(str(response.data['results']).encode()).hexdigest())
        return response

class SafeModuleTransactionListView(ListAPIView):
    filter_backends = (django_filters.rest_framework.DjangoFilterBackend, OrderingFilter)
    ordering_fields = ['created']
    pagination_class = DefaultPagination
    serializer_class = SafeModuleTransactionResponseSerializer

    def get_queryset(self):
        return ModuleTransaction.objects.filter(
            safe=self.kwargs['address']
        ).select_related(
            'internal_tx__ethereum_tx__block'
        ).order_by(
            '-created'
        )

    @swagger_auto_schema(responses={400: 'Invalid data',
                                    422: 'Invalid ethereum address'})
    def get(self, request, address, format=None):
        """
        Returns the module transaction of a Safe
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY, data='Invalid ethereum address')

        response = super().get(request, address)
        response.setdefault('ETag', 'W/' + hashlib.md5(str(response.data['results']).encode()).hexdigest())
        return response

@swagger_auto_schema(responses={200: 'Ok',
                                404: 'Not found'})
class SafeMultisigTransactionDetailView(RetrieveAPIView):
    serializer_class = SafeMultisigTransactionResponseSerializer
    lookup_field = 'safe_tx_hash'
    lookup_url_kwarg = 'safe_tx_hash'

    def get_queryset(self):
        return MultisigTransaction.objects.with_confirmations_required(
        ).prefetch_related(
            'confirmations'
        ).select_related(
            'ethereum_tx__block'
        )

class SafeMultisigTransactionListView(ListAPIView):
    filter_backends = (django_filters.rest_framework.DjangoFilterBackend, OrderingFilter)
    filterset_class = MultisigTransactionFilter
    ordering_fields = ['nonce', 'created']
    pagination_class = DefaultPagination

    def get_queryset(self):
        return MultisigTransaction.objects.filter(
            safe=self.kwargs['address']
        ).with_confirmations_required(
        ).prefetch_related(
            'confirmations'
        ).select_related(
            'ethereum_tx__block'
        ).order_by(
            '-nonce',
            '-created'
        )

    def get_unique_nonce(self, address: str):
        return MultisigTransaction.objects.filter(safe=address).distinct('nonce').count()

    def get_serializer_class(self):
        """
        Proxy returning a serializer class according to the request's verb.
        """
        if self.request.method == 'GET':
            return SafeMultisigTransactionResponseSerializer
        elif self.request.method == 'POST':
            return SafeMultisigTransactionSerializer

    @swagger_auto_schema(responses={400: 'Invalid data',
                                    422: 'Invalid ethereum address'})
    def get(self, request, *args, **kwargs):
        """
        Returns the history of a multisig tx (safe)
        """
        address = kwargs['address']
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY, data='Invalid ethereum address')

        response = super().get(request, *args, **kwargs)
        response.data['count_unique_nonce'] = self.get_unique_nonce(address) if response.data['count'] else 0
        response.setdefault('ETag', 'W/' + hashlib.md5(str(response.data['results']).encode()).hexdigest())
        return response

    @swagger_auto_schema(responses={201: 'Created or signature updated',
                                    400: 'Invalid data',
                                    422: 'Invalid ethereum address/User is not an owner/Invalid safeTxHash/'
                                         'Invalid signature/Nonce already executed/Sender is not an owner'})
    def post(self, request, address, format=None):
        """
        Creates a Multisig Transaction with its confirmations and retrieves all the information related.
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY, data='Invalid ethereum address')

        request.data['safe'] = address
        serializer = self.get_serializer_class()(data=request.data)

        if not serializer.is_valid():
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY, data=serializer.errors)
        else:
            serializer.save()
            return Response(status=status.HTTP_201_CREATED)

class SafeBalanceView(APIView):
    serializer_class = SafeBalanceResponseSerializer

    @swagger_auto_schema(responses={200: serializer_class(many=True),
                                    404: 'Safe not found',
                                    422: 'Safe address checksum not valid'})
    @method_decorator(cache_page(15))
    def get(self, request, address, format=None):
        """
        Get status of the safe
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY)
        else:
            try:
                SafeContract.objects.get(address=address)
            except SafeContract.DoesNotExist:
                return Response(status=status.HTTP_404_NOT_FOUND)

            safe_balances = BalanceServiceProvider().get_balances(address)
            serializer = self.serializer_class(safe_balances, many=True)
            return Response(status=status.HTTP_200_OK, data=serializer.data)

class SafeCollectiblesView(APIView):
    serializer_class = SafeCollectibleResponseSerializer

    @swagger_auto_schema(responses={200: serializer_class(many=True),
                                    404: 'Safe not found',
                                    422: 'code = 1: Checksum address validation failed'})
    @method_decorator(cache_page(15))
    def get(self, request, address, format=None):
        """
        Get status of the safe
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY, data={'code': 1,
                                                                               'message': 'Checksum address validation failed',
                                                                               'arguments': [address]})
        else:
            try:
                SafeContract.objects.get(address=address)
            except SafeContract.DoesNotExist:
                return Response(status=status.HTTP_404_NOT_FOUND)

            collectibles_with_metadata = CollectiblesServiceProvider().get_collectibles_with_metadata(address)
            serializer = self.serializer_class(collectibles_with_metadata, many=True)
            return Response(status=status.HTTP_200_OK, data=serializer.data)

class SafeBalanceUsdView(APIView):
    serializer_class = SafeBalanceUsdResponseSerializer

    @swagger_auto_schema(responses={200: serializer_class(many=True),
                                    404: 'Safe not found',
                                    422: 'code = 1: Checksum address validation failed'})
    @method_decorator(cache_page(15))
    def get(self, request, address, format=None):
        """
        Get status of the safe
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY, data={'code': 1,
                                                                               'message': 'Checksum address validation failed',
                                                                               'arguments': [address]})
        else:
            try:
                SafeContract.objects.get(address=address)
            except SafeContract.DoesNotExist:
                return Response(status=status.HTTP_404_NOT_FOUND)

            safe_balances = BalanceServiceProvider().get_usd_balances(address)
            serializer = self.serializer_class(safe_balances, many=True)
            return Response(status=status.HTTP_200_OK, data=serializer.data)

class SafeDelegateListView(ListCreateAPIView):
    pagination_class = DefaultPagination

    def get_queryset(self):
        return SafeContractDelegate.objects.filter(
            safe_contract_id=self.kwargs['address']
        )

    def get_serializer_class(self):
        if self.request.method == 'GET':
            return SafeDelegateResponseSerializer
        elif self.request.method == 'POST':
            return SafeDelegateSerializer

    @swagger_auto_schema(responses={400: 'Invalid data',
                                    422: 'Invalid Ethereum address'})
    def get(self, request, address, **kwargs):
        """
        Get the list of delegates for a Safe address
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY, data='Invalid ethereum address')

        return super().get(request, address, **kwargs)

    @swagger_auto_schema(responses={202: 'Accepted',
                                    400: 'Malformed data',
                                    422: 'Invalid Ethereum address/Error processing data'})
    def post(self, request, address, **kwargs):
        """
        Create a delegate for a Safe address with a custom label. Calls with same delegate but different label or
        signer will update the label or delegator if different.
        For the signature we are using TOTP with `T0=0` and `Tx=3600`. TOTP is calculated by taking the
        Unix UTC epoch time (no milliseconds) and dividing by 3600 (natural division, no decimals)
        For signature this hash need to be signed: keccak(address + str(int(current_epoch // 3600)))
        For example:
             - we want to add the owner `0x132512f995866CcE1b0092384A6118EDaF4508Ff` and `epoch=1586779140`.
             - TOTP = epoch // 3600 = 1586779140 // 3600 = 440771
             - The hash to sign by a Safe owner would be `keccak("0x132512f995866CcE1b0092384A6118EDaF4508Ff440771")`
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY, data='Invalid ethereum address')

        request.data['safe'] = address
        return super().post(request, address, **kwargs)

class SafeDelegateDestroyView(DestroyAPIView):
    serializer_class = SafeDelegateDeleteSerializer

    def get_object(self):
        return get_object_or_404(SafeContractDelegate,
                                 safe_contract_id=self.kwargs['address'],
                                 delegate=self.kwargs['delegate_address'])

    @swagger_auto_schema(responses={204: 'Deleted',
                                    400: 'Malformed data',
                                    404: 'Delegate not found',
                                    422: 'Invalid Ethereum address/Error processing data'})
    def delete(self, request, address, delegate_address, *args, **kwargs):
        """
        Delete a delegate for a Safe. Signature is built the same way that for adding a delegate.
        Check `POST /delegates/`
        """
        if not Web3.isChecksumAddress(address) or not Web3.isChecksumAddress(delegate_address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY, data='Invalid ethereum address')

        request.data['safe'] = address
        request.data['delegate'] = delegate_address
        serializer = self.get_serializer(data=request.data)
        serializer.is_valid(raise_exception=True)
        return super().delete(request, address, delegate_address, *args, **kwargs)

class SafeTransferListView(ListAPIView):
    filter_backends = (django_filters.rest_framework.DjangoFilterBackend,)
    filterset_class = TransferListFilter
    serializer_class = TransferResponseSerializer
    pagination_class = DefaultPagination

    def list(self, request, *args, **kwargs):
        # Queryset must be already filtered, as we cannot filter a union
        # queryset = self.filter_queryset(self.get_queryset())

        queryset = self.get_queryset()
        page = self.paginate_queryset(queryset)
        if page is not None:
            serializer = self.get_serializer(page, many=True)
            return self.get_paginated_response(serializer.data)

        serializer = self.get_serializer(queryset, many=True)
        return Response(serializer.data)

    def get_transfers(self, address: str):
        tokens_queryset = super().filter_queryset(InternalTx.objects.token_txs_for_address(address))
        ether_queryset = super().filter_queryset(InternalTx.objects.ether_txs_for_address(address))
        return InternalTx.objects.union_ether_and_token_txs(tokens_queryset, ether_queryset)

    def get_queryset(self):
        address = self.kwargs['address']
        return self.get_transfers(address)

    @swagger_auto_schema(responses={200: TransferResponseSerializer(many=True),
                                    422: 'Safe address checksum not valid'})
    def get(self, request, address, format=None):
        """
        Returns the history of a multisig tx (safe)
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY, data='Invalid ethereum address')

        response = super().get(request, address)
        response.setdefault('ETag', 'W/' + hashlib.md5(str(response.data['results']).encode()).hexdigest())
        return response

class SafeIncomingTransferListView(SafeTransferListView):
    def get_transfers(self, address: str):
        tokens_queryset = super().filter_queryset(InternalTx.objects.token_incoming_txs_for_address(address))
        ether_queryset = super().filter_queryset(InternalTx.objects.ether_incoming_txs_for_address(address))
        return InternalTx.objects.union_ether_and_token_txs(tokens_queryset, ether_queryset)

class SafeCreationView(APIView):
    serializer_class = SafeCreationInfoResponseSerializer

    @swagger_auto_schema(responses={200: serializer_class(),
                                    404: 'Safe creation not found',
                                    422: 'Owner address checksum not valid'})
    @method_decorator(cache_page(60 * 60))  # 1 hour
    def get(self, request, address, *args, **kwargs):
        """
        Get status of the safe
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY)

        safe_creation_info = SafeServiceProvider().get_safe_creation_info(address)
        if not safe_creation_info:
            return Response(status=status.HTTP_404_NOT_FOUND)

        serializer = self.serializer_class(safe_creation_info)
        return Response(status=status.HTTP_200_OK, data=serializer.data)

class SafeInfoView(APIView):
    serializer_class = SafeInfoResponseSerializer

    @swagger_auto_schema(responses={200: serializer_class(),
                                    404: 'Safe not found',
                                    422: 'code = 1: Checksum address validation failed\ncode = 50: Cannot get Safe info'})
    def get(self, request, address, *args, **kwargs):
        """
        Get status of the safe
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY, data={'code': 1,
                                                                               'message': 'Checksum address validation failed',
                                                                               'arguments': [address]})

        if not SafeContract.objects.filter(address=address).exists():
            return Response(status=status.HTTP_404_NOT_FOUND)

        try:
            safe_info = SafeServiceProvider().get_safe_info(address)
            serializer = self.serializer_class(safe_info)
            return Response(status=status.HTTP_200_OK, data=serializer.data)
        except CannotGetSafeInfo:
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY, data={'code': 50,
                                                                               'message': 'Cannot get Safe info',
                                                                               'arguments': [address]})

class MasterCopiesView(ListAPIView):
    serializer_class = MasterCopyResponseSerializer
    queryset = SafeMasterCopy.objects.all()
    pagination_class = None

class OwnersView(APIView):
    serializer_class = OwnerResponseSerializer

    @swagger_auto_schema(responses={200: OwnerResponseSerializer(),
                                    422: 'Owner address checksum not valid'})
    def get(self, request, address, *args, **kwargs):
        """
        Get status of the safe
        """
        if not Web3.isChecksumAddress(address):
            return Response(status=status.HTTP_422_UNPROCESSABLE_ENTITY)

        safes_for_owner = SafeStatus.objects.addresses_for_owner(address)
        serializer = self.serializer_class(data={'safes': safes_for_owner})
        assert serializer.is_valid()
        return Response(status=status.HTTP_200_OK, data=serializer.data)


# Based on https://medium.com/analytics-vidhya/pytorch-for-deep-learning-binary-classification-logistic-regression-382abd97fb43
import numpy as np
import pandas as pd
import matplotlib.pyplot as plt

import torch
import torch.nn as nn
import torch.optim as optim
from torch.utils.data import Dataset, DataLoader

from sklearn.preprocessing import StandardScaler
from sklearn.model_selection import train_test_split

def get_data(csv_file, training_size_frac=0.75):
    df = pd.read_csv(csv_file)
    X = np.array([df[label] for label in df.columns[1:(len(df.columns)-2)]])
    X = X.transpose()
    Y = np.array(df[df.columns[-1]])
    Y = np.array([1 if _y==0 else 0 for _y in Y])
    print(Y)

    training_set_len = int(training_size_frac*X.shape[0])

    X_train = X[:training_set_len,:]
    Y_train = Y[:training_set_len]

    X_eval = X[training_set_len:,:]
    Y_eval = Y[training_set_len:]
    X_train, Y_train, X_eval, Y_eval = map(torch.tensor, (X_train, Y_train, X_eval, Y_eval))
    #return X_train.float(), Y_train.long(), X_eval.float(), Y_eval.long()
    return X_train.float(), Y_train.float(), X_eval.float(), Y_eval.float()

class dataset(Dataset):
    def __init__(self,x,y):
        self.x = torch.tensor(x,dtype=torch.float32)
        self.y = torch.tensor(y,dtype=torch.float32)
        self.length = self.x.shape[0]

    def __getitem__(self,idx):
        return self.x[idx],self.y[idx]

    def __len__(self):
        return self.length

class Net(nn.Module):
    def __init__(self,input_shape):
        super(Net,self).__init__()
        self.fc1 = nn.Linear(input_shape,400)
        self.fc2 = nn.Linear(400,200)
        self.fc3 = nn.Linear(200,1)

        self.dropout = nn.Dropout(p=0.3)

    def forward(self,x):
        x = torch.relu(self.fc1(x))
        x = torch.relu(self.fc2(x))
        x = self.dropout(x)
        x = torch.sigmoid(self.fc3(x))
        return x

if __name__ == '__main__':
    X_train, y_train, X_test, y_test = get_data('Descriptors1545Label.csv')

    LEARNING_RATE = 0.01
    BATCH_SIZE = 64
    L2_REGULARIZATION = 0.025
    EPOCHS = 1000

    x = X_train
    y = y_train

    sc = StandardScaler()
    x = sc.fit_transform(x)
    X_test = sc.fit_transform(X_test)

    trainset = dataset(x,y)#DataLoader
    trainloader = DataLoader(trainset,batch_size=BATCH_SIZE,shuffle=False)

    model = Net(input_shape=x.shape[1])
    optimizer = torch.optim.SGD(model.parameters(),lr=LEARNING_RATE, weight_decay=L2_REGULARIZATION)
    loss_fn = nn.BCELoss()

    #forward loop
    losses = []
    accur = []
    print(x.shape)
    for i in range(EPOCHS):
        for j,(x_train,y_train) in enumerate(trainloader):

            #calculate output
            output = model(x_train)

            #calculate loss
            loss = loss_fn(output,y_train.reshape(-1,1))

            #accuracy
            predicted = model(torch.tensor(X_test, dtype=torch.float32))
            acc = (predicted.reshape(-1).detach().round() == y_test).float().mean()

            #backprop
            optimizer.zero_grad()
            loss.backward()
            optimizer.step()

        losses.append(loss)
        accur.append(acc)
        if i%50 == 0:
            print("epoch {}\tloss : {}\t accuracy : {}".format(i,loss,acc))

    #plt.plot(accur, label = 'Accuracy over test set')
    plt.plot(accur, label = 'Loss')
    plt.xlabel('Epoch')
    plt.ylabel('Accuracy over the test set')
    plt.ylim(.5, .8)
    #plt.legend(loc='center right')
    plt.savefig('TestCurve', dpi=300)
    plt.show()


"""Wrapper module to provide manipulation functions for vocabulary that
    should later be hidden from the user"""
import uuid
from enum import Enum

from pydantic import BaseModel, Field
from typing import Dict

from filip.models.base import LogLevel
from filip.semantics.vocabulary import *

class IdType(str, Enum):
    class_ = 'Class'
    object_property = 'Object Property'
    data_property = 'Data Property'
    datatype = 'Datatype'
    relation = 'Relation'
    combined_relation = 'Combined Relation'
    individual = 'Individual'
    source = 'Source'

class VocabularyBuilder(BaseModel):
    """Wrapper class to provide manipulation functions for vocabulary that
    should later be hidden from the user"""

    vocabulary: Vocabulary = Field(
        description="Vocabulary to manipulate"
    )

    current_source: Source = Field(
        default=None,
        description="Current source to which entities are added,"
                    "needed while parsing")

    def clear(self):
        """Clear all objects form the vocabulary

        Returns:
            None
        """
        self.vocabulary.classes.clear()
        self.vocabulary.object_properties.clear()
        self.vocabulary.data_properties.clear()
        self.vocabulary.datatypes.clear()
        self.vocabulary.relations.clear()
        self.vocabulary.combined_object_relations.clear()
        self.vocabulary.combined_data_relations.clear()
        self.vocabulary.individuals.clear()
        self.vocabulary.id_types.clear()
        for source in self.vocabulary.sources.values():
            source.clear()

    def add_class(self, class_: Class):
        """Add a class to the vocabulary

        Args:
            class_ (Class): class to be added

        Returns:
            None
        """
        self._add_and_merge_entity(class_,
                                   self.vocabulary.classes,
                                   IdType.class_)

    def add_object_property(self, obj_prop: ObjectProperty):
        """Add an ObjectProperty to the vocabulary

        Args:
            obj_prop (ObjectProperty): ObjectProperty to be added

        Returns:
            None
        """
        self._add_and_merge_entity(
            obj_prop, self.vocabulary.object_properties, IdType.object_property)

    def add_data_property(self, data_prop: DataProperty):
        """Add an DataProperty to the vocabulary

        Args:
            data_prop (DataProperty): DataProperty to be added

        Returns:
            None
        """
        self._add_and_merge_entity(
            data_prop, self.vocabulary.data_properties, IdType.data_property)

    def add_datatype(self, datatype: Datatype):
        """Add a DataType to the vocabulary

        Args:
            datatype (Datatype): Datatype to be added

        Returns:
            None
        """
        self._add_and_merge_entity(
            datatype, self.vocabulary.datatypes, IdType.datatype)

    def add_predefined_datatype(self, datatype: Datatype):
        """Add a DataType to the vocabulary, that belongs to the source:
            Predefined

        Args:
            datatype (Datatype): Datatype to be added

        Returns:
            None
        """
        self.vocabulary.id_types[datatype.iri] = IdType.datatype
        self.vocabulary.datatypes[datatype.iri] = datatype
        datatype.predefined = True
        datatype.source_ids.add("PREDEFINED")

    def add_individual(self, individual: Individual):
        """Add an Individual to the vocabulary

        Args:
            individual (Individual): Individual to be added

        Returns:
            None
        """
        self._add_and_merge_entity(individual,
                                   self.vocabulary.individuals,
                                   IdType.individual)

    def add_relation_for_class(self, class_iri: str, rel: Relation):
        """Add a relation object to a class

        Args:
            class_iri: Iri of the class to which the relation should be added
            rel: Relation to add

        Returns:
            None
        """

        class_ = self.vocabulary.get_class_by_iri(class_iri)

        # for rel_id in class_.relation_ids:
        #     ex_rel = self.vocabulary.get_relation_by_id(rel_id)
        #     if rel.target_statement== rel.target_statement:
        #         return

        self.vocabulary.relations[rel.id] = rel
        class_.relation_ids.append(rel.id)
        self.vocabulary.id_types[rel.id] = IdType.relation

    def add_combined_object_relation_for_class(self, class_iri: str,
                                               crel: CombinedObjectRelation):
        """Add a combined object relation object to a class

        Args:
            class_iri: Iri of the class to which the co-relation should be added
            crel: CombinedObjectRelation to add

        Returns:
            None
        """
        self.vocabulary.combined_object_relations[crel.id] = crel
        self.vocabulary.get_class_by_iri(class_iri).\
            combined_object_relation_ids.append(crel.id)
        self.vocabulary.id_types[crel.id] = IdType.combined_relation

    def add_combined_data_relation_for_class(self, class_iri: str,
                                             cdata: CombinedDataRelation):
        """Add a combined data relation object to a class

        Args:
            class_iri: Iri of the class to which the cd-relation should be added
            cdata: CombinedDataRelation to add

        Returns:
            None
        """
        self.vocabulary.combined_data_relations[cdata.id] = cdata
        self.vocabulary.get_class_by_iri(class_iri).\
            combined_data_relation_ids.append(cdata.id)
        self.vocabulary.id_types[cdata.id] = IdType.combined_relation

    def add_source(self, source: Source, id: str = None):
        """Add a source to the vocabulary

        Args:
            source: source to add
            id: id of source, if none is given a random id is generated

        Returns:
            None
        """
        if id is None:
            source.id = uuid.uuid4().hex
        else:
            source.id = id
        self.vocabulary.id_types[source.id] = IdType.source
        self.vocabulary.sources[source.id] = source
        self.current_source = source

    def set_current_source(self, source_id: str):
        """Set the source of the vocabulary to which new added objects belong

        Args:
            source_id: id of source to activate

        Returns:
            None
        """
        assert source_id in self.vocabulary.sources
        self.current_source = self.vocabulary.sources[source_id]

    def _add_and_merge_entity(self,
                              entity: Entity,
                              entity_dict: Dict[str, Entity],
                              id_type: IdType):
        """Adds an entity to the vocabulary. If an entity with teh same iri
        already exists the label and comment are "merged" and both sources
        are noted

        Args:
            entity: Entity to check
            entity_dict: Existing entities
            id_type: Type of entity

        Raises:
            ParsingError: if Entity of iri exists but has a different IdType

        Returns:
            None
        """

        if entity.iri in self.vocabulary.id_types:
            if not id_type == self.vocabulary.id_types[entity.iri]:
                self.current_source.add_parsing_log_entry(
                    LogLevel.CRITICAL, id_type, entity.iri,
                    f"{entity.iri} from source "
                    f"{self.current_source.get_name()} "
                    f"exists multiple times in different catagories. It was "
                    f"only added for the category "
                    f"{self.vocabulary.id_types[entity.iri].value}")
                return

            old_entity = entity_dict[entity.iri]

            def select_from(old: str, new: str, property: str) -> str:
                """
                Given two strings, one from the old_entity , one form the new
                one. It is selected which one to use.
                """
                if old == "":
                    return new
                elif new == "":
                    return ""
                else:
                    self.current_source.add_parsing_log_entry(
                        LogLevel.WARNING, id_type, entity.iri,
                        f"{property} from source "
                        f"{old_entity.get_source_names(self.vocabulary)} "
                        f"was overwritten")
                    return new

            entity.label = select_from(old_entity.label, entity.label, "label")
            entity.comment = select_from(old_entity.comment, entity.comment,
                                         "comment")

        self.vocabulary.id_types[entity.iri] = id_type
        entity.source_ids.add(self.current_source.id)
        entity_dict[entity.iri] = entity

    def entity_is_known(self, iri: str) -> bool:
        """Test if the given iri is in vocabulary, if not it belongs to a
        dependency which is not yet loaded

        Args:
            iri (str)

        Returns:
            bool
        """
        return iri in self.vocabulary.id_types


import pytesseract
import time
import cv2
import pyautogui
import re
import keyboard

def get_numbers_from_screen_section(x1, y1, x2, y2):
    # Capture the user-defined section of the screen
    screenshot = pyautogui.screenshot(region=(x1, y1, x2, y2))

    # Save the screenshot as an image
    screenshot.save("screenshot.png")

    # Read the image
    image = cv2.imread("screenshot.png")

    # Convert the image to grayscale
    gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)

    # Apply thresholding to the image
    thresh = cv2.threshold(gray, 0, 255, cv2.THRESH_BINARY + cv2.THRESH_OTSU)[1]

    # Pass the image to tesseract to get the recognized text
    text = pytesseract.image_to_string(thresh, lang='eng', config='--psm 11')
    return text

def check_screen_section(x1, y1, x2, y2):
    # Get the current numbers in the screen section
    current_numbers = get_numbers_from_screen_section(x1, y1, x2, y2)
    current_numbers = re.findall(r'\d+', current_numbers)
    current_numbers = int("".join(map(str, current_numbers))) if current_numbers else 0

    while True:
        # Get the numbers in the screen section again
        new_numbers = get_numbers_from_screen_section(x1, y1, x2, y2)
        print(f"new_numbers = {new_numbers}")

        # Convert string to list and remove non numbers
        new_numbers = re.findall(r'\d+', new_numbers)

        # Convert list to int
        new_numbers = int("".join(map(str, new_numbers))) if new_numbers else 0
        print(f"new_numbers alterado = {new_numbers}")

        # Check if the numbers have changed
        if new_numbers != current_numbers:
            start_time = time.time()  # Start the timer

            # Calculate the difference in numbers
            diff = new_numbers - current_numbers

            current_numbers = new_numbers

            end_time = time.time()  # Stop the timer
            elapsed_time = end_time - start_time  # Calculate the elapsed time

            print(f"Numbers changed by {diff}. Time taken: {elapsed_time} seconds.")

        else:
            time.sleep(1)  # Sleep for 1 second before checking again

# Call the function with the coordinates of the screen section

x1 = "0"
x2 = "300"
y1 = "0"
y2 = "100"

check_screen_section(x1, y1, x2, y2)


from tkinter import *
import numpy as np
import matplotlib.pyplot as plt
import matplotlib.animation as animation
import cmath as c
from math import pi
from math import sqrt
import turtle

# ......................... Window Configuration .......................

window = Tk()
window.geometry("1400x780")
window.title("Simulation Etat de l'Art")
icon = PhotoImage(file= 'logoISEP.png')
canvas = Canvas(window, height=500, width=500)
window.config(background="#326ba8")

# ....................... Variable declaration .........................

a = IntVar()
t = 0
x = 100
y = 100

# ................................ Functions .................................
# Menu Functions .......................

    #Entry functions ....................

def runSimulation():
    # Debut des calculs et de l'affichage des résultats

    def initialise():
        while True :
            try :
                global end
                global dt
                global t
                global teta
                global m
                global l
                global g
                global teta_zero
                global L
                global t
                global end

                end = 10000    #temps de simulation
                dt = 0.05
                t= np.linspace(0,end,int(150/dt)) # vecteur temps, discrétiser avec un pas de dt
                m = float(entryMasse.get())
                l = float(entryLong.get())
                g = float(9.81)
                teta =[]
                teta_zero = float(entryAngle.get())
                L = float(entryLatit.get())
                L = (L*pi/180)
                if (teta_zero <= 90 and teta_zero >= -90) and (L <= 90 and L>= -90):
                    break
            except TypeError:
                pass

    initialise()

    j = complex(0,1)
    teta.append(teta_zero*pi/180)      #conversion en radian de teta

    Omega = (7.29)*(10**-5)            # La vitesse de rotation de la Terre sur elle-même c'est l'une des causes même de l'effet Coriolis
    w = ((24*3600))/np.sin(L)          # vitesse angulaire
    omega_prime = np.sqrt(Omega**2 + w**2) # omega_prime est une variable mathématique qui nous aidera dans le calcul
    a = l*np.cos(teta_zero)              # C'est la position initiale du pendule dans le repère cartésien

    accel_ang =[] # On calcul l'acceération angulaire dans la base (ur,uteta,uz)
    vit_ang = []
    accel_ang.append(0)
    vit_ang.append(0)
    sol = slice(0,len(t),20)

    """ Calcul de la vitesse angulaire """
    for k in range(1,len(t)):
        vit_ang.append(vit_ang[k-1]+accel_ang[k-1]*dt)
        teta.append(teta[k-1] + vit_ang[k]*dt)
        accel_ang.append(-(g/l)*np.sin(teta[k]))

    vit_angX = np.zeros_like(vit_ang)
    vit_angY = np.zeros_like(vit_ang)

    plt.figure('1')
    plt.subplot(3,1,1)
    plt.title("Vitesse angulaire pendule simple")
    plt.plot(t[sol],vit_angX[sol],'yellow',label = 'x')
    plt.xlabel("t en (s)")
    plt.ylabel("(rad/s) ")
    plt.legend()

    plt.subplot(3,1,2)
    plt.plot(t[sol],vit_angY[sol], 'red', label = 'y')
    plt.xlabel("t en (s)")
    plt.ylabel("(rad/s) ")
    plt.legend()

    plt.subplot(3,1,3)
    plt.plot(t[sol],vit_ang[sol],'blue', label = 'z')
    plt.xlabel("t en (s)")
    plt.ylabel("(rad/s) ")
    plt.legend()

    plt.show()

    """ Plot X,Z
    Via une projection on trouve la position dans le repère (X,Y,Z)"""

    X = l*np.sin(teta)
    Z = l*(1-np.cos(teta))

    """Mouvement suivant l'axe Y,Z force de Coriolis
    Nous nous plaçons à Paris Latitude 48.85 latitude Nord
    On fixe pour conditions initiales x = l*cos(teta), pendule laché sans vitesse initiale
     C = X + iY"""

    C = a*(np.cos(w*t) + j*(Omega/omega_prime)*np.sin(omega_prime*t))*np.exp(-j*Omega*t)    # Equation du mouvement du pendule de Foucault s'obtient en résolvant un système d'équation différentielle couplée
    A = C.real
    B = C.imag
    P = []
    R = []

    """ Calcul vitesse angulaire """

    Vitesse_ang = [0]
    for k in C :
        P.append(c.phase(k)) # On calcul le vecteur phase
        R.append(abs(k))     # On calcul le module
    Len = len(R)
    for i in range(1,Len):
        Vitesse_ang.append((R[i]-R[i-1])/(t[i]-t[i-1]))

    Vitesse_angX = np.zeros_like(Vitesse_ang)
    Vitesse_angY = np.zeros_like(Vitesse_ang)

    plt.figure('2')

    plt.subplot(3,1,1)
    plt.title("vitesse angulaire pendule Foucault")
    plt.plot(t[sol],Vitesse_angX[sol],'yellow', label = 'x')
    plt.xlabel("t en (s)")
    plt.ylabel("(rad/s) ")
    plt.legend()

    plt.subplot(3,1,2)
    plt.plot(t[sol],Vitesse_angY[sol],'red', label = 'y')
    plt.xlabel("t en (s)")
    plt.ylabel("(rad/s) ")
    plt.legend()

    plt.subplot(3,1,3)
    plt.plot(t[sol],Vitesse_ang[sol],'blue', label= 'z')
    plt.xlabel("t en (s)")
    plt.ylabel("(rad/s) ")
    plt.legend()

    plt.show()

    """ pendule avec amortissements dus au frottements visqueux """
    r = 0.16
    coef = 6*pi*r
    K = coef*r
    Nair = 0.018 * 10** -13
    teta_rad = (teta_zero*pi)/180
    Ta = 2*pi*sqrt(l/g)*(1+(teta_rad**2/16))
    wa = (2*pi)/Ta
    Lambda =  (K*Ta)/(m*l**2)

    if abs(Lambda)<1 :
        t1 = np.linspace(0,720,720)
        axeX_Y = np.zeros_like(t1)
        print('Cas complexe Lambda = ',Lambda)
        Beta = wa*sqrt(1-Lambda**2)
        Alpha = -Lambda*wa
        C1 = teta_rad
        C2 = (Lambda*(teta_rad))/(sqrt(1-Lambda**2))
        PosAng = np.exp(Alpha*t1)*(C1*np.cos(Beta*t1)+C2*np.sin(Beta*t1))
        derPosAng = Alpha*np.exp(Alpha*t1)*(C1*np.cos(Beta*t1) + C2*np.sin(Beta*t1)) + Beta*np.exp(Alpha*t1)*(-C1*np.sin(Beta*t1)+C2*np.cos(Beta*t1))

        plt.figure('4')
        plt.subplot(3,1,1)
        plt.title('Vitesse angulaire avec amortissement (Cas delta complexe) Lambda = '+ str(Lambda))
        plt.plot(t1,PosAng, 'green' ,label = 'z')
        plt.xlabel("t en (s) ")
        plt.ylabel("Vitesse en (rad/s)")
        plt.legend()

        plt.subplot(3,1,2)
        plt.plot(t1, axeX_Y,'red', label = 'y')
        plt.xlabel("t en (s)")
        plt.ylabel("(rad/s) ")
        plt.legend()

        plt.subplot(3,1,3)
        plt.plot(t1,axeX_Y,'blue', label = 'z')
        plt.xlabel("t en (s)")
        plt.ylabel("(rad/s) ")
        plt.legend()

        plt.show()

    else:
        t1 = np.linspace(0,200,200)
        axeX_Y = np.zeros_like(t1)
        print('Cas réel Lambda = ',Lambda)
        Beta = wa*sqrt(Lambda**2-1)
        r1 = wa*(-Lambda + sqrt(Lambda**2 - 1))
        r2 = wa*(-Lambda - sqrt(Lambda**2 -1))
        A = (r2/(r2-r1))*(teta_rad)
        B = (r1/(r1-r2))*(teta_rad)
        PosAng = A*np.exp(r1*t1) + B*np.exp(r2*t1)
        derPosAng = r1*A*np.exp(r1*t1) + r2*B*np.exp(r2*t1)

        plt.figure('4')
        plt.subplot(3,1,1)
        plt.title('Vitesse angulaire avec amortissement (cas delta réel) Lamnda = ' + str(Lambda))
        plt.plot(t1,PosAng , 'green' , label = 'z')
        plt.xlabel("t en (s) ")
        plt.ylabel("Vitesse en (rad/s)")

        plt.subplot(3,1,2)
        plt.plot(t1,axeX_Y,'red', label = 'y')
        plt.xlabel("t en (s)")
        plt.ylabel("(rad/s) ")
        plt.legend()

        plt.subplot(3,1,3)
        plt.plot(t1,axeX_Y,'blue', label = 'z')
        plt.xlabel("t en (s)")
        plt.ylabel("(rad/s) ")
        plt.legend()

        plt.show()

 # Fin des calculs et de l'affichage des figures

def delete(entry):
    entry.delete(0,END)

def display():
    if(a.get()==1): # Force de Coriolis est présente

        canvas.itemconfig(1, state='normal')
        canvas.itemconfig(2, state='normal')
        canvas.itemconfig(3, state='normal')
        canvas.itemconfig(4, state='hidden')
        canvas.itemconfig(5, state='hidden')
        canvas.itemconfig(6, state='hidden')
        canvas.itemconfig(7, state='hidden')

    else:   # Pas de force de Coriolis

        canvas.itemconfig(1, state='hidden')
        canvas.itemconfig(2, state='hidden')
        canvas.itemconfig(3, state='hidden')
        canvas.itemconfig(4, state='normal')
        canvas.itemconfig(5, state='normal')
        canvas.itemconfig(6, state='normal')
        canvas.itemconfig(7, state='normal')

def create_circle(x, y, r, canvasName, color, w): # easier way to make a circle
    x0 = x - r
    y0 = y-r
    x1 = x + r
    y1 = y + r
    return canvasName.create_oval(x0, y0, x1, y1, fill = color, width = w)

def clearSimul():
    entryLong.delete(0,END)
    entryMasse.delete(0,END)
    entryAngle.delete(0,END)
    entryLatit.delete(0,END)
  #  entryVitRot.delete(0,END)

def printSimul():
    print("l = " + L)
    print("m = " + m)
    print("angle = " + h)
    print("L = " + x0)

# ....................... Calculate Operations .........................

def draw_nocoriolis(x,y):
    create_circle(x,y,7,canvas, "red", 1) # mass position

def draw_coriolis(x,y):
    create_circle(x,y,7,canvas, "red", 1) # mass position

def update(t,x,y):
    t=t+1
    x = x +10
    y = y + 10

def updateScreen():
    while(t<20):
        update(t,x,y)
        draw_coriolis(x, y)

# .......................... Widgets creation .........................

# ......................... Left Side Creation .........................

# ........................... Labels creation .........................

Titre = Label(window, text="Simulation Etat de l'Art",
                    font =('Arial', 40, 'bold'),
                    fg = 'white', bg='black',
                    relief = RAISED,
                    bd = 10,
                    padx = 5, pady = 5)

Texte_Parametrage = Label(window, text="Paramètres de la simulation à définir",
                    font =('Arial', 18, 'bold'),
                    fg = 'white', bg='black',
                    relief = RAISED,
                    bd = 5,
                    padx = 0, pady = 0)

LongueurFil = Label(window, text="Longueur du fil",
                    font =('Arial', 14),
                    fg = 'black', bg='white',
                    relief = SUNKEN,
                    bd = 2,
                    padx = 0, pady = 0)

MasseSmartphone = Label(window, text="Masse du smartphone (en moyenne 0.15 kg)",
                    font =('Arial', 14),
                    fg = 'black', bg='white',
                    relief = SUNKEN,
                    bd = 2,
                    padx = 0, pady = 0)

AngleInitial = Label(window, text="Angle Initial (en °)",
                    font =('Arial', 14),
                    fg = 'black', bg='white',
                    relief = SUNKEN,
                    bd = 2,
                    padx = 0, pady = 0)

Latitude = Label(window, text="Latitude (Paris = 48.52)",
                    font =('Arial', 14),
                    fg = 'black', bg='white',
                    relief = SUNKEN,
                    bd = 2,
                    padx = 0, pady = 0)

MessageAffich = Label(window, text="Les plots s'affichent dans l'environnement de développement \nou dans une autre fenêtre (si vous n'utilisez pas d'environnement de développement)",
                    font =('Arial', 12),
                    fg = 'black', bg='white',
                    relief = SUNKEN,
                    bd = 2,
                    padx = 0, pady = 0)

check_Coriol = Checkbutton(window, text = "Animation Pendule de Foucault",
                           variable = a, onvalue=1, offvalue= 2,
                            command = display)

check_Resist = Checkbutton(window, text = "Frottements")

# Menu Bar  .......................................................

menubar = Menu(window)
window.config(menu = menubar)

simulMenu = Menu(menubar, tearoff=0)
menubar.add_cascade(label="Simulation", menu = simulMenu)
simulMenu.add_command(label ="Run Simulation", command = runSimulation)
simulMenu.add_command(label ="Run Animation", command = updateScreen)
simulMenu.add_command(label ="Clear Parameters", command = clearSimul)

# ................. Create entries for parameters ........................
# First parameter ......................

entryLong = Entry(window, font =("Arial",14))
deleteLong = Button(window, text ="Clear", command=lambda:   delete(entryLong))

# Second Parameter

entryMasse = Entry(window, font =("Arial",14))
deleteMasse = Button(window, text ="Clear", command= lambda: delete(entryMasse))

# Third Parameter

entryAngle = Entry(window, font =("Arial",14))
deleteAngle = Button(window, text ="Clear", command=lambda:   delete(entryAngle))

# Fourth Parameter

entryLatit = Entry(window, font =("Arial",14))
deleteLatit = Button(window, text ="Clear", command=lambda:   delete(entryLatit))

# ......................... END OF LEFT SIDE .........................

# ........................ START OF RIGHT SIDE .......................

# ......................... Canvas Creation .......................

canvas.place(x = 800, y = 200)
# Force de Coriolis
canvas.create_oval(240,240,260,260, fill="purple", width=2)  # inside circle = center of pendule
canvas.create_oval(50,50,450,450, width=2, dash=(1,100)) # outside circle = max trajectory of pendule
main_circle = create_circle(30,30,7,canvas, "red", 1) # mass position

# No Force de Coriolis
create_circle(250,225,8,canvas, "purple", 2)  # inside circle = center of pendule
main_circle2 =create_circle(250,450,7,canvas, "red", 1)  # mass position
main_line2 = canvas.create_line(250,225,250,450, fill="black", width=1)
canvas.create_arc(25, 0, 450, 450, extent =180,start =180, width =0, dash=(1,1))

canvas.itemconfig(1, state='hidden')
canvas.itemconfig(2, state='hidden')
canvas.itemconfig(3, state='hidden')

# ........................ Placing the widgets ........................

# ........................ Left Side Creation .........................

Titre.place(x=450, y=0)
Texte_Parametrage.place(x=5, y=75)
LongueurFil.place(x=5, y=170)
MasseSmartphone.place(x=5, y=270)
AngleInitial.place(x=5, y=370)
Latitude.place(x=5, y=470)
MessageAffich.place(x=5, y=670)

# Place buttons
check_Coriol.place(x=5, y=570)
check_Resist.place(x=210, y=570)

entryLong.place(x=5, y =200)
deleteLong.place(x=230, y=200)

entryMasse.place(x=5, y =300)
deleteMasse.place(x=230, y=300)

entryAngle.place(x=5, y =400)
deleteAngle.place(x=230, y=400)

entryLatit.place(x=5, y =500)
deleteLatit.place(x=230, y=500)

# .......................... Right Side Creation ..................

# ...............................................................

window.mainloop()

Simulation - Etat de l'art/Integration_Simulation_Etat_de_l_art_G9D.py


from box import Box
from particle import Particle
import os
import pathlib
import csv
import random

box = Box(70,70,gravity=(0,-20))

radius = 0.5

for x in range(30,box.width-30,1) :
    for y in range(0,box.heigth-30,1) :

        box.addParticle(Particle(x,y+0.5,random.randint(-1,1),random.randint(-1,1),1,radius))

Tt = 10

dt = 0.01

output_path = str(pathlib.Path(__file__).parent.resolve()) + '/output.csv'

with open(output_path, 'w', newline='') as out :

    writer = csv.writer(out)

    tmp = [Tt,dt,box.width,box.heigth]
    for particule in box.particles : tmp.append(particule.radius)
    writer.writerow(tmp)

    t = 0
    while t < Tt :

        tmp =  [t]

        box.update(dt)

        for particle in box.particles :
            tmp.append(str(particle.position[0]) + ' ' + str(particle.position[1]))

        writer.writerow(tmp)

        os.system('clear')
        print(round((t/Tt)*100,0),'%')

        t += dt

    print('simulation completed')

import consoleRender #en depit de ent


# this class is to produce all relevant inspected statistics on the data set
import os
import re
from collections import Counter

import matplotlib.gridspec as gridspec
import matplotlib.pyplot as plt
import nltk
import seaborn as sns

from src.features.writing_style_features import *
from src.utils import input_reader
from src.utils.input_reader import load_50_authors_preprocessed_data

nltk.download('maxent_ne_chunker')
import string
import os.path
import sys

def seperate_entity_types(sentence):
    tokens = sentence.split()

    matcher = re.compile('^ent__')
    ent_types = ''
    for token in tokens:
        if matcher.match(token) is not None:
            ent_types = ent_types + token + " "

    exclude = set(string.punctuation)
    ent_types = ''.join(ch for ch in ent_types if ch not in exclude)
    ent_types = ent_types.replace('ent', '')
    return ent_types

def load_data(input_folder_name='input'):
    path_prefix = ".." + os.sep + ".." + os.sep + input_folder_name + os.sep
    train_df, test_df, sample_df = input_reader.load_data_sets(path_prefix + "train.csv", path_prefix + "test.csv",
                                                               None)
    train_df = train_df.set_index('id')
    train_df.index = [id[2:] for id in train_df.index]
    return train_df

def load_50_auth_data(train=True):
    train_df = input_reader.load_50_authors_data_sentences_to_dict(train=train)
    train_df = train_df.set_index('id')
    # train_df.index = [id[2:] for id in train_df.index]
    return train_df

def author_bar_plot(train_df):
    fig = plt.figure()
    sns.countplot(x=train_df.author, order=train_df.author.value_counts().index).set_title(
        'records count per author')
    plt.xticks(rotation='vertical', fontsize=5)
    fig.show()
    fig.tight_layout()
    fig.savefig('output_charts//author_bar_plot.pdf', format='pdf')
    print("author_bar_plot saved to output_charts//author_bar_plot.pdf")
    plt.close()

def plot_token_frequencies(author_df, referance_column='text_cleaned2', title_prefix='',
                           output_path='output_charts//50_authors_db//'):
    fig = plt.figure()
    fd = nltk.FreqDist([y for x in author_df[referance_column].str.split() for y in x])
    if title_prefix != '':
        title = title_prefix + ',token frequencies, top 30'
    else:
        title = 'token frequencies, top 30'

    fd.plot(30, title=title)
    fig.savefig(output_path + 'plot_token_frequencies_' + title_prefix + '.pdf', format='pdf')
    print(
        "common words/entities for author " + title_prefix + " saved to " + output_path + 'plot_token_frequencies_' + title_prefix + '.pdf')
    plt.close()

def plot_multiple_token_frequencies(author_df, output_file_prefix, referance_column='text_cleaned2',
                                    referance_author_column='author'):
    fig = plt.figure()
    # fig.subplots_adjust(hspace=0.4, wspace=0.4,figsize=(15,15))
    gs1 = gridspec.GridSpec(10, 5)
    gs1.tight_layout(fig)
    # fig.set_title('token frequencies, top 30')
    plt_i = 0
    for label in set(author_df[referance_author_column]):
        s_plt = fig.add_subplot(gs1[plt_i])
        plt_i = plt_i + 1
        s_plt.set_title(label)

        df = author_df[author_df[referance_author_column] == label]
        counter = Counter([y for x in df[referance_column].str.split() for y in x])
        top30 = counter.most_common(30)
        words = []
        words_count = []
        for i in range(0, len(top30)):
            str = top30[i][0]
            val = top30[i][1]
            words.append(str)
            words_count.append(val)
        width = 0.7
        plt.xticks(rotation='vertical', fontsize=5)
        plt.bar(words, words_count, width)
    fig.savefig('output_charts//50_authors_db//' + output_file_prefix + '.pdf', format='pdf')

def boxplot_length(author_df, out_folder=''):
    fig = plt.figure()
    sns.boxplot(x='author', y='words_cnt', data=author_df).set_title('sentence words count per author')
    plt.xticks(rotation='vertical', fontsize=5)
    fig.show()
    fig.savefig(out_folder + 'sentence_words_boxplot.pdf', format='pdf')
    print("boxplot for sentences word count saved to " + out_folder + 'sentence_words_boxplot.pdf')
    plt.close()

def boxplot_char_length(author_df, out_folder=''):
    fig = plt.figure()
    sns.boxplot(x='author', y='char_cnt', data=author_df).set_title('sentence characters per author')
    plt.xticks(rotation='vertical', fontsize=5)
    fig.show()
    fig.savefig(out_folder + 'sentence_chars_boxplot.pdf', format='pdf')
    print("boxplot for sentences length saved to " + out_folder + 'sentence_chars_boxplot.pdf')
    plt.close()

def drop_outliers(s):
    med = s.mean()
    std = s.std()
    return s[(med - 3 * std <= s) & (s <= med + 3 * std)]

def plot_panctuation_use(author_df, out_folder=''):
    f, ax = plt.subplots(figsize=(7, 4))
    for label in set(author_df.author):
        sns.kdeplot(drop_outliers(author_df.loc[author_df.author == label].punct_cnt), shade=True);
    ax.legend(labels=set(author_df.author)).set_title('panctuation use per author')
    f.savefig(out_folder + 'plot_punctuation_use.pdf', format='pdf')
    print("plot for panctuation use saved to " + out_folder + 'plot_punctuation_use.pdf')
    plt.close()

def plot_noun_use(author_df, out_folder=''):
    f, ax = plt.subplots(figsize=(7, 4))
    for label in set(author_df.author):
        sns.kdeplot(drop_outliers(author_df.loc[author_df.author == label].noun_chunks_cnt), shade=True);
    ax.legend(labels=set(author_df.author)).set_title('noun use per author')
    f.savefig(out_folder + 'plot_noun_use.pdf', format='pdf')
    print("plot for noun use saved to " + out_folder + 'plot_noun_use.pdf')
    plt.close()

def plot_author_polarity(author_df, out_folder=''):
    f, ax = plt.subplots(figsize=(7, 4))
    for label in set(author_df.author):
        sns.kdeplot(drop_outliers(author_df.loc[author_df.author == label].polarity_of_text), shade=True);
    ax.legend(labels=set(author_df.author)).set_title('text polarity per author')
    f.savefig('output_charts//' + out_folder + 'plot_text_polarity.pdf', format='pdf')
    print("plot for author polarity use saved to " + 'output_charts//' + out_folder + 'plot_text_polarity.pdf')
    plt.close()

def spooky_author_stats():
    df_train = load_data()
    print(df_train.info())
    # remove stop words and punctuations
    preprocess_text(df_train)
    df_train.to_csv('df_test_50_auth_preprocessed.tsv', sep='\t')

    author_bar_plot(df_train)

    df_train['text_cleaned2'] = df_train['text_cleaned'].str.replace('-PRON-', '')
    # plot common words per author
    plot_token_frequencies(author_df=df_train, title_prefix='Overall word')
    df_eap = df_train.loc[df_train.author == 'EAP']
    plot_token_frequencies(author_df=df_eap, title_prefix='EAP word')
    df_hpl = df_train.loc[df_train.author == 'HPL']
    plot_token_frequencies(author_df=df_hpl, title_prefix='HPL word')
    df_mws = df_train.loc[df_train.author == 'MWS']
    plot_token_frequencies(author_df=df_mws, title_prefix='MWS word')

    # enteties
    df_train['entities_types'] = df_train.text_ent_repl.apply(seperate_entity_types)
    plot_token_frequencies(author_df=df_train, referance_column='entities_types', title_prefix='Overall entities')
    df_eap = df_train.loc[df_train.author == 'EAP']
    plot_token_frequencies(author_df=df_eap, referance_column='entities_types', title_prefix='EAP entities')
    df_hpl = df_train.loc[df_train.author == 'HPL']
    plot_token_frequencies(author_df=df_hpl, referance_column='entities_types', title_prefix='HPL entities')
    df_mws = df_train.loc[df_train.author == 'MWS']
    plot_token_frequencies(author_df=df_mws, referance_column='entities_types', title_prefix='MWS entities')

    # additional stats
    boxplot_length(df_train)
    boxplot_char_length(df_train)
    plot_panctuation_use(df_train)
    plot_noun_use(df_train)
    plot_author_polarity(df_train)

# input args: path for external input data
if __name__ == '__main__':
    if len(sys.argv) > 1:
        print("reading from external data file")
        input_data_path = sys.argv[1]
        df_train = pd.read_csv(input_data_path)
        print("preprocess data")
        preprocess_text(df_train)
    else:
        df_train = load_50_authors_preprocessed_data()

    print("data information: ")
    print(df_train.info())

    author_bar_plot(df_train)
    df_train['text_cleaned2'] = df_train['text_cleaned'].str.replace('-PRON-', '')

    # plot common words per author
    print("plotting common words per author:")
    for label in set(df_train['author']):
        df_label = df_train[df_train['author'] == label]
        author_name = label.replace('\\', '')
        plot_token_frequencies(author_df=df_label, title_prefix=author_name + '_word',
                               output_path='output_charts//word_frquencies//')

    #  plot common enteties per author
    print("plotting common entities per author:")
    df_train['entities_types'] = df_train.text_with_entities.apply(seperate_entity_types,
                                                                   "plot_enteties_freq_per_author")
    for label in set(df_train['author']):
        df_label = df_train[df_train['author'] == label]
        author_name = label.replace('\\', '')
        plot_token_frequencies(author_df=df_label, referance_column='entities_types',
                               title_prefix=author_name + '_entities',
                               output_path='output_charts//entities_frequencies//')

    # additional stats
    print("plotting additional stats:")
    boxplot_length(df_train, out_folder='output_charts//')
    df_train['char_cnt'] = df_train.text.apply(len)
    boxplot_char_length(df_train, out_folder='output_charts//')
    plot_panctuation_use(df_train, out_folder='output_charts//')
    plot_noun_use(df_train, out_folder='output_charts//')
    plot_author_polarity(df_train, out_folder='output_charts//')


#!/usr/bin/env python

from setuptools import setup, find_packages

with open("README.md", "r") as fh:
   long_description = fh.read()

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

setup(
   name='airflow-bigquerylogger',
   version='0.4.5',
   description='BigQuery logger handler for Airflow',
   long_description=long_description,
   long_description_content_type="text/markdown",
   author='Gabriele Diener',
   author_email='gabriele.diener@gmail.com',
   install_requires=requires,
   packages=find_packages(),
   classifiers=[
      "Programming Language :: Python :: 3",
      "License :: OSI Approved :: MIT License",
      "Operating System :: OS Independent",
   ],
   python_requires='>=3.6'
)


from PyQt5.QtWidgets import QMainWindow
from PyQt5.QtGui import QStandardItem, QStandardItemModel
from PyQt5 import QtCore
from UI.ui_main import Ui_MainWindow
from UI.settings import SettingsUI
from UI.sequence import SequenceUI
from UI.updater import UpdaterUI
from database import Settings, Data
from thread_controller import ControllerThread
from thread_autopilot import AutopilotThread
from thread_recording import RecordingThread
from thread_training import TrainingThread
import sys

class MainUI(object):
    def __init__(self):
        self.window = QMainWindow()
        self.ui = Ui_MainWindow()
        self.ui.setupUi(self.window)

        # Register other windows
        self.settings_ui = SettingsUI()
        self.sequence_ui = SequenceUI()
        self.updater_ui = UpdaterUI()

        # Define thread variables
        self.thread_controller = None
        self.thread_training = None
        self.thread_autopilot = None
        self.thread_recording = None

        # Register buttons and stuff
        self.ui.actionSettings.triggered.connect(self.settings_ui.show)
        self.ui.actionExit.triggered.connect(sys.exit)
        self.ui.actionUpdater.triggered.connect(self.updater_ui.show)
        self.ui.actionAbout.triggered.connect(self.show_info)

        self.ui.b_sequenceApply.clicked.connect(self.append_sequence_changes)
        self.ui.b_sequenceDetails.clicked.connect(self.show_sequence_details)
        self.ui.b_sequenceDelete.clicked.connect(self.delete_selected_sequence)
        self.ui.sequence_list.clicked.connect(self.fill_sequence_data_fields)

        self.ui.b_mode.clicked.connect(self.enter_mode)

        self.fill_sequence_list()

        # Try to start controller thread
        if Settings().get_value(Settings.CONTROLLER) is not None and Settings().get_value(Settings.VJOY_DEVICE) is not None:
            self.thread_controller = ControllerThread()
            self.thread_controller.start()

    def __exit__(self, exc_type, exc_val, exc_tb):
        if self.thread_controller is not None and self.thread_controller.is_alive():
            print(self.thread_controller.is_alive())
            self.thread_controller.stop()
        if self.thread_autopilot is not None and self.thread_autopilot.is_alive():
            self.thread_autopilot.stop()
        if self.thread_recording is not None and self.thread_recording.is_alive():
            self.thread_recording.stop()
        if self.thread_training is not None and self.thread_training.is_alive():
            self.thread_training.stop()

    def show(self):
        self.window.show()

    def hide(self):
        pass

    def show_info(self):
        """
        actionAbout:
        Show window with program info.
        """
        pass

    def _get_selected_sequence(self):
        selection_list = self.ui.sequence_list.selectedIndexes()
        if len(selection_list) > 0:
            return selection_list[0].data(QtCore.Qt.UserRole)
        else:
            return None

    def fill_sequence_list(self):
        """
        Fill sequence_list with data.
        """
        data = Data()
        sequence_list = self.ui.sequence_list

        model = QStandardItemModel(sequence_list)
        sequences = data.get_sequence_list()
        if len(sequences) > 0:
            for sequence in sequences:
                note = ""
                if sequence[4] is not None:
                    note = " - %s" % sequence[4]
                item = QStandardItem("%s%s" % (sequence[1], note))
                item.setEditable(False)
                item.setData(str(sequence[0]), QtCore.Qt.UserRole)
                model.insertRow(0, item)
        sequence_list.setModel(model)

    def fill_sequence_data_fields(self):
        """
        Set text of e_country and choose right cb_roadtype.
        """
        sid = self._get_selected_sequence()
        if sid:
            sequence_data = Data().get_sequence_data(sid)
            if sequence_data:
                code = Data().get_country_code(sequence_data[1])
                self.ui.e_country.setText(code)
                self.ui.cb_roadtype.setCurrentIndex(sequence_data[2]+1)

    def append_sequence_changes(self):
        """
        b_sequenceApply:
        Update data of selected sequence.
        """
        sid = self._get_selected_sequence()
        code = self.ui.e_country.text()
        road_type = self.ui.cb_roadtype.currentIndex()-1
        Data().update_sequence(sid, code, road_type)

    def delete_selected_sequence(self):
        """
        b_sequenceDelete:
        Delete the selected sequence.
        """
        sid = self._get_selected_sequence()
        Data().delete_sequence(sid)
        self.fill_sequence_list()

    def show_sequence_details(self):
        """
        b_sequenceDetails:
        Show window with all images of the selected sequence.
        """
        sid = self._get_selected_sequence()
        if sid:
            self.sequence_ui.set_sequence_id(sid)
            self.sequence_ui.show()

    def enter_mode(self):
        """
        b_mode:
        Starts the autopilot, recording or training.
        """
        rb_autopilot = self.ui.mode_autopilot.isChecked()
        rb_recording = self.ui.mode_recording.isChecked()
        rb_training = self.ui.mode_training.isChecked()

        # Start the controller thread
        if self.thread_controller is not None:
            self.thread_controller.stop()
        self.thread_controller = None
        self.thread_controller = ControllerThread()
        self.thread_controller.start()

        # Start mode specific thread
        if rb_autopilot:
            self.thread_autopilot = AutopilotThread(self.ui.statusbar, self.thread_controller, self.ui.steering_wheel, self.ui.image_front)
            self.thread_autopilot.start()
        elif rb_recording:
            self.thread_recording = RecordingThread(self.ui.statusbar, self.ui.image_front, self.fill_sequence_list)
            self.thread_recording.start()
        elif rb_training:
            self.thread_training = TrainingThread(self.ui.statusbar)
            self.thread_training.start()

        # Deactivate radio boxes while on mode is active
        self.ui.mode_autopilot.setEnabled(False)
        self.ui.mode_training.setEnabled(False)
        self.ui.mode_recording.setEnabled(False)

        self.ui.b_mode.clicked.disconnect()
        self.ui.b_mode.clicked.connect(self.leave_mode)
        self.ui.b_mode.setText("Stop")

    def leave_mode(self):
        """
        b_mode:
        Stops the autopilot, recording or training.
        """
        rb_autopilot = self.ui.mode_autopilot.isChecked()
        rb_recording = self.ui.mode_recording.isChecked()
        rb_training = self.ui.mode_training.isChecked()

        # Stop mode specific thread
        if rb_autopilot:
            self.thread_autopilot.stop()
            self.thread_autopilot = None
        elif rb_recording:
            self.thread_recording.stop()
            self.thread_recording = None
        elif rb_training:
            self.thread_training.stop()
            self.thread_training = None

        # Show recorded corrections
        self.fill_sequence_list()

        self.ui.mode_autopilot.setEnabled(True)
        self.ui.mode_training.setEnabled(True)
        self.ui.mode_recording.setEnabled(True)

        self.ui.b_mode.clicked.disconnect()
        self.ui.b_mode.clicked.connect(self.enter_mode)
        self.ui.b_mode.setText("Start")


""" Handler for logging in security.log.csv files
"""
from __future__ import absolute_import
from __future__ import division
from __future__ import print_function

import os

from DIRAC import gLogger, S_OK, S_ERROR, gConfig, rootPath
from DIRAC.Core.DISET.RequestHandler import RequestHandler
from DIRAC.Core.Utilities.File import mkDir
from DIRAC.FrameworkSystem.private.SecurityFileLog import SecurityFileLog
from DIRAC.FrameworkSystem.Client.SecurityLogClient import SecurityLogClient

__RCSID__ = "$Id$"

gSecurityFileLog = False

def initializeSecurityLoggingHandler(serviceInfo):
  global gSecurityFileLog

  serviceCS = serviceInfo['serviceSectionPath']
  dataPath = gConfig.getValue("%s/DataLocation" % serviceCS, "data/securityLog")
  dataPath = dataPath.strip()
  if "/" != dataPath[0]:
    dataPath = os.path.realpath("%s/%s" % (gConfig.getValue('/LocalSite/InstancePath', rootPath), dataPath))
  gLogger.info("Data will be written into %s" % dataPath)
  mkDir(dataPath)

  try:
    testFile = "%s/seclog.jarl.test" % dataPath
    with open(testFile, "w"):
      pass
    os.unlink(testFile)
  except IOError:
    gLogger.fatal("Can't write to %s" % dataPath)
    return S_ERROR("Data location is not writable")
  # Define globals
  gSecurityFileLog = SecurityFileLog(dataPath)
  SecurityLogClient().setLogStore(gSecurityFileLog)
  return S_OK()

class SecurityLoggingHandler(RequestHandler):

  types_logAction = [(list, tuple)]

  def export_logAction(self, secMsg):
    """ Log a single action
    """
    result = gSecurityFileLog.logAction(secMsg)
    if not result['OK']:
      return S_OK([(secMsg, result['Message'])])
    return S_OK()

  types_logActionBundle = [(list, tuple)]

  def export_logActionBundle(self, secMsgList):
    """ Log a list of actions
    """
    errorList = []
    for secMsg in secMsgList:
      result = gSecurityFileLog.logAction(secMsg)
      if not result['OK']:
        errorList.append((secMsg, result['Message']))
    if errorList:
      return S_OK(errorList)
    return S_OK()


import numpy as np
from multiprocessing import cpu_count
from n2 import HnswIndex
from typing import List

def kNN(matrix: np.ndarray, k: int) -> List[float]:
    index = HnswIndex(matrix.shape[1], 'L2')
    for sample in matrix:
        index.add_data(sample)
    index.build(m=32, max_m0=48, ef_construction=int(k * 1.1), n_threads=cpu_count())

    result = []
    for i in range(0, matrix.shape[0]):
        results = index.search_by_id(i, k, include_distances=True)
        result.append(np.mean(np.sqrt(np.array([dist for _, dist in results]))))
    return np.sort(result)


from django.urls import path
from .views import *

urlpatterns = [
    path('', MovieListView.as_view(), name='index'),
    path('<int:pk>/', MovieDetailView.as_view(), name='detail'),
    path('create/', MovieCreateView.as_view(), name='create'),
    path('update/<int:pk>/', MovieUpdateView.as_view(), name='update'),
    path('delete/<int:pk>/', MovieDeleteView.as_view(), name='delete'),
    path('api/movies/search/<id>', MovieListViewSearch.as_view())
    ]


#!/usr/bin/env python3
#
# calculate_shapelet_distances.py: Performs basic distance (dissimilarity)
# analysis of a set of shapelets. This permits post-processing the output
# of S3M, the main executable of this project.
#
# Input:  JSON file with shapelets
# Output: Matrix of pairwise distances of shapelets
#
# The output will be written to `stdout`.

import json
import sys

import numpy as np

from scipy.spatial.distance import sqeuclidean

def distance(S,T):
  """
  Calculates the Euclidean distance between two sequences of varying
  lengths, using early abandon if possible.
  """
  n, m = len(S), len(T)

  if n > m:
    n,m = m,n
    S,T = T,S

  min_distance = np.inf

  for i in range(0, m - n + 1):
    stop         = False
    sum_distance = 0.0

    for j,x in enumerate(S):
      y             = T[i+j]
      sum_distance += sqeuclidean(x, y)

      # Abandon calculations as soon as the best distance (so far) has
      # been surpassed---adding more values will only increase it.
      if sum_distance >= min_distance:
        stop = True
        break

    if not stop:
      min_distance = sum_distance

  return min_distance

if __name__ == "__main__":
  with open(sys.argv[1]) as f:
    data = json.load(f)

  shapelets = data["shapelets"]
  n         = len(shapelets)
  distances = np.zeros(shape=(n,n), dtype="float32")

  for i in range(n):
    for j in range(i+1,n):
      distances[i,j]                          \
        = distance(shapelets[i]["shapelet"],  \
                   shapelets[j]["shapelet"])

      distances[j,i] = distances[i,j]

  np.savetxt(sys.stdout, distances, fmt="%.8f")


import re
from flask import Flask, request, Response, render_template, redirect, url_for , session

# Create an instance of the Flask class and set the name of the application
app = Flask(__name__)

# Define a function to check if the user has answered at least one firewall security question
def has_answered_security_question():
    enable_firewall1 = request.form.get('enable_firewall1')
    enable_firewall2 = request.form.get('enable_firewall2')
    return enable_firewall1 is not None or enable_firewall2 is not None or request.method == 'GET'

# Define a Flask route for the root URL of the web application
@app.route('/')
def route():
        return redirect('/login')

@app.route('/index', methods=['GET','POST'])
def index():
    # If the request method is POST (i.e. the user has submitted data)
    if request.method == 'POST':
        # Check if the user has answered at least one firewall security question and if the answer is yes or no
        if not has_answered_security_question() or (request.form.get('question') == 'yes' or request.form.get('question') == 'no'):
            return "Please answer at least one security question with a yes or no response to access the input box."

        # Get the submitted data from the form
        data = request.form['data']

        # Check if the user wants to enable the first firewall security
        enable_firewall1 = request.form.get('enable_firewall1')
        if enable_firewall1 == 'yes':
            # Import the security_scan function from the first firewall_security module
            from firewall_security import security_scan

            # Call the security_scan function to check for potential security issues
            if security_scan(data):
                # If the data passes the security scan, return a success message
                return "Data submitted successfully!"
            else:
                # If potential security issues are found, return an error message
                return "Security scan detected potentially malicious content in your data."
        if enable_firewall1 == 'no':
            return "Data submitted successfully!"

        # Check if the user wants to enable the second firewall security
        enable_firewall2 = request.form.get('enable_firewall2')
        if enable_firewall2 == 'yes':
            # Import the security_scan function from the second firewall_security module
            from firewall_security import security_scan

            # Call the security_scan function to check for potential security issues
            if security_scan(data):
                # If the data passes the security scan, return a success message
                return "Data submitted successfully!"
            else:
                # If potential security issues are found, return an error message
                return "Security scan detected potentially malicious content in your data."

        if enable_firewall2 == 'no':
            return "Data submitted successfully!"
    # If neither firewall security is enabled, redirect the user to the login page
    else:
        return render_template('index.html')

# Define a Flask route for the login page
# Define a Flask route for the login page
@app.route('/login', methods=['GET', 'POST'])
def login():
    # If the request method is POST (i.e. the user has submitted login data)
    if request.method == 'POST':
        # Get the submitted username and password from the form
        return render_template('index.html')
    # If the request method is not POST, return an HTML form asking for login credentials
    else:
        return render_template('login.html')

@app.route('/get_student_name', methods=['GET'])
def get_student_name():
    sap_id = request.args.get('sap_id')
    return get_student_name(sap_id)

if __name__ == '__main__':
    # Start the Flask application and set it to run in debug mode
    app.run(host='localhost', port=8080, debug=True)