from cgi import parse_header
from collections import Counter
from csv import DictReader
from datetime import datetime
from io import StringIO
from operator import attrgetter, itemgetter
from random import choice
from uuid import UUID

import factory
import pytest
from dateutil.parser import parse as dateutil_parse
from django.conf import settings
from django.utils.timezone import utc
from freezegun import freeze_time
from rest_framework import status
from rest_framework.reverse import reverse

from datahub.company.models import OneListTier
from datahub.company.test.factories import CompanyFactory, ContactFactory, SubsidiaryFactory
from datahub.core import constants
from datahub.core.query_utils import get_bracketed_concat_expression, get_full_name_expression
from datahub.core.test_utils import (
    APITestMixin,
    create_test_user,
    format_csv_data,
    get_attr_or_none,
    join_attr_values,
    random_obj_for_queryset,
)
from datahub.core.utils import join_truthy_strings
from datahub.interaction.models import (
    CommunicationChannel,
    Interaction,
    InteractionPermission,
    PolicyArea,
    PolicyIssueType,
)
from datahub.interaction.test.factories import (
    CompanyInteractionFactory,
    CompanyInteractionFactoryWithPolicyFeedback,
    EventServiceDeliveryFactory,
    InteractionDITParticipantFactory,
    InvestmentProjectInteractionFactory,
    ServiceDeliveryFactory,
)
from datahub.investment.project.test.factories import ActiveInvestmentProjectFactory
from datahub.metadata.models import Sector
from datahub.metadata.test.factories import TeamFactory
from datahub.search.interaction import InteractionSearchApp
from datahub.search.interaction.views import (
    SearchInteractionExportAPIView,
    SearchInteractionPolicyFeedbackExportAPIView,
)

pytestmark = [
    pytest.mark.django_db,
    # Index objects for this search app only
    pytest.mark.opensearch_collector_apps.with_args(InteractionSearchApp),
]

@pytest.fixture
def interactions(opensearch_with_collector):
    """Sets up data for the tests."""
    data = []
    with freeze_time('2017-01-01 13:00:00'):
        company_1 = CompanyFactory(name='ABC Trading Ltd')
        company_2 = CompanyFactory(name='Little Puddle Ltd')
        data.extend([
            CompanyInteractionFactory(
                subject='Exports meeting',
                date=dateutil_parse('2017-10-30T00:00:00Z'),
                company=company_1,
                contacts=[
                    ContactFactory(company=company_1, first_name='Lee', last_name='Danger'),
                    ContactFactory(company=company_1, first_name='Francis', last_name='Brady'),
                    ContactFactory(company=company_1, first_name='Zanger Za', last_name='Qa'),
                ],
                dit_participants__adviser__first_name='Angela',
                dit_participants__adviser__last_name='Lawson',
            ),
            CompanyInteractionFactory(
                subject='a coffee',
                date=dateutil_parse('2017-04-05T00:00:00Z'),
                company=company_2,
                contacts=[
                    ContactFactory(company=company_1, first_name='Try', last_name='Slanger'),
                ],
                dit_participants__adviser__first_name='Zed',
                dit_participants__adviser__last_name='Zeddy',
            ),
            CompanyInteractionFactory(
                subject='Email about exhibition',
                date=dateutil_parse('2016-09-02T00:00:00Z'),
                company=company_2,
                contacts=[
                    ContactFactory(company=company_1, first_name='Caroline', last_name='Green'),
                ],
                dit_participants__adviser__first_name='Prime',
                dit_participants__adviser__last_name='Zeddy',
            ),
            CompanyInteractionFactory(
                subject='talking about cats',
                date=dateutil_parse('2018-02-01T00:00:00Z'),
                company=company_2,
                contacts=[
                    ContactFactory(company=company_1, first_name='Full', last_name='Bridge'),
                ],
                dit_participants__adviser__first_name='Low',
                dit_participants__adviser__last_name='Tremon',
            ),
            CompanyInteractionFactory(
                subject='Event at HQ',
                date=dateutil_parse('2018-01-01T00:00:00Z'),
                company=company_2,
                contacts=[
                    ContactFactory(company=company_1, first_name='Diane', last_name='Pree'),
                ],
                dit_participants__adviser__first_name='Trevor',
                dit_participants__adviser__last_name='Saleman',
            ),
        ])

    opensearch_with_collector.flush_and_refresh()

    yield data

class TestInteractionEntitySearchView(APITestMixin):
    """Tests interaction search views."""

    def test_interaction_search_no_permissions(self):
        """Should return 403"""
        user = create_test_user(dit_team=TeamFactory())
        api_client = self.create_api_client(user=user)
        url = reverse('api-v3:search:interaction')
        response = api_client.get(url)
        assert response.status_code == status.HTTP_403_FORBIDDEN

    def test_get_all(self, interactions):
        """
        Tests that all interactions are returned with an empty POST body.
        """
        url = reverse('api-v3:search:interaction')

        response = self.api_client.post(url, {})

        assert response.status_code == status.HTTP_200_OK
        response_data = response.json()
        assert response_data['count'] == len(interactions)
        expected_ids = Counter(str(interaction.id) for interaction in interactions)
        assert Counter([item['id'] for item in response_data['results']]) == expected_ids

    def test_limit(self, interactions):
        """Tests that results can be limited."""
        url = reverse('api-v3:search:interaction')

        request_data = {
            'limit': 1,
        }
        response = self.api_client.post(url, request_data)

        assert response.status_code == status.HTTP_200_OK
        response_data = response.json()
        assert len(response_data['results']) == 1

    def test_offset(self, interactions):
        """Tests that results can be offset."""
        url = reverse('api-v3:search:interaction')

        request_data = {
            'offset': 1,
        }
        response = self.api_client.post(url, request_data)

        assert response.status_code == status.HTTP_200_OK
        response_data = response.json()
        assert len(response_data['results']) == 4

    def test_default_sort(self, opensearch_with_collector):
        """Tests default sorting of results by date (descending)."""
        url = reverse('api-v3:search:interaction')

        dates = (
            datetime(2017, 2, 4, 13, 15, 0, tzinfo=utc),
            datetime(2017, 1, 4, 11, 23, 10, tzinfo=utc),
            datetime(2017, 9, 29, 3, 25, 15, tzinfo=utc),
            datetime(2017, 7, 5, 11, 44, 33, tzinfo=utc),
            datetime(2017, 2, 1, 18, 15, 1, tzinfo=utc),
        )
        CompanyInteractionFactory.create_batch(
            len(dates),
            date=factory.Iterator(dates),
        )
        opensearch_with_collector.flush_and_refresh()

        response = self.api_client.post(url, {})

        assert response.status_code == status.HTTP_200_OK
        response_data = response.json()

        sorted_dates = sorted(dates, reverse=True)
        expected_dates = [d.isoformat() for d in sorted_dates]
        assert response_data['count'] == len(dates)
        assert [item['date'] for item in response_data['results']] == expected_dates

    def test_sort_by_subject_asc(self, interactions):
        """Tests sorting of results by subject (ascending)."""
        url = reverse('api-v3:search:interaction')

        request_data = {
            'sortby': 'subject:asc',
        }
        response = self.api_client.post(url, request_data)

        assert response.status_code == status.HTTP_200_OK
        response_data = response.json()
        assert response_data['count'] == len(interactions)
        subjects = (interaction.subject for interaction in interactions)
        expected_subjects = list(sorted(subjects, key=lambda s: s.lower()))
        assert [item['subject'] for item in response_data['results']] == expected_subjects

    def test_sort_by_subject_desc(self, interactions):
        """Tests sorting of results by subject (ascending)."""
        url = reverse('api-v3:search:interaction')

        request_data = {
            'sortby': 'subject:desc',
        }
        response = self.api_client.post(url, request_data)

        assert response.status_code == status.HTTP_200_OK
        response_data = response.json()
        assert response_data['count'] == len(interactions)
        subjects = (interaction.subject for interaction in interactions)
        expected_subjects = list(sorted(subjects, key=lambda s: s.lower(), reverse=True))
        assert [item['subject'] for item in response_data['results']] == expected_subjects

    @pytest.mark.parametrize(
        'sortby,error',
        (
            ('date:backwards', '"backwards" is not a valid sort direction.'),
            ('gyratory:asc', '"gyratory" is not a valid choice for the sort field.'),
        ),
    )
    def test_sort_by_invalid_field(self, opensearch_with_collector, sortby, error):
        """Tests attempting to sort by an invalid field and direction."""
        url = reverse('api-v3:search:interaction')

        request_data = {
            'sortby': sortby,
        }
        response = self.api_client.post(url, request_data)

        assert response.status_code == status.HTTP_400_BAD_REQUEST
        response_data = response.json()
        assert response_data == {
            'sortby': [error],
        }

    @pytest.mark.parametrize(
        'term',
        (
            'exports',
            'meeting',
            'exports meeting',
            'danger',
            'dan',
            'dang',
            'FRANCIS',
            'angela',
            'angel',
            'ngel',
            'ela',
            'za',
            'QA',
        ),
    )
    def test_search_original_query(self, interactions, term):
        """Tests searching across fields for a particular interaction."""
        url = reverse('api-v3:search:interaction')

        request_data = {
            'original_query': term,
        }
        response = self.api_client.post(url, request_data)

        assert response.status_code == status.HTTP_200_OK
        response_data = response.json()
        interaction = interactions[0]
        assert response_data['count'] == 1
        results = response_data['results']

        for result in results:
            result['contacts'].sort(key=itemgetter('id'))
            result['companies'].sort(key=itemgetter('id'))
            result['dit_participants'].sort(
                key=lambda dit_participant: dit_participant['adviser']['id'],
            )

        assert results == [{
            'id': str(interaction.pk),
            'kind': interaction.kind,
            'date': interaction.date.isoformat(),
            'company': {
                'id': str(interaction.company.pk),
                'name': interaction.company.name,
                'trading_names': interaction.company.trading_names,
            },
            'companies': [{
                'id': str(company.pk),
                'name': company.name,
                'trading_names': company.trading_names,
            } for company in sorted(interaction.companies.all(), key=attrgetter('id'))],
            'company_sector': {
                'id': str(interaction.company.sector.pk),
                'name': interaction.company.sector.name,
                'ancestors': [{
                    'id': str(ancestor.pk),
                } for ancestor in interaction.company.sector.get_ancestors()],
            },
            'company_one_list_group_tier': {
                'id': interaction.company.get_one_list_group_tier().pk,
                'name': interaction.company.get_one_list_group_tier().name,
            } if interaction.company.get_one_list_group_tier() else None,
            'contacts': [
                {
                    'id': str(contact.pk),
                    'first_name': contact.first_name,
                    'name': contact.name,
                    'last_name': contact.last_name,
                }
                for contact in sorted(interaction.contacts.all(), key=attrgetter('id'))
            ],
            'is_event': None,
            'event': None,
            'service': {
                'id': str(interaction.service.pk),
                'name': interaction.service.name,
            },
            'subject': interaction.subject,
            'dit_participants': [
                {
                    'adviser': {
                        'id': str(dit_participant.adviser.pk),
                        'first_name': dit_participant.adviser.first_name,
                        'name': dit_participant.adviser.name,
                        'last_name': dit_participant.adviser.last_name,
                    },
                    'team': {
                        'id': str(dit_participant.team.pk),
                        'name': dit_participant.team.name,
                    },
                }
                for dit_participant in interaction.dit_participants.order_by('adviser__pk')
            ],
            'notes': interaction.notes,
            'communication_channel': {
                'id': str(interaction.communication_channel.pk),
                'name': interaction.communication_channel.name,
            },
            'investment_project': None,
            'investment_project_sector': None,
            'policy_areas': [],
            'policy_issue_types': [],
            'service_delivery_status': None,
            'grant_amount_offered': None,
            'net_company_receipt': None,
            'was_policy_feedback_provided': interaction.was_policy_feedback_provided,
            'created_on': interaction.created_on.isoformat(),
            'modified_on': interaction.modified_on.isoformat(),
        }]

    def test_filter_by_kind(self, opensearch_with_collector):
        """Tests filtering interaction by kind."""
        CompanyInteractionFactory.create_batch(10)
        service_deliveries = ServiceDeliveryFactory.create_batch(10)

        opensearch_with_collector.flush_and_refresh()

        url = reverse('api-v3:search:interaction')
        request_data = {
            'kind': Interaction.Kind.SERVICE_DELIVERY,
        }
        response = self.api_client.post(url, request_data)

        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()

        assert response_data['count'] == 10

        results = response_data['results']
        service_delivery_ids = {str(interaction.id) for interaction in service_deliveries}
        assert {result['id'] for result in results} == service_delivery_ids

    def test_filter_by_company_id(self, opensearch_with_collector):
        """Tests filtering interaction by company id."""
        companies = CompanyFactory.create_batch(10)
        CompanyInteractionFactory.create_batch(
            len(companies),
            company=factory.Iterator(companies),
        )
        opensearch_with_collector.flush_and_refresh()

        url = reverse('api-v3:search:interaction')
        request_data = {
            'company': companies[5].id,
        }
        response = self.api_client.post(url, request_data)

        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()

        assert response_data['count'] == 1

        results = response_data['results']
        assert results[0]['company']['id'] == str(companies[5].id)

    @pytest.mark.parametrize(
        'name_term,matched_company_name',
        (
            # name
            ('whiskers', 'whiskers and tabby'),
            ('whi', 'whiskers and tabby'),
            ('his', 'whiskers and tabby'),
            ('ers', 'whiskers and tabby'),
            ('1a', '1a'),

            # trading names
            ('maine coon egyptian mau', 'whiskers and tabby'),
            ('maine', 'whiskers and tabby'),
            ('mau', 'whiskers and tabby'),
            ('ine oon', 'whiskers and tabby'),
            ('ine mau', 'whiskers and tabby'),
            ('3a', '1a'),

            # non-matches
            ('whi lorem', None),
            ('wh', None),
            ('whe', None),
            ('tiger', None),
            ('panda', None),
            ('moine', None),
        ),
    )
    def test_filter_by_company_name(
        self, opensearch_with_collector, name_term, matched_company_name,
    ):
        """Tests filtering interaction by company name."""
        matching_company1 = CompanyFactory(
            name='whiskers and tabby',
            trading_names=['Maine Coon', 'Egyptian Mau'],
        )
        matching_company2 = CompanyFactory(
            name='1a',
            trading_names=['3a', '4a'],
        )
        non_matching_company = CompanyFactory(
            name='Pluto and pippo',
            trading_names=['eniam nooc', 'naitpyge uam'],
        )
        CompanyInteractionFactory(company=matching_company1)
        CompanyInteractionFactory(company=matching_company2)
        CompanyInteractionFactory(company=non_matching_company)

        opensearch_with_collector.flush_and_refresh()

        url = reverse('api-v3:search:interaction')

        response = self.api_client.post(
            url,
            data={
                'original_query': '',
                'company_name': name_term,
            },
        )

        assert response.status_code == status.HTTP_200_OK
        match = Interaction.objects.filter(company__name=matched_company_name).first()
        if match:
            assert response.data['count'] == 1
            assert len(response.data['results']) == 1
            assert response.data['results'][0]['id'] == str(match.id)
        else:
            assert response.data['count'] == 0
            assert len(response.data['results']) == 0

    def test_filter_by_one_list_tier_group(
        self,
        opensearch_with_collector,
    ):
        """
        Test that we can filter by one list tier group.
        """
        one_list_tier = OneListTier.objects.all().order_by('?')[0]
        company_1 = CompanyFactory(
            name='Global HQ Ltd',
            one_list_tier=one_list_tier,
        )
        company_2 = CompanyFactory(
            name='Regional Subsidiary Ltd',
            global_headquarters=company_1,
        )
        CompanyInteractionFactory(
            subject='Global HQ chat',
            company=company_1,
        )
        CompanyInteractionFactory(
            subject='Regional Subsidiary chat',
            company=company_2,
        )

        opensearch_with_collector.flush_and_refresh()

        url = reverse('api-v3:search:interaction')

        response = self.api_client.post(
            url,
            data={
                'company_one_list_group_tier': one_list_tier.id,
            },
        )

        assert response.status_code == status.HTTP_200_OK
        assert response.data['count'] == 2
        assert len(response.data['results']) == 2
        matched_interaction_subjects = {result['subject'] for result in response.data['results']}

        assert matched_interaction_subjects == {'Global HQ chat', 'Regional Subsidiary chat'}
        assert all(
            result['company_one_list_group_tier']['name'] == one_list_tier.name
            for result in response.data['results']
        )

    def test_filter_by_multiple_one_list_tier_groups(
        self,
        opensearch_with_collector,
    ):
        """
        Test that we can filter by multiple one list tier groups.
        """
        one_list_tiers = list(OneListTier.objects.all().order_by('?')[0:2])
        company_1 = CompanyFactory(
            name='Global HQ Ltd',
            one_list_tier=one_list_tiers[0],
        )
        company_2 = CompanyFactory(
            name='Other Company',
            one_list_tier=one_list_tiers[1],
        )
        CompanyInteractionFactory(
            subject='Global HQ chat',
            company=company_1,
        )
        CompanyInteractionFactory(
            subject='Other Company chat',
            company=company_2,
        )
        opensearch_with_collector.flush_and_refresh()

        url = reverse('api-v3:search:interaction')

        response = self.api_client.post(
            url,
            data={
                'company_one_list_group_tier': [tier.id for tier in one_list_tiers],
            },
        )

        expected_interaction_subjects = {
            'Global HQ chat',
            'Other Company chat',
        }
        assert response.status_code == status.HTTP_200_OK
        assert response.data['count'] == 2
        assert len(response.data['results']) == 2
        matched_interaction_subjects = {result['subject'] for result in response.data['results']}

        assert matched_interaction_subjects == expected_interaction_subjects

    @pytest.mark.parametrize(
        'created_on_exists',
        (True, False),
    )
    def test_filter_by_created_on_exists(self, opensearch_with_collector, created_on_exists):
        """Tests filtering interaction by created_on exists."""
        CompanyInteractionFactory.create_batch(3)
        no_created_on = CompanyInteractionFactory.create_batch(3)
        for interaction in no_created_on:
            interaction.created_on = None
            interaction.save()

        opensearch_with_collector.flush_and_refresh()

        url = reverse('api-v3:search:interaction')
        request_data = {
            'created_on_exists': created_on_exists,
        }
        response = self.api_client.post(url, request_data)

        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()
        results = response_data['results']
        assert response_data['count'] == 3
        assert all(
            (not result['created_on'] is None) == created_on_exists
            for result in results
        )

    @pytest.mark.parametrize('dit_participant_field', ('adviser', 'team'))
    def test_filter_by_dit_participant(self, opensearch_with_collector, dit_participant_field):
        """Test filtering interaction by DIT participant adviser and team IDs."""
        interactions = CompanyInteractionFactory.create_batch(10, dit_participants=[])
        for interaction in interactions:
            InteractionDITParticipantFactory.create_batch(2, interaction=interaction)

        opensearch_with_collector.flush_and_refresh()

        interaction = choice(interactions)
        dit_participant = interaction.dit_participants.order_by('?').first()

        url = reverse('api-v3:search:interaction')
        request_data = {
            f'dit_participants__{dit_participant_field}':
                getattr(dit_participant, dit_participant_field).id,
        }
        response = self.api_client.post(url, request_data)
        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()
        assert response_data['count'] == 1

        results = response_data['results']
        assert len(results) == 1
        assert results[0]['id'] == str(interaction.pk)

    def test_filter_by_communication_channel(self, opensearch_with_collector):
        """Tests filtering interaction by interaction type."""
        communication_channels = list(CommunicationChannel.objects.order_by('?')[:2])
        CompanyInteractionFactory.create_batch(
            5,
            communication_channel=communication_channels[0],
        )
        CompanyInteractionFactory.create_batch(
            5,
            communication_channel=communication_channels[1],
        )
        opensearch_with_collector.flush_and_refresh()

        url = reverse('api-v3:search:interaction')
        request_data = {
            'original_query': '',
            'communication_channel': communication_channels[1].pk,
        }
        response = self.api_client.post(url, request_data)

        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()

        assert response_data['count'] == 5

        results = response_data['results']
        result_ids = {result['communication_channel']['id'] for result in results}
        assert result_ids == {str(communication_channels[1].pk)}

    @pytest.mark.parametrize(
        'field,field_model',
        (
            ('policy_areas', PolicyArea),
            ('policy_issue_types', PolicyIssueType),
        ),
    )
    def test_filter_by_policy_fields(self, opensearch_with_collector, field, field_model):
        """
        Tests filtering interactions by:
        - policy area
        - policy issue type
        """
        values = list(field_model.objects.order_by('?')[:2])
        expected_field_value = values[0]
        other_field_value = values[1]

        factory_values = [
            [expected_field_value, other_field_value],
            [expected_field_value, other_field_value],
            [expected_field_value],
            [expected_field_value],
            [expected_field_value],
        ]

        expected_interactions = CompanyInteractionFactoryWithPolicyFeedback.create_batch(
            5,
            **{field: factory.Iterator(factory_values)},
        )

        # Unrelated interactions
        CompanyInteractionFactoryWithPolicyFeedback.create_batch(
            6,
            **{field: [other_field_value]},
        )
        CompanyInteractionFactory.create_batch(6)

        opensearch_with_collector.flush_and_refresh()

        url = reverse('api-v3:search:interaction')
        request_data = {
            'original_query': '',
            field: expected_field_value.pk,
        }
        response = self.api_client.post(url, request_data)
        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()
        results = response_data['results']
        expected_ids = {str(interaction.pk) for interaction in expected_interactions}

        assert response_data['count'] == 5
        assert Counter(
            value['id']
            for result in results
            for value in result[field]
        ) == {
            str(expected_field_value.pk): 5,
            # two interactions had both values
            str(other_field_value.pk): 2,
        }
        assert {result['id'] for result in results} == expected_ids

    def test_filter_by_service(self, opensearch_with_collector):
        """Tests filtering interaction by service."""
        CompanyInteractionFactory.create_batch(
            5,
            service_id=constants.Service.inbound_referral.value.id,
        )
        service_id = constants.Service.account_management.value.id
        CompanyInteractionFactory.create_batch(
            5,
            service_id=service_id,
        )
        opensearch_with_collector.flush_and_refresh()

        url = reverse('api-v3:search:interaction')
        request_data = {
            'service': service_id,
        }
        response = self.api_client.post(url, request_data)

        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()

        assert response_data['count'] == 5

        results = response_data['results']
        result_ids = {result['service']['id'] for result in results}
        assert result_ids == {str(service_id)}

    @pytest.mark.parametrize('was_policy_feedback_provided', (False, True))
    def test_filter_by_was_policy_feedback_provided(
        self,
        opensearch_with_collector,
        was_policy_feedback_provided,
    ):
        """Test filtering interactions by was_policy_feedback_provided."""
        interactions_without_policy_feedback = CompanyInteractionFactory.create_batch(5)
        interactions_with_policy_feedback = (
            CompanyInteractionFactoryWithPolicyFeedback.create_batch(5)
        )

        opensearch_with_collector.flush_and_refresh()

        url = reverse('api-v3:search:interaction')
        request_data = {
            'was_policy_feedback_provided': was_policy_feedback_provided,
        }
        response = self.api_client.post(url, data=request_data)
        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()
        expected_interactions = (
            interactions_with_policy_feedback if was_policy_feedback_provided
            else interactions_without_policy_feedback
        )
        assert response_data['count'] == len(expected_interactions)

        results = response_data['results']
        result_ids = {result['id'] for result in results}
        assert result_ids == {str(interaction.pk) for interaction in expected_interactions}

    @pytest.mark.parametrize(
        'data,results',
        (
            (
                {
                    'date_after': '2017-12-01',
                },
                {
                    'talking about cats',
                    'Event at HQ',
                },
            ),
            (
                {
                    'date_after': '2017-12-01',
                    'date_before': '2018-01-02',
                },
                {
                    'Event at HQ',
                },
            ),
            (
                {
                    'date_before': '2017-01-01',
                },
                {
                    'Email about exhibition',
                },
            ),
        ),
    )
    def test_filter_by_date(self, interactions, data, results):
        """Tests filtering interaction by date."""
        url = reverse('api-v3:search:interaction')
        response = self.api_client.post(url, data)

        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()
        names = {result['subject'] for result in response_data['results']}
        assert names == results

    @pytest.mark.parametrize(
        'sector_level',
        (0, 1, 2),
    )
    def test_sector_descends_filter_for_company_interaction(
            self,
            hierarchical_sectors,
            opensearch_with_collector,
            sector_level,
    ):
        """Test the sector_descends filter with company interactions."""
        num_sectors = len(hierarchical_sectors)
        sectors_ids = [sector.pk for sector in hierarchical_sectors]

        companies = CompanyFactory.create_batch(
            num_sectors,
            sector_id=factory.Iterator(sectors_ids),
        )
        company_interactions = CompanyInteractionFactory.create_batch(
            3,
            company=factory.Iterator(companies),
        )

        other_companies = CompanyFactory.create_batch(
            3,
            sector=factory.LazyFunction(lambda: random_obj_for_queryset(
                Sector.objects.exclude(pk__in=sectors_ids),
            )),
        )
        CompanyInteractionFactory.create_batch(
            3,
            company=factory.Iterator(other_companies),
        )

        opensearch_with_collector.flush_and_refresh()

        url = reverse('api-v3:search:interaction')
        body = {
            'sector_descends': hierarchical_sectors[sector_level].pk,
        }
        response = self.api_client.post(url, body)
        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()
        assert response_data['count'] == num_sectors - sector_level

        actual_ids = {UUID(interaction['id']) for interaction in response_data['results']}
        expected_ids = {interaction.pk for interaction in company_interactions[sector_level:]}
        assert actual_ids == expected_ids

    @pytest.mark.parametrize(
        'sector_level',
        (0, 1, 2),
    )
    def test_sector_descends_filter_for_investment_project_interaction(
            self,
            hierarchical_sectors,
            opensearch_with_collector,
            sector_level,
    ):
        """Test the sector_descends filter with investment project interactions."""
        num_sectors = len(hierarchical_sectors)
        sectors_ids = [sector.pk for sector in hierarchical_sectors]

        projects = ActiveInvestmentProjectFactory.create_batch(
            num_sectors,
            sector_id=factory.Iterator(sectors_ids),
        )
        investment_project_interactions = InvestmentProjectInteractionFactory.create_batch(
            3,
            investment_project=factory.Iterator(projects),
        )

        other_projects = ActiveInvestmentProjectFactory.create_batch(
            3,
            sector=factory.LazyFunction(lambda: random_obj_for_queryset(
                Sector.objects.exclude(pk__in=sectors_ids),
            )),
        )
        InvestmentProjectInteractionFactory.create_batch(
            3,
            investment_project=factory.Iterator(other_projects),
        )

        opensearch_with_collector.flush_and_refresh()

        url = reverse('api-v3:search:interaction')
        body = {
            'sector_descends': hierarchical_sectors[sector_level].pk,
        }
        response = self.api_client.post(url, body)
        assert response.status_code == status.HTTP_200_OK

        response_data = response.json()
        assert response_data['count'] == num_sectors - sector_level

        actual_ids = {UUID(interaction['id']) for interaction in response_data['results']}
        expected_ids = {
            interaction.pk for interaction in investment_project_interactions[sector_level:]
        }
        assert actual_ids == expected_ids

class TestInteractionExportView(APITestMixin):
    """Tests the interaction export view."""

    @pytest.mark.parametrize(
        'permissions',
        (
            (),
            (InteractionPermission.view_all,),
            (InteractionPermission.export,),
        ),
    )
    def test_user_without_permission_cannot_export(self, opensearch_with_collector, permissions):
        """Test that a user without the correct permissions cannot export data."""
        user = create_test_user(dit_team=TeamFactory(), permission_codenames=permissions)
        api_client = self.create_api_client(user=user)

        url = reverse('api-v3:search:interaction-export')
        response = api_client.post(url)
        assert response.status_code == status.HTTP_403_FORBIDDEN

    @pytest.mark.parametrize(
        'request_sortby,orm_ordering',
        (
            (None, '-date'),
            ('date', 'date'),
            ('company.name', 'company__name'),
        ),
    )
    def test_interaction_export(
        self,
        opensearch_with_collector,
        request_sortby,
        orm_ordering,
    ):
        """
        Test export of interaction search results with a policy feedback user.

        Checks that all interaction kinds except for policy feedback are included in the export.
        """
        # Faker generates job titles containing commas which complicates comparisons,
        # so all contact job titles are explicitly set
        company = CompanyFactory()
        interaction = CompanyInteractionFactory(
            company=company,
            contacts=[
                ContactFactory(company=company, job_title='Engineer'),
                ContactFactory(company=company, job_title=None),
                ContactFactory(company=company, job_title=''),
            ],
        )
        InteractionDITParticipantFactory.create_batch(2, interaction=interaction)
        InteractionDITParticipantFactory(interaction=interaction, team=None)
        InteractionDITParticipantFactory(
            interaction=interaction,
            adviser=None,
            team=factory.SubFactory(TeamFactory),
        )
        EventServiceDeliveryFactory(
            company=company,
            contacts=[
                ContactFactory(company=company, job_title='Managing director'),
            ],
        )
        InvestmentProjectInteractionFactory(
            company=company,
            contacts=[
                ContactFactory(company=company, job_title='Exports manager'),
            ],
        )
        ServiceDeliveryFactory(
            company=company,
            contacts=[
                ContactFactory(company=company, job_title='Sales director'),
            ],
        )
        CompanyInteractionFactoryWithPolicyFeedback(
            company=company,
            contacts=[
                ContactFactory(company=company, job_title='Business development manager'),
            ],
            policy_areas=PolicyArea.objects.order_by('?')[:2],
            policy_issue_types=PolicyIssueType.objects.order_by('?')[:2],
        )

        opensearch_with_collector.flush_and_refresh()

        data = {}
        if request_sortby:
            data['sortby'] = request_sortby

        url = reverse('api-v3:search:interaction-export')

        with freeze_time('2018-01-01 11:12:13'):
            response = self.api_client.post(url, data=data)

        assert response.status_code == status.HTTP_200_OK
        assert parse_header(response.get('Content-Type')) == ('text/csv', {'charset': 'utf-8'})
        assert parse_header(response.get('Content-Disposition')) == (
            'attachment', {'filename': 'Data Hub - Interactions - 2018-01-01-11-12-13.csv'},
        )
        sorted_interactions = Interaction.objects.order_by(
            orm_ordering,
            'pk',
        )
        reader = DictReader(StringIO(response.getvalue().decode('utf-8-sig')))

        assert reader.fieldnames == list(SearchInteractionExportAPIView.field_titles.values())

        expected_row_data = [
            {
                'Date': interaction.date,
                'Type': interaction.get_kind_display(),
                'Service': get_attr_or_none(interaction, 'service.name'),
                'Subject': interaction.subject,
                'Link': f'{settings.DATAHUB_FRONTEND_URL_PREFIXES["interaction"]}'
                        f'/{interaction.pk}',
                'Company': get_attr_or_none(interaction, 'company.name'),
                'Company link':
                    f'{settings.DATAHUB_FRONTEND_URL_PREFIXES["company"]}'
                    f'/{interaction.company.pk}',
                'Company country': get_attr_or_none(
                    interaction,
                    'company.address_country.name',
                ),
                'Company UK region': get_attr_or_none(interaction, 'company.uk_region.name'),
                'Company sector': get_attr_or_none(interaction, 'company.sector.name'),
                'Contacts': _format_expected_contacts(interaction),
                'Advisers': _format_expected_advisers(interaction),
                'Event': get_attr_or_none(interaction, 'event.name'),
                'Communication channel':
                    get_attr_or_none(interaction, 'communication_channel.name'),
                'Service delivery status': get_attr_or_none(
                    interaction,
                    'service_delivery_status.name',
                ),
                'Net company receipt': interaction.net_company_receipt,
                'Policy issue types': join_attr_values(
                    interaction.policy_issue_types.order_by('name'),
                ),
                'Policy areas': join_attr_values(
                    interaction.policy_areas.order_by('name'),
                    separator='; ',
                ),
                'Policy feedback notes': interaction.policy_feedback_notes,
            }
            for interaction in sorted_interactions
        ]

        # DictReader uses OrderedDicts, we convert them to normal dicts to get better errors
        # when the assertion fails
        actual_row_data = [dict(item) for item in reader]

        assert actual_row_data == format_csv_data(expected_row_data)

    @pytest.mark.parametrize(
        'request_sortby,orm_ordering',
        (
            (None, '-date'),
            ('date', 'date'),
            ('company.name', 'company__name'),
        ),
    )
    def test_policy_feedback_export(
        self,
        opensearch_with_collector,
        request_sortby,
        orm_ordering,
    ):
        """
        Test export of interaction policy feedback
        """
        # Faker generates job titles containing commas which complicates comparisons,
        # so all contact job titles are explicitly set
        company = SubsidiaryFactory()
        interaction = CompanyInteractionFactory(
            company=company,
            contacts=[
                ContactFactory(company=company, job_title='Engineer'),
                ContactFactory(company=company, job_title=None),
                ContactFactory(company=company, job_title=''),
            ],
        )
        InteractionDITParticipantFactory.create_batch(2, interaction=interaction)
        InteractionDITParticipantFactory(interaction=interaction, team=None)
        InteractionDITParticipantFactory(
            interaction=interaction,
            adviser=None,
            team=factory.SubFactory(TeamFactory),
        )
        EventServiceDeliveryFactory(
            company=company,
            contacts=[
                ContactFactory(company=company, job_title='Managing director'),
            ],
        )
        InvestmentProjectInteractionFactory(
            company=company,
            contacts=[
                ContactFactory(company=company, job_title='Exports manager'),
            ],
        )
        ServiceDeliveryFactory(
            company=company,
            contacts=[
                ContactFactory(company=company, job_title='Sales director'),
            ],
        )
        CompanyInteractionFactoryWithPolicyFeedback(
            company=company,
            contacts=[
                ContactFactory(company=company, job_title='Business development manager'),
            ],
            policy_areas=PolicyArea.objects.order_by('?')[:2],
            policy_issue_types=PolicyIssueType.objects.order_by('?')[:2],
        )

        opensearch_with_collector.flush_and_refresh()

        data = {}
        if request_sortby:
            data['sortby'] = request_sortby

        url = reverse('api-v3:search:interaction-policy-feedback')

        with freeze_time('2018-01-01 11:12:13'):
            response = self.api_client.post(url, data=data)

        assert response.status_code == status.HTTP_200_OK
        assert parse_header(response.get('Content-Type')) == ('text/csv', {'charset': 'utf-8'})
        assert parse_header(response.get('Content-Disposition')) == (
            'attachment', {'filename': 'Data Hub - Interactions - 2018-01-01-11-12-13.csv'},
        )
        sorted_interactions = Interaction.objects.order_by(
            orm_ordering,
            'pk',
        )
        reader = DictReader(StringIO(response.getvalue().decode('utf-8-sig')))

        assert reader.fieldnames == list(
            SearchInteractionPolicyFeedbackExportAPIView.field_titles.values(),
        )

        expected_row_data = [
            {
                'Date': interaction.date,
                'Created date': interaction.created_on,
                'Modified date': interaction.modified_on,
                'Link': f'{settings.DATAHUB_FRONTEND_URL_PREFIXES["interaction"]}'
                        f'/{interaction.pk}',
                'Service': get_attr_or_none(interaction, 'service.name'),
                'Subject': interaction.subject,
                'Company': get_attr_or_none(interaction, 'company.name'),
                'Parent': get_attr_or_none(
                    interaction,
                    'company.global_headquarters.name',
                ),
                'Parent country': get_attr_or_none(
                    interaction,
                    'company.global_headquarters.address_country.name',
                ),
                'Company country': get_attr_or_none(
                    interaction,
                    'company.address_country.name',
                ),
                'Company UK region': get_attr_or_none(interaction, 'company.uk_region.name'),
                'One List Tier': get_attr_or_none(interaction, 'company.one_list_tier.name'),
                'Company sector': get_attr_or_none(interaction, 'company.sector.name'),
                'Company sector cluster': get_attr_or_none(
                    interaction,
                    'company.sector.sector_cluster.name',
                ),
                'turnover': get_attr_or_none(interaction, 'company.turnover'),
                'number_of_employees': get_attr_or_none(
                    interaction,
                    'company.number_of_employees',
                ),
                'team_names': _format_expected_team_names(interaction),
                'team_countries': _format_expected_team_countries(interaction),
                'kind_name': interaction.get_kind_display(),
                'Communication channel':
                    get_attr_or_none(interaction, 'communication_channel.name'),
                'was_policy_feedback_provided': interaction.was_policy_feedback_provided,
                'Policy issue types': join_attr_values(
                    interaction.policy_issue_types.order_by('name'),
                ),
                'Policy areas': join_attr_values(
                    interaction.policy_areas.order_by('name'),
                    separator='; ',
                ),
                'Policy feedback notes': interaction.policy_feedback_notes,
                'advisers': _format_expected_advisers(interaction),
                'adviser_emails': _format_expected_adviser_emails(interaction),
                'tag_1': '',
                'probability_score_tag_1': '',
                'tag_2': '',
                'probability_score_tag_2': '',
                'tag_3': '',
                'probability_score_tag_3': '',
                'tag_4': '',
                'probability_score_tag_4': '',
                'tag_5': '',
                'probability_score_tag_5': '',

                'Contacts': _format_expected_contacts(interaction),
                'Event': get_attr_or_none(interaction, 'event.name'),
                'Service delivery status': get_attr_or_none(
                    interaction,
                    'service_delivery_status.name',
                ),
                'Net company receipt': interaction.net_company_receipt,
            }
            for interaction in sorted_interactions
        ]

        # DictReader uses OrderedDicts, we convert them to normal dicts to get better errors
        # when the assertion fails
        actual_row_data = [dict(item) for item in reader]

        assert actual_row_data == format_csv_data(expected_row_data)

class TestInteractionBasicSearch(APITestMixin):
    """Tests searching for interactions via basic (global) search."""

    @pytest.mark.parametrize(
        'term',
        (
            'exports',
            'meeting',
            'exports meeting',
            'danger',
            'dan',
            'dang',
            'FRANCIS',
            'angela',
            'angel',
            'ngel',
            'ela',
            'za',
            'QA',
        ),
    )
    def test_search(self, interactions, term):
        """Tests searching for various search terms."""
        url = reverse('api-v3:search:basic')

        request_data = {
            'term': term,
            'entity': 'interaction',
        }
        response = self.api_client.get(url, request_data)

        assert response.status_code == status.HTTP_200_OK
        response_data = response.json()
        interaction = interactions[0]
        assert response_data['count'] >= 1
        results = response_data['results']

        for result in results:
            result['contacts'].sort(key=itemgetter('id'))
            result['companies'].sort(key=itemgetter('id'))
            result['dit_participants'].sort(
                key=lambda dit_participant: dit_participant['adviser']['id'],
            )

        assert results[0] == {
            'id': str(interaction.pk),
            'kind': interaction.kind,
            'date': interaction.date.isoformat(),
            'company': {
                'id': str(interaction.company.pk),
                'name': interaction.company.name,
                'trading_names': interaction.company.trading_names,
            },
            'companies': [
                {
                    'id': str(company.pk),
                    'name': company.name,
                    'trading_names': company.trading_names,
                } for company in sorted(interaction.companies.all(), key=attrgetter('id'))
            ],
            'company_one_list_group_tier': {
                'id': interaction.company.get_one_list_group_tier().pk,
                'name': interaction.company.get_one_list_group_tier().name,
            } if interaction.company.get_one_list_group_tier() else None,
            'company_sector': {
                'id': str(interaction.company.sector.pk),
                'name': interaction.company.sector.name,
                'ancestors': [{
                    'id': str(ancestor.pk),
                } for ancestor in interaction.company.sector.get_ancestors()],
            },
            'contacts': [
                {
                    'id': str(contact.pk),
                    'first_name': contact.first_name,
                    'name': contact.name,
                    'last_name': contact.last_name,
                }
                for contact in sorted(interaction.contacts.all(), key=attrgetter('id'))
            ],
            'is_event': None,
            'event': None,
            'service': {
                'id': str(interaction.service.pk),
                'name': interaction.service.name,
            },
            'subject': interaction.subject,
            'dit_participants': [
                {
                    'adviser': {
                        'id': str(dit_participant.adviser.pk),
                        'first_name': dit_participant.adviser.first_name,
                        'name': dit_participant.adviser.name,
                        'last_name': dit_participant.adviser.last_name,
                    },
                    'team': {
                        'id': str(dit_participant.team.pk),
                        'name': dit_participant.team.name,
                    },
                }
                for dit_participant in interaction.dit_participants.order_by('adviser__pk')
            ],
            'notes': interaction.notes,
            'communication_channel': {
                'id': str(interaction.communication_channel.pk),
                'name': interaction.communication_channel.name,
            },
            'investment_project': None,
            'investment_project_sector': None,
            'policy_areas': [],
            'policy_issue_types': [],
            'service_delivery_status': None,
            'grant_amount_offered': None,
            'net_company_receipt': None,
            'was_policy_feedback_provided': interaction.was_policy_feedback_provided,
            'created_on': interaction.created_on.isoformat(),
            'modified_on': interaction.modified_on.isoformat(),
        }

def _format_expected_contacts(interaction):
    queryset = interaction.contacts.order_by(
        get_full_name_expression(bracketed_field_name='job_title'),
    )

    return ', '.join(
        _format_expected_contact_name(contact) for contact in queryset
    )

def _format_expected_contact_name(contact):
    if contact.job_title:
        return f'{contact.name} ({contact.job_title})'

    return f'{contact.name}'

def _format_expected_team_names(interaction):
    queryset = interaction.dit_participants.order_by(
        'team__name',
    )
    return ', '.join(
        dit_participant.team.name for dit_participant in queryset if dit_participant.team
    )

def _format_expected_team_countries(interaction):
    queryset = interaction.dit_participants.order_by(
        'team__name',
    )

    return ', '.join(
        dit_participant.team.country.name for dit_participant in queryset if dit_participant.team
    )

def _format_expected_advisers(interaction):
    queryset = interaction.dit_participants.order_by(
        get_bracketed_concat_expression(
            'adviser__first_name',
            'adviser__last_name',
            expression_to_bracket='team__name',
        ),
    )

    return ', '.join(
        _format_expected_adviser_name(dit_participant) for dit_participant in queryset
    )

def _format_expected_adviser_emails(interaction):
    queryset = interaction.dit_participants.order_by('adviser__email')

    return ', '.join(
        dit_participant.adviser.email for dit_participant in queryset if dit_participant.adviser
    )

def _format_expected_adviser_name(dit_participant):
    adviser_name = dit_participant.adviser.name if dit_participant.adviser else ''
    team_name = f'({dit_participant.team.name})' if dit_participant.team else ''
    return join_truthy_strings(adviser_name, team_name)


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

# In[63]:

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
from sklearn.linear_model import LogisticRegression
from sklearn.metrics import accuracy_score
x_data = np.loadtxt('X.dat')
y_data = np.loadtxt('y.dat')
#x_data =  pd.read_csv('x.csv', sep=' ', header=None)
#y_data = pd.read_csv('y.dat', header=None)

# In[64]:

reg = LogisticRegression(penalty='none', fit_intercept=False).fit(x_data, y_data)
reg.score(x_data, y_data)
reg.coef_
reg.intercept_
#reg.predict(np.array([[3, 5]]))
print(reg.score(x_data, y_data))
print(reg.coef_)
print(reg.coef_[0][1])
print(reg.intercept_)
w1 = reg.coef_[0][0]
w2 = reg.coef_[0][1]

# In[65]:

# Accuracy of the scikit learn model
print(reg.score(x_data, y_data))

# In[66]:

def sigmoid(x):
    return 1 / (1 + np.exp(-x))

# In[67]:

## Logistic Regression with SSE
#l_sse=sum((y_data-sigmoid(x_data.dot(w[i,:]))**2))

y_data[y_data == -1] = 0
y_data=y_data.reshape((400,1))

epoch = 100
lr = 0.001
w = np.zeros((epoch,2))
w[0,:] = [1,-1]

for i in range(epoch-1):
    lsw = sigmoid(np.dot(w[i,:],x_data.T)).reshape((400,1))
    dif_l_sse = sum(
        2*(y_data-lsw)
        *(-lsw)
        *(1-lsw)
        *x_data
)
    w[i+1] = w[i] - lr * dif_l_sse

# In[68]:

plt.figure(figsize=(17, 5))
plt.plot(w[:,0],w[:,1],'.')
plt.title('Weight trajectory of LSSE')
plt.show()

# In[69]:

## Logistic Regression with ML

epoch = 100
lr = 0.001
w2 = np.zeros((epoch,2))
w2[0,:] = [1,-1]

for i in range(epoch-1):
    #l_sse=sum((y_data-sigmoid(x_data.dot(w[i,:]))**2))
    lsw = sigmoid(np.dot(w2[i,:],x_data.T)).reshape((400,1))
    dif_l_sse = sum(
        (y_data*(1-lsw)
        -(1-y_data)*lsw)*x_data
)
    w2[i+1] = w2[i] + lr * dif_l_sse

# In[70]:

lsw = sigmoid(np.dot(w[0,:],x_data.T)).reshape((400,1))
dif_l_sse = sum(
        (y_data*(1-lsw)
        -(1-y_data)*lsw)*x_data
)
#w2[i+1] = w2[i] - lr * dif_l_sse
print(dif_l_sse)

# In[71]:

plt.figure(figsize=(17, 5))
plt.plot(w2[:,0],w2[:,1],'.')
plt.title('Weight trajectory of LML')
plt.legend(['Lsse', 'LML'])
plt.show()

# In[78]:

plt.figure(figsize=(17, 5))
plt.plot(w[:,0],w[:,1],'r.')
plt.plot(w2[:,0],w2[:,1],'.')
plt.plot(reg.coef_[0][0],reg.coef_[0][1], '^', markersize=20)
plt.title('Weight trajectory of LML and LSSE')
plt.legend(['Lsse', 'LML','Scikit learn'])
plt.show()


import tensorflow as tf
import sys
sys.path.append('tf-serving/tf_models/textsum')
import seq2seq_attention_model
import data

if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser()
    parser.add_argument('--content', metavar='content', )
    args = parser.parse_args()
    hps = seq2seq_attention_model.HParams(
        mode='eval',  # train, eval, decode
        min_lr=0.01,  # min learning rate.
        lr=0.15,  # learning rate
        batch_size=1,
        enc_layers=4,
        enc_timesteps=120,
        dec_timesteps=30,
        min_input_len=2,  # discard articles/summaries < than this
        num_hidden=256,  # for rnn cell
        emb_dim=128,  # If 0, don't use embedding
        max_grad_norm=2,
        num_softmax_samples=4096)

    vocab = data.Vocab('vocabulary.txt', 1000000)
    model = seq2seq_attention_model.Seq2SeqAttentionModel(hps, vocab, num_gpus=0)
    model.build_graph()
    saver = tf.train.Saver()
    sess = tf.Session(config=tf.ConfigProto(allow_soft_placement=True))
    ckpt_state = tf.train.get_checkpoint_state('model_save')
    (summaries, loss, train_step) = model.run_eval_step(
        sess, [args.content], [''], targets, article_lens,
        abstract_lens, loss_weights)


import json
from typing import Optional

import requests
from pydantic import BaseModel

class MintResponse(BaseModel):
    success: bool
    message: Optional[str]

def get_response(address: str) -> MintResponse:
    url = f"https://qr-mint.g7p.io/api/checkWhitelist?wallet={address}"
    response = requests.get(url=url)
    return MintResponse.parse_obj(json.loads(response.content))

if __name__ == '__main__':
    with open('address.txt') as file:
        lines = [line for line in file.read().splitlines() if line]

    for num, address in enumerate(lines):
        if address:
            try:
                response = get_response(address=address)
                if response.message:
                    print(f'#{num + 1} | {address} | {response.success}, {response.message}')
                else:
                    print(f'#{num + 1} | {address} | {response.success}.')
            except Exception as e:
                print(e.args)


from p5 import *
import hectorASM as asm

# Variables

scene = 'init'

# Elements

class Paddel:
    def __init__(self, height, pos, vel):
        self.width = 50
        self.heigth = height
        self.pos = pos
        self.vel = vel
        self.moving = 0

ball = {
    'radius' : 50,
    'pos' : [50, 50],
    'color' : [255, 255, 255],
    'vel' : [10, 10]
}

leftPaddel = None
rightPaddle = None

# p5 methods

def setup():
    global leftPaddel, rightPaddle

    title('PongASM')
    size(1280, 720)

    # Paddle creation
    leftPaddel = Paddel(
        height = 150,
        pos = {'x': 50, 'y' : 50},
        vel = 10
    )
    rightPaddle = Paddel(
        height = 150,
        pos = {'x': asm.SUB(width, 50), 'y' : 50},
        vel = 10
    )

    # Ball creation
    ball['pos'] = [ width/2, height/2 ]

    # Correctly position the paddles
    rightPaddle.pos['x'] = asm.SUB(rightPaddle.pos['x'], rightPaddle.width)
    leftPaddel.pos['y'] = asm.SUB(int(height / 2), int(leftPaddel.heigth / 2))
    rightPaddle.pos['y'] = asm.SUB(int(height / 2), int(rightPaddle.heigth / 2))

def draw():
    global leftPaddel, rightPaddle
    if scene == 'init':
        scene_init()
    elif scene == 'game':
        scene_game()

def key_pressed():
    # Left paddle move
    if key == 'W':
        leftPaddel.moving = -1
    elif key == 'S':
        leftPaddel.moving = 1

    # Right paddle move
    if key == 'UP':
        rightPaddle.moving = -1
    elif key == 'DOWN':
        rightPaddle.moving = 1

# Scenes

def scene_init():
    background(0)

def scene_game():
    background(0)
    drawBall() # Ball
    drawPaddles() # Paddles

# Update methods for draw()

def drawBall():
    # Ball
    no_stroke()
    fill(ball['color'][0], ball['color'][1], ball['color'][2])
    circle((ball['pos'][0], ball['pos'][1]), ball['radius'])

    # Border colitions
    if asm.ADD(int(ball['pos'][1]), int(ball['radius'] / 2)) > height or asm.SUB(int(ball['pos'][1]), int(ball['radius'] / 2)) < 0:
        ball['vel'][1] = asm.MUL(ball['vel'][1], -1)

    # Right paddle colitions
    if asm.ADD(int(ball['pos'][0]), int(ball['radius'] / 2)) >= rightPaddle.pos['x']:
        if asm.ADD(int(ball['pos'][1]), int(ball['radius'] / 2)) >= rightPaddle.pos['y'] and asm.SUB(int(ball['pos'][1]), int(ball['radius'] / 2)) <= asm.ADD(int(rightPaddle.pos['y']), rightPaddle.heigth):
            ball['vel'][0] = asm.MUL(ball['vel'][0], -1)

    # Left paddle colitions
    if asm.ADD(int(ball['pos'][0]), int(ball['radius'] / 2)) <= asm.ADD(int(leftPaddel.pos['x']), asm.MUL(leftPaddel.width, 2)):
        if asm.ADD(int(ball['pos'][1]), int(ball['radius'] / 2)) >= leftPaddel.pos['y'] and asm.SUB(int(ball['pos'][1]), int(ball['radius'] / 2)) <= asm.ADD(int(leftPaddel.pos['y']), leftPaddel.heigth):
            ball['vel'][0] = asm.MUL(ball['vel'][0], -1)

    # Update ball position
    ball['pos'][1] = asm.ADD(int(ball['pos'][1]), ball['vel'][1])
    ball['pos'][0] = asm.ADD(int(ball['pos'][0]), ball['vel'][0])

def drawPaddles():
    # Paddles
    no_stroke()
    fill(255)
    rect(( leftPaddel.pos['x'], leftPaddel.pos['y'] ), leftPaddel.width, leftPaddel.heigth)
    rect(( rightPaddle.pos['x'], rightPaddle.pos['y'] ), rightPaddle.width, rightPaddle.heigth)

    # Check move
    if leftPaddel.moving != 0:
        if leftPaddel.moving == 1:
            if asm.ADD(leftPaddel.pos['y'], leftPaddel.heigth) < height:
                leftPaddel.pos['y'] = asm.ADD(leftPaddel.pos['y'], asm.MUL(leftPaddel.vel, leftPaddel.moving))
        else:
            if leftPaddel.pos['y'] > 0:
                leftPaddel.pos['y'] = asm.ADD(leftPaddel.pos['y'], asm.MUL(leftPaddel.vel, leftPaddel.moving))
    if rightPaddle.moving != 0:
        if rightPaddle.moving == 1:
            if asm.ADD(rightPaddle.pos['y'], rightPaddle.heigth) < height:
                rightPaddle.pos['y'] = asm.ADD(rightPaddle.pos['y'], asm.MUL(rightPaddle.vel, rightPaddle.moving))
        else:
            if rightPaddle.pos['y'] > 0:
                rightPaddle.pos['y'] = asm.ADD(rightPaddle.pos['y'], asm.MUL(rightPaddle.vel, rightPaddle.moving))

if __name__ == '__main__':
    run()


def in_file(filename):
    '''returns [orientation, [list of tags]]'''
    #filename = "a_example.txt"
    images = []
    with open(filename, 'r') as f:
        line_count = f.readline()
        for i in range(int(line_count)):
            orientation, tags_count, *tags = f.readline().split()
            images.append([orientation, set(tags), [i]])
    return images

def output(filename: str, slides: list):
    with open(filename[:-4]+"_out.txt", 'w') as f:
        f.write(str(len(slides))+'\n')
        for slide in slides:
            line = ""
            for integer in slide:
                line += str(integer)+" "
            f.write(line[:-1]+'\n')

if __name__=="__main__":
    print(in_file('a_example.txt'))
    print(output("test", [[0], [3], [1,2]]))


import xadmin
from .models import *

from xadmin import views
# Register your models here.

xadmin.site.site_header = '发现生活后台管理'
xadmin.site.site_title = '发现生活'

# # 创建xadmin的最基本管理器配置，并与view绑定
# class BaseSetting(object):
#     # 开启主题功能
#     enable_themes = True
#     use_bootswatch = True
#
# # 将基本配置管理与view绑定
# xadmin.site.register(views.BaseAdminView,BaseSetting)

# 全局修改，固定写法
class GlobalSettings(object):
    # 修改title
    site_title = '高仿点评后台管理界面'
    # 修改footer
    site_footer = '中北大学大数据学院物联网工程大型软件实验周课设'
    # 收起菜单
    menu_style = 'accordion'

# 将title和footer信息进行注册
xadmin.site.register(views.CommAdminView,GlobalSettings)

# 进行类配置
class AddressAdmin(object):
    # 显示的列
    list_display = ['id', 'userid', 'addressName', 'tel','province','detail']
    # 搜索的字段，不要添加时间搜索
    search_fields = ['id', 'userid', 'addressName', 'tel','province','detail']
    # 过滤
    list_filter = ['id', 'userid', 'addressName', 'tel','province','detail']

class CategoryAdmin(object):
    # 显示的列
    list_display = ['category_id', 'category_name', 'category_parent']
    # 搜索的字段，不要添加时间搜索
    search_fields = ['category_id', 'category_name', 'category_parent']
    # 过滤
    list_filter = ['category_id', 'category_name', 'category_parent']

class CityAdmin(object):
    # 显示的列
    list_display = ['id', 'name', 'sortKey']
    # 搜索的字段，不要添加时间搜索
    search_fields = ['id', 'name', 'sortKey']
    # 过滤
    list_filter = ['id', 'name', 'sortKey']

class CommentAdmin(object):
    # 显示的列
    list_display = ['comment_id', 'user', 'prodouct','comment_conent', 'comment_time']
    # 搜索的字段，不要添加时间搜索
    search_fields = ['comment_id', 'user', 'prodouct','comment_conent', 'comment_time']
    # 过滤
    list_filter = ['comment_id', 'user', 'prodouct','comment_conent', 'comment_time']

class OrdersAdmin(object):
    # 显示的列
    list_display = ['orders_id', 'user', 'orders_time','orders_all_price', 'orders_paystate','orders_prodouct_id']
    # 搜索的字段，不要添加时间搜索
    search_fields = ['orders_id', 'user', 'orders_time','orders_all_price', 'orders_paystate','orders_prodouct_id']
    # 过滤
    list_filter = ['orders_id', 'user', 'orders_time','orders_all_price', 'orders_paystate','orders_prodouct_id']

class ProdouctAdmin(object):
    # 显示的列
    list_display = ['id', 'categoryId', 'shopId','CityId', 'sortTitle','value', 'price', 'ribat',]
    # 搜索的字段，不要添加时间搜索
    search_fields = ['id', 'categoryId', 'shopId','CityId', 'sortTitle','value', 'price', 'ribat',]
    # 过滤
    list_filter = ['id', 'categoryId', 'shopId','CityId', 'sortTitle','value', 'price', 'ribat',]

class ShopAdmin(object):
    # 显示的列
    list_display = ['id', 'name', 'tel','address', 'area','opentime', 'lon', 'lat',]
    # 搜索的字段，不要添加时间搜索
    search_fields = ['id', 'name', 'tel','address', 'area','opentime', 'lon', 'lat',]
    # 过滤
    list_filter = ['id', 'name', 'tel','address', 'area','opentime', 'lon', 'lat',]

class UserAdmin(object):
    # 显示的列
    list_display = ['id', 'name', 'loginPwd','payPwd', 'tel',]
    # 搜索的字段，不要添加时间搜索
    search_fields = ['id', 'name', 'loginPwd','payPwd', 'tel',]
    # 过滤
    list_filter = ['id', 'name', 'loginPwd','payPwd', 'tel',]

xadmin.site.register(Address,AddressAdmin)
xadmin.site.register(Category,CategoryAdmin)
xadmin.site.register(City,CityAdmin)
xadmin.site.register(Comment,CommentAdmin)
# xadmin.site.register(Favorite)
xadmin.site.register(Orders,OrdersAdmin)
xadmin.site.register(Prodouct,ProdouctAdmin)
xadmin.site.register(Shop,ShopAdmin)
# xadmin.site.register(SubCategory)
# xadmin.site.register(Ticket)
xadmin.site.register(User,UserAdmin)


# _*_ coding: utf-8 _*_
'a test module'
__author__ = 'Michael Liao'
import sys

class Hello(object):
	def hello(self, name='world'):
		print('Hello, %s.' % name)
def test():
    args = sys.argv
    if len(args)==1:
        print('Hello, world')
    elif len(args)==2:
        print('Hello, %s!' % args[1])
    else:
        print('Too many arguments!')

if __name__=='__main__':
    test()

'''
第1行是标准注释，第行注释表示.py文件本身使用标准UTF-8编码
第2行是一个字符串，表示模块的文档注释，任何模块代码的第一个字符串都被视为模块的文档注释；
第3行使用_ _author_ _变量把作者写进去，这样当你公开源代码后别人就可以瞻仰你的大名
'''


import numpy as np

from environments.circuits import NodeCircuit
from environments.physical_environment import verify_circuit

def reset_environment_state(env, circuit, qubit_locations):
    initial_state, gates_scheduled = env.generate_starting_state(circuit, qubit_locations)

    while env.is_done(initial_state[1]):
        initial_state, gates_scheduled = env.generate_starting_state(circuit, qubit_locations)

    return initial_state, gates_scheduled

def schedule_swaps(environment, agent, circuit=None, experience_db=None, qubit_locations=None, safety_checks_on=False, decompose_cnots=False):
    total_gates_scheduled = []
    original_circuit = circuit
    circuit = circuit.to_dqn_rep()

    state, gates_scheduled = reset_environment_state(environment, circuit, qubit_locations)
    actions = []

    initial_qubit_locations = state[0][:]

    total_gates_scheduled.extend(list(map(lambda g: ('CnotGate',g[0],g[1]), gates_scheduled)))

    if experience_db is not None:
        experience_db.new_experience(state, environment.circuit)

    for time in range(1500):
        action, action_type = agent.act(state)
        next_state, reward, done, next_gates_scheduled = environment.step(action, state)

        edges_swapped = [environment.edge_list[e] for e in np.where(np.array(action) == 1)[0]]
        total_gates_scheduled.extend(list(map(lambda g: ('SwapGate',g[0],g[1]), edges_swapped)))
        total_gates_scheduled.extend(list(map(lambda g: ('CnotGate',g[0],g[1]), next_gates_scheduled)))

        actions.append(action)

        if experience_db is not None:
            experience_db.add_state_transition(next_state, next_state, action_type)

        state = next_state
        gates_scheduled = next_gates_scheduled

        if done:
            break

    if experience_db is not None:
        experience_db.save_experience()

    scheduled_circuit = NodeCircuit.from_gates(environment.number_of_nodes, total_gates_scheduled, decompose=decompose_cnots)

    if safety_checks_on:
        verify_circuit(original_circuit, scheduled_circuit, environment, initial_qubit_locations)

    return actions, scheduled_circuit.depth()


#!/usr/bin/env python3

# Validation code for the chapter-4 examples
#
# SPDX-License-Identifier: MIT

import subprocess
import pytest
import tempfile
import os
import sys
import glob
from pathlib import Path
from os.path import exists as file_exists

def get_script_path():
    return Path( __file__).parent

def get_root_project_directory():
    return get_script_path().parent

def get_chapter4_root_directory():
    return get_root_project_directory().joinpath("chapter04")

if os.name == 'nt':
    CMAKE_COMMAND_MULTICONFIG_ARGS=("--config", "Debug")
    CPACK_COMMAND_MULTICONFIG_ARGS=("-C", "Debug")
    PLATFORM_EXECUTABLE_EXTENSION=".exe"
    PLATFORM_STATIC_LIBRARY_PREFIX=""
    PLATFORM_STATIC_LIBRARY_EXTENSION=".lib"
else:
    PLATFORM_EXECUTABLE_EXTENSION=""
    PLATFORM_STATIC_LIBRARY_PREFIX="lib"
    PLATFORM_STATIC_LIBRARY_EXTENSION=".a"
    CMAKE_COMMAND_MULTICONFIG_ARGS=()
    CPACK_COMMAND_MULTICONFIG_ARGS=()

CMAKE_COMMAND="cmake"
CPACK_COMMAND="cpack"

def run_command(command, *args):
    """Execute a command with arguments.

    Args:
        command (string): Command to execute
        *args (args list): Arguments to be forwarded to the

    Returns:
        bool: True if command execution did not throw any errors, False otherwise
    """
    try:
        subprocess.run(args=[command, *args], check=True, stdout=subprocess.DEVNULL, stderr=subprocess.DEVNULL)
        return True
    except:
        return False

def run_cmake(*args):
    """Run CMake with given args

    Returns:
        bool: True if command execution did not throw any errors, False otherwise
    """
    return run_command(CMAKE_COMMAND, *args)

def run_cpack(*args):
    """Run CPack with given args

    Returns:
        bool: True if command execution did not throw any errors, False otherwise
    """
    return run_command(CPACK_COMMAND, *args)

def test_prerequisites():
    """
    Check overall prerequisites for the tests.

    If one of the checks fail, the testing cannot proceed any further.
    """
    assert run_cmake("--version"), "CMake is not present!"
    assert run_cpack("--version"), "CPack is not present!"
    # assert run_command("rpmbuild", "--version"), "rpmbuild is not present!"
    # assert run_command("dpkg", "--version"), "DPKG is not present!"
    assert run_command("tar", "--version"), "TAR is not present!"

class TestChapter4():
    """
    Tests for chapter 4 CMake example content.

    This code validates that can be configured, built, installed without any issues. In addition,
    the test code validates installation has installed the expected files (and not installed the unexpected ones)
    and tries to run the executables.
    """
    temporary_build_root_dir=tempfile.TemporaryDirectory("build")
    temporary_install_root_dir=tempfile.TemporaryDirectory("install")
    temporary_build_root=temporary_build_root_dir.name
    temporary_install_root=temporary_install_root_dir.name
    source_directory=str(get_chapter4_root_directory().absolute())

    def test_configure(self):
        """Check if project can be configured
        """
        assert run_cmake("-S", self.source_directory, "-B", self.temporary_build_root)

    @pytest.mark.depends(on=['test_configure'])
    def test_build(self):
        """Check if project can be built
        """
        assert run_cmake("--build", self.temporary_build_root, *CMAKE_COMMAND_MULTICONFIG_ARGS,  "--parallel", str(os.cpu_count()))

    @pytest.mark.depends(on=['test_configure'])
    def test_install(self):
        """Check if project can be installed
        """
        assert run_cmake("--install", self.temporary_build_root, *CMAKE_COMMAND_MULTICONFIG_ARGS, "--prefix", self.temporary_install_root)

    @pytest.mark.depends(on=['test_install'])
    def test_install_check_files_exists(self):
        """Check if install step has installed the all files that install() commands intend to install
        """

        # Print install folder contents if an assert fails to make debugging easier
        for root, subdirs, files in os.walk(self.temporary_install_root):
            print('--\nroot = ' + root)
            for s in subdirs:
                print('\tdirs-- ' + s)
            for f in files:
                print('\t\t files-- ' + f)

        # Example 1
        assert file_exists(f"{self.temporary_install_root}/bin/ch4_ex01_executable{PLATFORM_EXECUTABLE_EXTENSION}")
        # Example 2
        # use globbing to account for platform-tuple suffixes i.e. lib/x64_86-linux-gnu etc
        assert len(glob.glob(f"{self.temporary_install_root}/lib/**/{PLATFORM_STATIC_LIBRARY_PREFIX}ch4_ex02_static{PLATFORM_STATIC_LIBRARY_EXTENSION}", recursive=True)) > 0

        assert file_exists(f"{self.temporary_install_root}/include/chapter4/ex02/lib.hpp")
        # Example 3
        assert file_exists(f"{self.temporary_install_root}/bin/chapter4_greeter_content")
        assert file_exists(f"{self.temporary_install_root}/bin/chapter4_greeter")
        # Example 4
        assert file_exists(f"{self.temporary_install_root}/var/dir1/subdir/asset5.x")
        assert file_exists(f"{self.temporary_install_root}/var/dir1/asset1.x")
        assert not file_exists(f"{self.temporary_install_root}/var/dir1/asset2")
        assert file_exists(f"{self.temporary_install_root}/var/dir2/chapter4_hello.dat")
        assert not file_exists(f"{self.temporary_install_root}/var/dir2/chapter1_hello.hpp")
        assert file_exists(f"{self.temporary_install_root}/var/dir3/asset4")
        assert not file_exists(f"{self.temporary_install_root}/var/dir3/bin/goodbye.dat")
        # Example 5
        assert len(glob.glob(f"{self.temporary_install_root}/lib/**/{PLATFORM_STATIC_LIBRARY_PREFIX}ch4_ex05_lib{PLATFORM_STATIC_LIBRARY_EXTENSION}", recursive=True)) > 0

        assert file_exists(f"{self.temporary_install_root}/include/chapter4/ex05/lib.hpp")
        assert file_exists(f"{self.temporary_install_root}/cmake/ch4_ex05_lib-config.cmake")
        assert file_exists(f"{self.temporary_install_root}/cmake/ch4_ex05_lib-config-version.cmake")

    @pytest.mark.depends(on=['test_configure'])
    def test_install_run_binaries(self):
        """Try to run executables that installed via install
        """
        assert run_command(f"{self.temporary_install_root}/bin/ch4_ex01_executable{PLATFORM_EXECUTABLE_EXTENSION}")
        assert run_command("python3", f"{self.temporary_install_root}/bin/chapter4_greeter")

    @pytest.mark.depends(on=['test_configure'])
    def test_ex05_consumer(self):
        """Check config-file package works by building ex05_consumer after installing the chapter 4 content
        """
        ex05_temporary_build_root_dir=tempfile.TemporaryDirectory("build")
        ex05_temporary_build_root=ex05_temporary_build_root_dir.name
        ex05_source_directory=str(get_chapter4_root_directory().joinpath("ex05_consumer").absolute())
        assert run_cmake("-S", ex05_source_directory, "-B", ex05_temporary_build_root, f"-DCMAKE_INSTALL_PREFIX:STRING={self.temporary_install_root}")
        assert run_cmake("--build", ex05_temporary_build_root, *CMAKE_COMMAND_MULTICONFIG_ARGS, "--parallel", str(os.cpu_count()))

class TestChapter4Example6():
    """Tests for the packaging example
    """
    temporary_build_root_dir=tempfile.TemporaryDirectory("build")
    temporary_install_root_dir=tempfile.TemporaryDirectory("install")
    temporary_build_root=temporary_build_root_dir.name
    temporary_install_root=temporary_install_root_dir.name
    source_directory=str(get_chapter4_root_directory().joinpath("ex06_pack").absolute())

    def test_configure(self):
        """Check if project can be configured
        """
        assert run_cmake("-S", self.source_directory, "-B", self.temporary_build_root)

    @pytest.mark.depends(on=['test_configure'])
    def test_configure_check_files(self):
        """Check if CPack configuration files are present after configuration
        """
        assert file_exists(f"{self.temporary_build_root}/CPackConfig.cmake")
        assert file_exists(f"{self.temporary_build_root}/CPackSourceConfig.cmake")

    @pytest.mark.depends(on=['test_configure'])
    def test_build(self):
        """Check if project can be built
        """
        assert run_cmake("--build", self.temporary_build_root, *CMAKE_COMMAND_MULTICONFIG_ARGS,  "--parallel", str(os.cpu_count()))

    @pytest.mark.depends(on=['test_configure'])
    def test_install(self):
        """Check if project can be installed
        """
        assert run_cmake("--install", self.temporary_build_root, *CMAKE_COMMAND_MULTICONFIG_ARGS, "--prefix", self.temporary_install_root)

    @pytest.mark.depends(on=['test_install'])
    def test_install_check_files(self):
        """Check if install step has installed the all files that install() commands intend to install
        """
        assert file_exists(f"{self.temporary_install_root}/bin/ch4_ex06_executable{PLATFORM_EXECUTABLE_EXTENSION}")
        # use globbing to account for platform-tuple suffixes i.e. lib/x64_86-linux-gnu etc
        assert len(glob.glob(f"{self.temporary_install_root}/lib/**/{PLATFORM_STATIC_LIBRARY_PREFIX}ch4_ex06_library{PLATFORM_STATIC_LIBRARY_EXTENSION}", recursive=True)) > 0
        assert file_exists(f"{self.temporary_install_root}/include/chapter4/ex06/lib.hpp")

    @pytest.mark.depends(on=['test_install'])
    def test_install_run_binaries(self):
        """Try to run executables that installed via install
        """
        assert run_command(f"{self.temporary_install_root}/bin/ch4_ex06_executable{PLATFORM_EXECUTABLE_EXTENSION}")

    @pytest.mark.depends(on=['test_configure'])
    def test_pack(self):
        """Try to pack the project via CPack
        """
        assert run_cpack("--config", f"{self.temporary_build_root}/CPackConfig.cmake", *CPACK_COMMAND_MULTICONFIG_ARGS, "-G", "TGZ", "-B", f"{self.temporary_build_root}/pak")

    @pytest.mark.depends(on=['test_pack'])
    def test_pack_check_files(self):
        """Check whether CPack produced the package files
        """
        # Linux, Windows, and Darwin
        for system_name in ["Linux", "win32", "win64", "Darwin"]:
            if file_exists(f"{self.temporary_build_root}/pak/ch4_ex06_pack-1.0-{system_name}.tar.gz"):
                return True
        assert False, "Package file is not present!"


#!/usr/bin/python3

from re import I

def pattern(row):
    i,j = 1,0
    while i <= row:
        j = i
        while j != 0:
            print("*",end = "")
            j -=1
        print()
        i += 1

pattern(int(input("Enter the number of rows: ")))


import argparse
import glob

import netCDF4 as nc
import re
from datetime import datetime, timedelta
import pandas as pd
import tqdm
import numpy as np

from gfs_archive_0_25.gfs_processor.own_logger import logger
from gfs_archive_0_25.utils import prep_zeros_if_needed
from gfs_archive_0_25.gfs_processor.consts import *
from gfs_common.common import GFS_PARAMETERS
from util.coords import GFS_SPACE, Coords

OFFSET = 3

class ProcessingException(Exception):
    pass

def get_forecast_df_for_date_and_run(csv_path):
    if os.path.exists(csv_path):
        return pd.read_csv(csv_path, index_col=[0])
    else:
        return pd.DataFrame(columns=["date"])

def get_date_run_offset_from_netCDF_file_name(file):
    date_matcher = re.match(RAW_NETCDF_FILENAME_REGEX, file)
    if date_matcher is None:
        logger.warn(f"Filename {file} does not match raw netCDF file regex: {RAW_NETCDF_FILENAME_REGEX}")
        raise ProcessingException(f"Filename {file} does not match raw netCDF file regex: {RAW_NETCDF_FILENAME_REGEX}")

    date_from_filename = date_matcher.group(2)
    year = date_from_filename[:4]
    month = date_from_filename[4:6]
    day = date_from_filename[6:8]
    return datetime(int(year), int(month), int(day)), date_from_filename[8:10], date_matcher.group(3)

def get_values_as_numpy_arr_from_file(netCDF_filepath, coords: Coords):
    ds = nc.Dataset(netCDF_filepath)
    lats, lons = ds.variables[[key for key in ds.variables.keys() if key.startswith('lat')][0]][:],\
                 ds.variables[[key for key in ds.variables.keys() if key.startswith('lon')][0]][:]
    if coords.nlat not in lats or coords.slat not in lats or coords.wlon not in lons or coords.elon not in lons:
        return None
    else:
        lats = lats.data.tolist()
        lons = lons.data.tolist()
        nlat_index, slat_index, wlon_index, elon_index = lats.index(coords.nlat), lats.index(coords.slat), \
                                                         lons.index(coords.wlon), lons.index(coords.elon)

        return ds.variables[[key for key in ds.variables.keys() if key[0].isupper()][0]][nlat_index:slat_index + 1, wlon_index:elon_index + 1].data

def get_value_from_netCDF(dataset, lat_index, lon_index):
    return next(iter(dataset.variables.values()))[0][lat_index][lon_index]

def process_netCDF_file_to_csv(file, parameter_level_tuple, output_dir):
    name, level = parameter_level_tuple
    ds = nc.Dataset(file)
    lats, lons = ds.variables['lat_0'][:], ds.variables['lon_0'][:]
    init_date, run, offset = get_date_run_offset_from_netCDF_file_name(file)
    date_str = (init_date + timedelta(hours=int(offset))).isoformat()

    for lat_index, lat in enumerate(lats):
        for lon_index, lon in list(enumerate(lons)):
            final_csv_dir = os.path.join(output_dir, str(lat).replace('.', '_') + '-' + str(lon).replace('.', '_'))
            if not os.path.exists(final_csv_dir):
                os.makedirs(final_csv_dir)

            value = get_value_from_netCDF(ds, lat_index, lon_index)
            param_name = name + '_' + level.replace("_", ":")

            final_csv_name = FINAL_CSV_FILENAME_FORMAT.format(init_date.year,
                                                              prep_zeros_if_needed(str(init_date.month), 1),
                                                              prep_zeros_if_needed(str(init_date.day), 1),
                                                              run)
            final_csv_path = os.path.join(final_csv_dir, final_csv_name)
            forecast_df = get_forecast_df_for_date_and_run(final_csv_path)

            if param_name not in forecast_df:
                forecast_df[param_name] = 0

            rows = forecast_df[forecast_df['date'] == date_str]
            if len(rows) == 0:
                forecast_df.loc[len(forecast_df.index), :] = ''
                forecast_df.loc[len(forecast_df.index) - 1, ['date', param_name]] = [date_str,
                                                                                value]
                forecast_df.sort_values('date')
            else:
                forecast_df.loc[forecast_df['date'] == date_str, param_name] = value

            forecast_df.to_csv(final_csv_path)
    # #os.remove(csv_file_path)

def check_if_any_file_for_year_exists(year, parameter_level_tuple):
    netCDF_file_glob = RDA_NETCDF_FILENAME_FORMAT.format(str(year),
                                                         '*',
                                                         '',
                                                         '',
                                                         '00' + str(OFFSET),
                                                         '*')
    netCDF_path_glob = os.path.join(NETCDF_DOWNLOAD_PATH, parameter_level_tuple[0],
                                    parameter_level_tuple['level'].replace(":", "_").replace(",", "-"), netCDF_file_glob)
    found_files = glob.glob(netCDF_path_glob)
    if len(found_files) > 0:
        return True
    return False

def process_to_numpy_array(parameter_level_tuple, input_dir: str, output_dir: str):
    for root, dirs, filenames in os.walk(input_dir):
        if len(filenames) > 0:
            output_dir = os.path.join(output_dir, parameter_level_tuple['name'], parameter_level_tuple['level'])

            if not os.path.exists(output_dir):
                os.makedirs(output_dir)

            for file in tqdm.tqdm(filenames):
                try:
                    date, run, offset = get_date_run_offset_from_netCDF_file_name(file)

                    output_path = os.path.join(output_dir, FINAL_NUMPY_FILENAME_FORMAT.format(
                        str(date.year),
                        prep_zeros_if_needed(str(date.month), 1),
                        prep_zeros_if_needed(str(date.day), 1),
                        run,
                        prep_zeros_if_needed(str(offset), 2)))

                    # consider as done if output file already exists
                    if not os.path.exists(output_path):
                        forecast = get_values_as_numpy_arr_from_file(os.path.join(input_dir, file), GFS_SPACE)
                        if forecast is not None:
                            np.save(output_path, forecast)
                except ProcessingException:
                    pass
        break

def process_to_csv(parameter_level_tuple, input_dir: str, output_dir: str):
    for root, level_dirs, filenames in os.walk(input_dir):
        if len(filenames) > 0:
            output_dir = os.path.join(output_dir, parameter_level_tuple['name'], parameter_level_tuple['level'])

            if not os.path.exists(output_dir):
                os.makedirs(output_dir)

            for file in tqdm.tqdm(filenames):
                file_name_match = re.match(RAW_NETCDF_FILENAME_REGEX, file)
                if file_name_match is not None:
                    process_netCDF_file_to_csv(os.path.join(input_dir, file), parameter_level_tuple, output_dir)

def process_netCDF_files_to_csv(output_dir: str):
    for param in GFS_PARAMETERS:
        logger.info(f"Converting parameter {param['name']} {param['level']}")
        process_to_csv(param, GFS_SPACE, output_dir)

def process_netCDF_files(mode: str, output_dir: str):
    for param in GFS_PARAMETERS:
        name = param['name']
        level = param['level']
        logger.info(f"Converting parameter {name} {level}")
        if name == 'T CDC':
            param_name_dir = 'L CDC' if level == 'LCY_0' else 'M CDC' if level == 'MCY_0' else 'H CDC'
        else:
            param_name_dir = name
        input_dir = os.path.join(NETCDF_DOWNLOAD_PATH, param_name_dir, level)

        if mode == "NPY":
            process_to_numpy_array(param, input_dir, output_dir)
        else:
            process_to_csv(param, input_dir, output_dir)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()

    parser.add_argument('--mode', help='CSV or NPY - output format to which save the data. ', default="NPY", choices=["CSV", "NPY"])
    parser.add_argument('--output_dir', help='Output directory for the result files.', default="D:\\WindForecast\\gfs")
    args = parser.parse_args()

    process_netCDF_files(args.mode, args.output_dir)


# пример использования преобразования к категориям
import numpy
from keras.datasets import cifar10
from keras.utils import to_categorical
# Задаем seed для повторяемости результатов
numpy.random.seed(42)

# Загружаем данные
(X_train, y_train), (X_test, y_test) = cifar10.load_data()
# Размер мини-выборки
batch_size = 32
# Количество классов изображений
nb_classes = 10
# Количество эпох для обучения
nb_epoch = 25
# Размер изображений
img_rows, img_cols = 32, 32
# Количество каналов в изображении: RGB
img_channels = 3

# Нормализуем данные
X_train = X_train.astype('float32')
X_test = X_test.astype('float32')
X_train /= 255
X_test /= 255

# Преобразуем метки в категории
Y_train = to_categorical(y_train, nb_classes)
Y_test = to_categorical(y_test, nb_classes)

print("y: ", type(y_train))
print("Y: ", Y_train)

# y:
#  [[6]
#  [9]
#  [9]
#  ...
#  [9]
#  [1]
#  [1]]
# Y:
#  [[0. 0. 0. ... 0. 0. 0.]
#  [0. 0. 0. ... 0. 0. 1.]
#  [0. 0. 0. ... 0. 0. 1.]
#  ...
#  [0. 0. 0. ... 0. 0. 1.]
#  [0. 1. 0. ... 0. 0. 0.]
#  [0. 1. 0. ... 0. 0. 0.]]


import constants
import pygame

class GameScreen:
    """The screen that is shown when the game is being played.
    """
    def __init__(self):
        pass

    def draw_screen(self, window, card_size, card_back, cards, poker, replace_button):
        """Draws the game screen on the screen.
        Args:
            window (pygame.Surface): the window to draw the game screen on
            card_size (tuple): the size of the cards
            card_back (pygame.Surface): the back of the cards
            cards (dict): the dictionary of the cards
            poker (Poker): the poker game
            replace_button (Button): the button to replace the cards
        """
        window.blit(pygame.font.SysFont(constants.FONT2[0], constants.FONT2[1]).render \
                    ("You", 1, constants.BLACK), (constants.WIDTH/3 + 150, \
                                                   constants.HEIGHT/5 - card_size[1]/2 - 50))

        window.blit(pygame.font.SysFont(constants.FONT2[0], constants.FONT2[1]).render \
                    ("Bot 1", 1, constants.BLACK), (constants.WIDTH/3 - card_size[0]/2 - 300 + 175, \
                                                    constants.HEIGHT/5 - card_size[1]/2 + 200))

        window.blit(pygame.font.SysFont(constants.FONT2[0], constants.FONT2[1]).render \
                    ("Bot 2", 1, constants.BLACK), ((constants.WIDTH/3 - card_size[0]/2 - 300 + 175) + 650, \
                                                    constants.HEIGHT/5 - card_size[1]/2 + 200))

        window.blit(pygame.font.SysFont(constants.FONT2[0], constants.FONT2[1]).render \
                    ("Bot 3", 1, constants.BLACK), (constants.WIDTH/3 - card_size[0]/2 + 175, \
                                                    constants.HEIGHT/5 - card_size[1]/2 + 450))

        window.blit(pygame.font.SysFont(constants.FONT3[0], constants.FONT3[1]).render \
                    ("Select cards to replace: ", 1, constants.BLACK), \
                    (constants.WIDTH/3, \
                        constants.HEIGHT/5 - card_size[1]/2 + 110))

        replace_button.draw(window)

        for i in range(5):
            window.blit(cards[str(poker.player_hand[i])], self.player_card_loc[i])
            window.blit(card_back, self.bot1_card_loc[i])
            window.blit(card_back, self.bot2_card_loc[i])
            window.blit(card_back, self.bot3_card_loc[i])

    def draw_scores(self, window, scoreboard):
        """Draws the scores on the screen.
        Args:
            window (pygame.Surface): the window to draw the scores on
            scoreboard (list): the list of scores
        """
        window.blit(pygame.font.SysFont(constants.FONT3[0], constants.FONT3[1]).render \
                         (f"Your score: {scoreboard[0]}", 1, constants.BLACK), \
                         (20, 20))

        window.blit(pygame.font.SysFont(constants.FONT3[0], constants.FONT3[1]).render \
                            (f"Bot 1 score: {scoreboard[1]}", 1, constants.BLACK), \
                            (20, 55))

        window.blit(pygame.font.SysFont(constants.FONT3[0], constants.FONT3[1]).render \
                            (f"Bot 2 score: {scoreboard[2]}", 1, constants.BLACK), \
                            (20, 90))

        window.blit(pygame.font.SysFont(constants.FONT3[0], constants.FONT3[1]).render \
                            (f"Bot 3 score: {scoreboard[3]}", 1, constants.BLACK), \
                            (20, 125))

    def set_locs(self, card_size):
        """Sets the locations of the cards.
        Args:
            card_size (tuple): the size of the cards
        """
        self.player_card_loc = []
        for i in range(5):
            self.player_card_loc.append(
                (constants.WIDTH/3 - card_size[0]/2 + i * 100, constants.HEIGHT/5 - card_size[1]/2))

        self.bot1_card_loc = []
        for i in range(5):
            self.bot1_card_loc.append(
                ((constants.WIDTH/3 - card_size[0]/2 - 300 + i * 100), \
                 constants.HEIGHT/5 - card_size[1]/2 + 250))

        self.bot2_card_loc = []
        for i in range(5):
            self.bot2_card_loc.append(
                (constants.WIDTH/3 - card_size[0]/2 - 300 + i * 100 + 650, \
                 constants.HEIGHT/5 - card_size[1]/2 + 250))

        self.bot3_card_loc = []
        for i in range(5):
            self.bot3_card_loc.append(
                (constants.WIDTH/3 - card_size[0]/2 + i * 100, constants.HEIGHT/5 - card_size[1]/2 + 500))

    def get_locs(self):
        """Gets the locations of the cards.
        Returns:
            list: the list of the locations of the player's cards
        """
        return self.player_card_loc

    def update_card_loc(self, window, card, card_loc):
        """Updates the location of the card.
        Args:
            window (pygame.Surface): the window to draw the card on
            card (pygame.Surface): the card to draw
            card_loc (tuple): the location of the card
        """
        window.blit(card, card_loc)


import csv
import re
import yaml
import logging

from github import Github
from pathlib import Path

logging.basicConfig(
    filename="meta_with_no_base.log",
    format="%(levelname)s: %(message)s",
    level=logging.INFO,
)

def notifier(msg):
    logging.info(msg)

def check_for_base(meta, pecha_id):
    source_meta = meta['source_metadata']
    out_key = 'volumes'
    if out_key in source_meta.keys():
        if source_meta['volumes'] != ({} or ''):
            volumes = source_meta['volumes']
            for vol_id, vol_info in volumes.items():
                key = 'base_file'
                if key in vol_info.keys():
                    print(f"{pecha_id} has base_file")
                    break
                else:
                    notifier(f"[{pecha_id}] has no base_file")
                    print(f"{pecha_id} has no base_file")
                    break
        else:
            print(f"[{pecha_id}] has no volumes")
    else:
        notifier(f"[{pecha_id}] meta data not updated")
        print(f"{pecha_id} has no volumes")

if __name__ == "__main__":
    token = ''
    g = Github(token)
    with open("catalog.csv", newline="") as csvfile:
        pechas = list(csv.reader(csvfile, delimiter=","))
        for pecha in pechas[3626:4302]:
            pecha_id = re.search("\[.+\]", pecha[0])[0][1:-1]
            repo = g.get_repo(f"Openpecha/{pecha_id}")
            contents = repo.get_contents(f"./{pecha_id}.opf/meta.yml")
            meta_content = contents.decoded_content.decode()
            meta_content = yaml.safe_load(meta_content)
            check_for_base(meta_content, pecha_id)


# -*- coding: utf-8 -*-
import pathlib
import argparse
import torch
from parse_config import ConfigParser
from model.model import NNEModel
from collections import OrderedDict

parser = argparse.ArgumentParser(description='Description of your program')
parser.add_argument('-i','--input', help='Path of model', required=True)
parser.add_argument('-o','--output', help='Path for output model', required=True)
args = vars(parser.parse_args())

try:
    checkpoint = torch.load(args['input'], map_location=torch.device('cpu'))

except NotImplementedError:
    temp = pathlib.PosixPath
    pathlib.PosixPath = pathlib.WindowsPath
    checkpoint = torch.load(args['input'], map_location=torch.device('cpu'))

state_dict_new = OrderedDict()
state_dict = checkpoint['state_dict']
for key, value in state_dict.items():
    state_dict_new[str(key).replace('module.','',1)] = value
torch.save(state_dict_new, args['output'])