import datetime
import pytest

from model_bakery import baker
from rest_framework import status
from uuid import UUID
from unittest.mock import Mock

from usaspending_api.common.exceptions import InvalidParameterException
from usaspending_api.recipient.v2.views import recipients

# Getting relative dates as the 'latest'/default argument returns results relative to when it gets called
from usaspending_api.search.tests.data.utilities import setup_elasticsearch_test

TODAY = datetime.datetime.now()
INSIDE_OF_LATEST = TODAY - datetime.timedelta(365 - 2)
FISCAL_INSIDE_OF_LATEST = INSIDE_OF_LATEST + datetime.timedelta(days=30 * 3)

TEST_REF_COUNTRY_CODE = {
    "PARENT COUNTRY CODE": {"country_code": "PARENT COUNTRY CODE", "country_name": "PARENT COUNTRY NAME"},
    "CHILD COUNTRY CODE": {"country_code": "CHILD COUNTRY CODE", "country_name": "CHILD COUNTRY NAME"},
}
MAP_DUNS_TO_CONTRACT = {
    "address_line_1": "address_line1",
    "address_line_2": "address_line2",
    "city": "city_name",
    "congressional_district": "congressional_code",
    "state": "state_code",
    "zip5": "zip",
}

TEST_DUNS = {
    "000000001": {
        "awardee_or_recipient_uniqu": "000000001",
        "legal_business_name": "PARENT RECIPIENT",
        "address_line_1": "PARENT ADDRESS LINE 1",
        "address_line_2": "PARENT ADDRESS LINE 2",
        "city": "PARENT CITY",
        "congressional_district": "PARENT CONGRESSIONAL DISTRICT",
        "country_code": "PARENT COUNTRY CODE",
        "state": "PARENT STATE",
        "zip": "PARENT ZIP",
        "zip4": "PARENT ZIP4",
        "business_types_codes": ["2X"],
        "uei": "AAAAAAAAAAAA",
    },
    "000000002": {
        "awardee_or_recipient_uniqu": "000000002",
        "legal_business_name": "CHILD RECIPIENT",
        "address_line_1": "CHILD ADDRESS LINE 1",
        "address_line_2": "CHILD ADDRESS LINE 2",
        "city": "CHILD CITY",
        "congressional_district": "CHILD CONGRESSIONAL DISTRICT",
        "country_code": "CHILD COUNTRY CODE",
        "state": "CHILD STATE",
        "zip": "CHILD ZIP",
        "zip4": "CHILD ZIP4",
        "business_types_codes": ["A8"],
    },
}
TEST_RECIPIENT_LOCATIONS = {
    "a52a7544-829b-c925-e1ba-d04d3171c09a": {
        "address_line_1": "PARENT ADDRESS LINE 1",
        "address_line_2": "PARENT ADDRESS LINE 2",
        "city": "PARENT CITY",
        "congressional_district": "PARENT CONGRESSIONAL DISTRICT",
        "country_code": "PARENT COUNTRY CODE",
        "state": "PARENT STATE",
        "zip5": "PARENT ZIP",
        "zip4": "PARENT ZIP4",
    },
    "acb93cfc-e4f8-ecd5-5ac3-fa62f115e8f5": {
        "address_line_1": "CHILD ADDRESS LINE 1",
        "address_line_2": "CHILD ADDRESS LINE 2",
        "city": "CHILD CITY",
        "congressional_district": "CHILD CONGRESSIONAL DISTRICT",
        "country_code": "CHILD COUNTRY CODE",
        "state": "CHILD STATE",
        "zip5": "CHILD ZIP",
        "zip4": "CHILD ZIP4",
    },
    "cd6ac2ed-8d2d-2c2e-4934-710eb82100f3": {
        "address_line_1": "OTHER ADDRESS LINE 1",
        "address_line_2": "OTHER ADDRESS LINE 2",
        "city": "OTHER CITY",
        "congressional_district": "OTHER CONGRESSIONAL DISTRICT",
        "country_code": "OTHER COUNTRY CODE",
        "state": "OTHER STATE",
        "zip5": "OTHER ZIP",
        "zip4": "OTHER ZIP4",
    },
    "6dffe44a-554c-26b4-b7ef-44db50083732": {
        "address_line_1": None,
        "address_line_2": None,
        "city": None,
        "congressional_district": None,
        "country_code": None,
        "state": None,
        "zip5": None,
        "zip4": None,
    },
}
TEST_RECIPIENT_LOOKUPS = {
    "a52a7544-829b-c925-e1ba-d04d3171c09a": {
        "recipient_hash": "a52a7544-829b-c925-e1ba-d04d3171c09a",
        "duns": "000000001",
        "uei": "AAAAAAAAAAAA",
        "legal_business_name": "PARENT RECIPIENT",
    },
    "acb93cfc-e4f8-ecd5-5ac3-fa62f115e8f5": {
        "recipient_hash": "acb93cfc-e4f8-ecd5-5ac3-fa62f115e8f5",
        "duns": "000000002",
        "uei": "BBBBBBBBBBBB",
        "legal_business_name": "CHILD RECIPIENT",
    },
    "cd6ac2ed-8d2d-2c2e-4934-710eb82100f3": {
        "recipient_hash": "cd6ac2ed-8d2d-2c2e-4934-710eb82100f3",
        "duns": None,
        "uei": None,
        "legal_business_name": "OTHER RECIPIENT",
    },
    "6dffe44a-554c-26b4-b7ef-44db50083732": {
        "recipient_hash": "6dffe44a-554c-26b4-b7ef-44db50083732",
        "duns": None,
        "uei": None,
        "legal_business_name": "MULTIPLE RECIPIENTS",
    },
}
for hash, recipient in TEST_RECIPIENT_LOOKUPS.items():
    recipient.update(TEST_RECIPIENT_LOCATIONS[hash])

TEST_RECIPIENT_PROFILES = {
    # Parent Recipient, including non-existent child duns
    "a52a7544-829b-c925-e1ba-d04d3171c09a-P": {
        "recipient_level": "P",
        "recipient_hash": "a52a7544-829b-c925-e1ba-d04d3171c09a",
        "recipient_unique_id": "000000001",
        "recipient_name": "PARENT RECIPIENT",
        "recipient_affiliations": [
            "AAAAAAAAAAAA",
            "BBBBBBBBBBBB",
            "ZZZZZZZZZZZZ",
        ],
        "uei": "AAAAAAAAAAAA",
    },
    # Child Recipient 1 - lists itself as both parent and child
    "a52a7544-829b-c925-e1ba-d04d3171c09a-C": {
        "recipient_level": "C",
        "recipient_hash": "a52a7544-829b-c925-e1ba-d04d3171c09a",
        "recipient_unique_id": "000000001",
        "recipient_name": "PARENT RECIPIENT",
        "recipient_affiliations": ["AAAAAAAAAAAA"],
        "uei": "AAAAAAAAAAAA",
    },
    # Child Recipient 2 - different from parent duns
    "acb93cfc-e4f8-ecd5-5ac3-fa62f115e8f5-C": {
        "recipient_level": "C",
        "recipient_hash": "acb93cfc-e4f8-ecd5-5ac3-fa62f115e8f5",
        "recipient_unique_id": "000000002",
        "recipient_name": "CHILD RECIPIENT",
        "recipient_affiliations": ["AAAAAAAAAAAA"],
        "uei": "BBBBBBBBBBBB",
    },
    # Other Recipient
    "cd6ac2ed-8d2d-2c2e-4934-710eb82100f3-R": {
        "recipient_level": "R",
        "recipient_hash": "cd6ac2ed-8d2d-2c2e-4934-710eb82100f3",
        "recipient_unique_id": None,
        "recipient_name": "OTHER RECIPIENT",
        "recipient_affiliations": [],
        "uei": "BBBBBBBBBBBB",
    },
}

TEST_SUMMARY_TRANSACTION_NORMALIZED_FOR_FPDS = {
    "latest": {
        "action_date": INSIDE_OF_LATEST,
        "fiscal_action_date": FISCAL_INSIDE_OF_LATEST,
        "federal_action_obligation": 100,
        "generated_pragmatic_obligation": 100,
    },
    "FY2016": {
        "action_date": datetime.datetime(2015, 10, 1),
        "fiscal_action_date": datetime.datetime(2016, 1, 1),
        "federal_action_obligation": 50,
        "generated_pragmatic_obligation": 50,
    },
    "FY2008": {
        "action_date": datetime.datetime(2007, 10, 1),
        "fiscal_action_date": datetime.datetime(2008, 1, 1),
        "federal_action_obligation": 200,
        "generated_pragmatic_obligation": 200,
    },
}
TEST_SUMMARY_TRANSACTION_NORMALIZED_FOR_FABS = {
    "latest": {
        "action_date": INSIDE_OF_LATEST,
        "fiscal_action_date": FISCAL_INSIDE_OF_LATEST,
        "face_value_loan_guarantee": 1000,
        "type": "07",
        "generated_pragmatic_obligation": 0,
    },
    "FY2016": {
        "action_date": datetime.datetime(2015, 10, 1),
        "fiscal_action_date": datetime.datetime(2016, 1, 1),
        "face_value_loan_guarantee": 500,
        "type": "08",
        "generated_pragmatic_obligation": 0,
    },
    "FY2008": {
        "action_date": datetime.datetime(2007, 10, 1),
        "fiscal_action_date": datetime.datetime(2008, 1, 1),
        "face_value_loan_guarantee": 2000,
        "type": "08",
        "generated_pragmatic_obligation": 0,
    },
}
TEST_SUMMARY_TRANSACTION_RECIPIENT = {
    "latest": {
        "recipient_name": "PARENT RECIPIENT",
        "recipient_unique_id": "000000001",
        "parent_recipient_unique_id": "000000001",
        "recipient_uei": "AAAAAAAAAAAA",
        "parent_uei": "AAAAAAAAAAAA",
        "recipient_hash": "a52a7544-829b-c925-e1ba-d04d3171c09a",
        "parent_recipient_hash": "a52a7544-829b-c925-e1ba-d04d3171c09a",
        "recipient_levels": ["P", "C"],
    },
    "FY2016": {
        "recipient_name": "CHILD RECIPIENT",
        "recipient_unique_id": "000000002",
        "parent_recipient_unique_id": "000000001",
        "recipient_uei": "BBBBBBBBBBBB",
        "parent_uei": "AAAAAAAAAAAA",
        "recipient_hash": "acb93cfc-e4f8-ecd5-5ac3-fa62f115e8f5",
        "parent_recipient_hash": "a52a7544-829b-c925-e1ba-d04d3171c09a",
        "recipient_levels": ["C"],
    },
    "FY2008": {
        "recipient_name": "OTHER RECIPIENT",
        "recipient_unique_id": None,
        "parent_recipient_unique_id": None,
        "parent_uei": None,
        "recipient_hash": "cd6ac2ed-8d2d-2c2e-4934-710eb82100f3",
        "recipient_levels": ["R"],
    },
}

@pytest.mark.django_db
def create_transaction_test_data(transaction_recipient_list=None):

    if transaction_recipient_list is None:
        transaction_recipient_list = list(TEST_SUMMARY_TRANSACTION_RECIPIENT.values())

    id = 1

    for count, transaction_search in enumerate(TEST_SUMMARY_TRANSACTION_NORMALIZED_FOR_FPDS.values()):
        base_transaction_search = {
            "transaction_id": id,
            "award_id": id,
            "is_fpds": True,
            "business_categories": ["expected", "business", "cat"],
        }
        base_transaction_search.update(transaction_search)
        base_transaction_search.update(transaction_recipient_list[count])
        baker.make("search.AwardSearch", award_id=id, latest_transaction_id=id)
        baker.make("search.TransactionSearch", **base_transaction_search)

        id += 1

    for count, transaction_search in enumerate(TEST_SUMMARY_TRANSACTION_NORMALIZED_FOR_FABS.values()):
        base_transaction_search = {
            "transaction_id": id,
            "award_id": id,
            "is_fpds": False,
            "business_categories": ["expected", "business", "cat"],
        }
        base_transaction_search.update(transaction_search)
        base_transaction_search.update(transaction_recipient_list[count])
        baker.make("search.AwardSearch", award_id=id, latest_transaction_id=id)
        baker.make("search.TransactionSearch", **base_transaction_search)

        id += 1

@pytest.mark.django_db
def create_recipient_profile_test_data(*recipient_profile_list):
    for recipient_profile in recipient_profile_list:
        baker.make("recipient.RecipientProfile", **recipient_profile)

@pytest.mark.django_db
def create_recipient_lookup_test_data(*recipient_lookup_list):
    for recipient_lookup in recipient_lookup_list:
        baker.make("recipient.RecipientLookup", **recipient_lookup)

@pytest.mark.django_db
def test_validate_recipient_id_success():
    """ Testing a run of a valid recipient id """
    recipient_id = "a52a7544-829b-c925-e1ba-d04d3171c09a-P"
    baker.make("recipient.RecipientProfile", **TEST_RECIPIENT_PROFILES[recipient_id])

    expected_hash = recipient_id[:-2]
    expected_level = recipient_id[-1]
    try:
        recipient_hash, recipient_level = recipients.validate_recipient_id(recipient_id)
        assert recipient_hash == expected_hash
        assert recipient_level == expected_level
    except InvalidParameterException:
        assert False

@pytest.mark.django_db
def test_validate_recipient_id_failures():
    """ Testing a run of invalid recipient ids """
    recipient_id = "a52a7544-829b-c925-e1ba-d04d3171c09a-P"
    baker.make("recipient.RecipientProfile", **TEST_RECIPIENT_PROFILES[recipient_id])

    def call_validate_recipient_id(recipient_id):
        try:
            recipients.validate_recipient_id(recipient_id)
            return False
        except InvalidParameterException:
            return True

    # Test with no dashes
    recipient_id = "broken_recipient_id"
    assert call_validate_recipient_id(recipient_id) is True

    # Test with invalid recipient level
    recipient_id = "broken_recipient-id"
    assert call_validate_recipient_id(recipient_id) is True

    # Test with invalid hash
    recipient_id = "broken_recipient-R"
    assert call_validate_recipient_id(recipient_id) is True

    # Test with id not available
    recipient_id = "00002940-fdbe-3fc5-9252-000000-R"
    assert call_validate_recipient_id(recipient_id) is True

@pytest.mark.django_db
def test_extract_duns_uei_name_from_hash():
    """ Testing extracting name and duns from the recipient hash """
    recipient_hash = "a52a7544-829b-c925-e1ba-d04d3171c09a"
    baker.make("recipient.RecipientLookup", **TEST_RECIPIENT_LOOKUPS[recipient_hash])

    expected_duns = TEST_RECIPIENT_LOOKUPS[recipient_hash]["duns"]
    expected_uei = TEST_RECIPIENT_LOOKUPS[recipient_hash]["uei"]
    expected_name = TEST_RECIPIENT_LOOKUPS[recipient_hash]["legal_business_name"]
    duns, uei, name = recipients.extract_duns_uei_name_from_hash(recipient_hash)
    assert duns == expected_duns
    assert uei == expected_uei
    assert name == expected_name

@pytest.mark.django_db
def test_extract_parent_from_hash():
    """ Testing extracting parent duns/name from recipient hash"""
    # This one specifically has to be a child
    recipient_id = "acb93cfc-e4f8-ecd5-5ac3-fa62f115e8f5-C"
    recipient_hash = TEST_RECIPIENT_PROFILES[recipient_id]["recipient_hash"]
    baker.make("recipient.RecipientProfile", **TEST_RECIPIENT_PROFILES[recipient_id])

    expected_parent_id = "a52a7544-829b-c925-e1ba-d04d3171c09a-P"
    parent_hash = expected_parent_id[:-2]
    baker.make("recipient.RecipientLookup", **TEST_RECIPIENT_LOOKUPS[parent_hash])

    expected_name = TEST_RECIPIENT_LOOKUPS[parent_hash]["legal_business_name"]
    expected_duns = TEST_RECIPIENT_LOOKUPS[parent_hash]["duns"]
    parents = recipients.extract_parents_from_hash(recipient_hash)
    assert expected_duns == parents[0]["parent_duns"]
    assert expected_name == parents[0]["parent_name"]
    assert expected_parent_id == parents[0]["parent_id"]

@pytest.mark.django_db
def test_extract_parent_from_hash_failure():
    """Testing extracting parent duns/name from recipient hash but with recipient lookup removed
    as there may be cases where the parent recipient is not found/listed
    """
    # This one specifically has to be a child
    recipient_id = "acb93cfc-e4f8-ecd5-5ac3-fa62f115e8f5-C"
    recipient_hash = TEST_RECIPIENT_PROFILES[recipient_id]["recipient_hash"]
    baker.make("recipient.RecipientProfile", **TEST_RECIPIENT_PROFILES[recipient_id])

    expected_name = None
    expected_duns = None
    expected_parent_id = None
    parents = recipients.extract_parents_from_hash(recipient_hash)
    assert expected_duns == parents[0]["parent_duns"]
    assert expected_name == parents[0]["parent_name"]
    assert expected_parent_id == parents[0]["parent_id"]

@pytest.mark.django_db
def test_extract_location_success():
    """ Testing extracting location data from recipient hash using the DUNS table """
    recipient_hash = "a52a7544-829b-c925-e1ba-d04d3171c09a"
    baker.make("recipient.RecipientLookup", **TEST_RECIPIENT_LOOKUPS[recipient_hash])
    country_code = TEST_RECIPIENT_LOCATIONS[recipient_hash]["country_code"]
    baker.make("references.RefCountryCode", **TEST_REF_COUNTRY_CODE[country_code])

    additional_blank_fields = ["address_line3", "foreign_province", "county_name", "foreign_postal_code"]
    expected_location = TEST_RECIPIENT_LOCATIONS[recipient_hash].copy()
    expected_location["country_name"] = TEST_REF_COUNTRY_CODE[country_code]["country_name"]
    for additional_blank_field in additional_blank_fields:
        expected_location[additional_blank_field] = None
    for k in MAP_DUNS_TO_CONTRACT:
        expected_location[MAP_DUNS_TO_CONTRACT[k]] = expected_location[k]
        del expected_location[k]
    location = recipients.extract_location(recipient_hash)
    assert location == expected_location

@pytest.mark.django_db
def test_cleanup_location():
    """ Testing cleaning up the location data """

    # Test United States fix
    test_location = {"country_code": "UNITED STATES"}
    assert {"country_code": "USA", "country_name": None} == recipients.cleanup_location(test_location)

    # Test Country_Code
    baker.make("references.RefCountryCode", country_code="USA", country_name="UNITED STATES")
    test_location = {"country_code": "USA"}
    assert {"country_code": "USA", "country_name": "UNITED STATES"} == recipients.cleanup_location(test_location)

    # Test Congressional Codes
    test_location = {"congressional_code": "CA13"}
    assert {"congressional_code": "13"} == recipients.cleanup_location(test_location)
    test_location = {"congressional_code": "13.0"}
    assert {"congressional_code": "13"} == recipients.cleanup_location(test_location)

@pytest.mark.django_db
def test_extract_business_categories(monkeypatch):
    """ Testing extracting business categories from the recipient name/duns """
    recipient_hash = "a52a7544-829b-c925-e1ba-d04d3171c09a"
    recipient_name = TEST_RECIPIENT_LOOKUPS[recipient_hash]["legal_business_name"]
    recipient_uei = TEST_RECIPIENT_LOOKUPS[recipient_hash]["uei"]
    business_categories = ["le", "business", "cat"]

    utm_objects = Mock()
    utm_objects.filter().order_by().values().first.return_value = {"business_categories": business_categories}
    monkeypatch.setattr("usaspending_api.search.models.TransactionSearch.objects", utm_objects)

    baker.make("recipient.RecipientLookup", **TEST_RECIPIENT_LOOKUPS[recipient_hash])

    # Mock DUNS
    # Should add 'category_business'
    baker.make("recipient.DUNS", **TEST_DUNS[TEST_RECIPIENT_LOOKUPS[recipient_hash]["duns"]])

    expected_business_cat = business_categories + ["category_business"]
    business_cat = recipients.extract_business_categories(recipient_name, recipient_uei, recipient_hash)
    # testing for equality-only, order unnecessary
    assert sorted(business_cat) == sorted(expected_business_cat)

@pytest.mark.django_db
def test_extract_business_categories_special():
    """ Testing extracting the business categories for a special case  """
    recipient_name = "MULTIPLE RECIPIENTS"
    recipient_uei = None
    recipient_hash = ""
    business_categories = recipients.extract_business_categories(recipient_name, recipient_uei, recipient_hash)
    assert business_categories == []

@pytest.mark.django_db
def test_obtain_recipient_totals_year(monkeypatch, elasticsearch_transaction_index):
    """ Testing recipient totals with different year values """
    # Testing with specific child
    recipient_id = "acb93cfc-e4f8-ecd5-5ac3-fa62f115e8f5-C"
    recipient_hash = recipient_id[:-2]

    # load all of the transactions
    transaction_recipient_data = {
        "recipient_name": "CHILD RECIPIENT",
        "recipient_name_raw": "CHILD RECIPIENT",
        "recipient_unique_id": "000000002",
        "recipient_uei": "BBBBBBBBBBBB",
        "parent_recipient_unique_id": "000000001",
        "recipient_hash": recipient_hash,
        "recipient_levels": ["C"],
    }
    create_transaction_test_data([transaction_recipient_data] * len(TEST_SUMMARY_TRANSACTION_RECIPIENT))

    # load recipient lookup
    create_recipient_lookup_test_data(TEST_RECIPIENT_LOOKUPS[recipient_hash])

    # For latest transaction's we're pulling from recipient_profile
    associated_recipient_profile = TEST_RECIPIENT_PROFILES[recipient_id].copy()
    associated_recipient_profile["last_12_months"] = 100
    associated_recipient_profile["last_12_months_count"] = 1
    baker.make("recipient.RecipientProfile", **associated_recipient_profile)

    setup_elasticsearch_test(monkeypatch, elasticsearch_transaction_index)

    # Latest
    results = recipients.obtain_recipient_totals(recipient_id, year="latest")
    assert results[0]["total_obligation_amount"] == 100
    assert results[0]["total_obligation_count"] == 2
    assert results[0]["total_face_value_loan_amount"] == 1000
    assert results[0]["total_face_value_loan_count"] == 1

    # All
    results = recipients.obtain_recipient_totals(recipient_id, year="all")
    assert results[0]["total_obligation_amount"] == 350
    assert results[0]["total_obligation_count"] == 6
    assert results[0]["total_face_value_loan_amount"] == 3500
    assert results[0]["total_face_value_loan_count"] == 3

    # FY2016
    results = recipients.obtain_recipient_totals(recipient_id, year="2016")
    assert results[0]["total_obligation_amount"] == 50
    assert results[0]["total_obligation_count"] == 2
    assert results[0]["total_face_value_loan_amount"] == 500
    assert results[0]["total_face_value_loan_count"] == 1

@pytest.mark.django_db
def test_obtain_recipient_totals_parent(monkeypatch, elasticsearch_transaction_index):
    """ Testing recipient totals with parent child relationships """
    # Testing with specific parent/child ids
    parent_id = "a52a7544-829b-c925-e1ba-d04d3171c09a-P"

    # load recipient profiles
    for recipient_id, recipient_profile in TEST_RECIPIENT_PROFILES.items():
        baker.make("recipient.RecipientProfile", **recipient_profile)

    # load transactions for each child and parent (making sure it's excluded)
    create_transaction_test_data()

    # load recipient lookup
    create_recipient_lookup_test_data(*TEST_RECIPIENT_LOOKUPS.values())

    setup_elasticsearch_test(monkeypatch, elasticsearch_transaction_index)

    results = recipients.obtain_recipient_totals(parent_id, year="all")
    assert results[0]["total_obligation_amount"] == 150
    assert results[0]["total_obligation_count"] == 4
    assert results[0]["total_face_value_loan_amount"] == 1500
    assert results[0]["total_face_value_loan_count"] == 2

def recipient_overview_endpoint(id, year="latest"):
    endpoint = "/api/v2/recipient/duns/{}/".format(id)
    if year:
        endpoint = "{}?year={}".format(endpoint, year)
    return endpoint

@pytest.mark.django_db
def test_recipient_overview(client, monkeypatch, elasticsearch_transaction_index):
    """ Testing a simple example of the endpoint as a whole """
    r_id = "a52a7544-829b-c925-e1ba-d04d3171c09a-C"

    # Mock Transactions
    create_transaction_test_data()

    # Mock Recipient Profiles
    for recipient_id, recipient_profile in TEST_RECIPIENT_PROFILES.items():
        recipient_profile_copy = recipient_profile.copy()
        if recipient_id == r_id:
            recipient_profile_copy["last_12_months"] = 100
            recipient_profile_copy["last_12_months_count"] = 1
        baker.make("recipient.RecipientProfile", **recipient_profile_copy)

    # Mock Recipient Lookups
    create_recipient_lookup_test_data(*TEST_RECIPIENT_LOOKUPS.values())

    # Mock DUNS - should add `category-business`
    for duns, duns_dict in TEST_DUNS.items():
        test_duns_model = duns_dict.copy()
        country_code = test_duns_model["country_code"]
        baker.make("recipient.DUNS", **test_duns_model)
        baker.make("references.RefCountryCode", **TEST_REF_COUNTRY_CODE[country_code])

    setup_elasticsearch_test(monkeypatch, elasticsearch_transaction_index)

    resp = client.get(recipient_overview_endpoint(r_id))
    assert resp.status_code == status.HTTP_200_OK
    expected = {
        "name": "PARENT RECIPIENT",
        "alternate_names": [],
        "duns": "000000001",
        "uei": "AAAAAAAAAAAA",
        "recipient_id": "a52a7544-829b-c925-e1ba-d04d3171c09a-C",
        "recipient_level": "C",
        "parent_name": "PARENT RECIPIENT",
        "parent_duns": "000000001",
        "parent_id": "a52a7544-829b-c925-e1ba-d04d3171c09a-P",
        "parent_uei": "AAAAAAAAAAAA",
        "parents": [
            {
                "parent_duns": "000000001",
                "parent_id": "a52a7544-829b-c925-e1ba-d04d3171c09a-P",
                "parent_name": "PARENT RECIPIENT",
                "parent_uei": "AAAAAAAAAAAA",
            }
        ],
        "business_types": sorted(["expected", "business", "cat"] + ["category_business"]),
        "location": {
            "address_line1": "PARENT ADDRESS LINE 1",
            "address_line2": "PARENT ADDRESS LINE 2",
            "address_line3": None,
            "county_name": None,
            "city_name": "PARENT CITY",
            "congressional_code": "PARENT CONGRESSIONAL DISTRICT",
            "country_code": "PARENT COUNTRY CODE",
            "country_name": "PARENT COUNTRY NAME",
            "state_code": "PARENT STATE",
            "zip": "PARENT ZIP",
            "zip4": "PARENT ZIP4",
            "foreign_province": None,
            "foreign_postal_code": None,
        },
        "total_transaction_amount": 100,
        "total_transactions": 2,
        "total_face_value_loan_amount": 1000,
        "total_face_value_loan_transactions": 1,
    }
    # testing for equality-only, order unnecessary
    resp.data["business_types"] = sorted(resp.data["business_types"])
    assert resp.data == expected

@pytest.mark.django_db
def test_extract_hash_from_duns_or_uei_via_duns():
    """ Testing extracting the hash/name from a DUNS """
    example_duns = "000000001"
    expected_hash = "a52a7544-829b-c925-e1ba-d04d3171c09a"
    baker.make("recipient.RecipientLookup", **TEST_RECIPIENT_LOOKUPS[expected_hash])

    recipient_hash = recipients.extract_hash_from_duns_or_uei(example_duns)
    assert UUID(expected_hash) == recipient_hash

@pytest.mark.django_db
def test_extract_hash_from_duns_or_uei_via_uei():
    """ Testing extracting the hash/name from a DUNS """
    example_uei = "AAAAAAAAAAAA"
    expected_hash = "a52a7544-829b-c925-e1ba-d04d3171c09a"
    baker.make("recipient.RecipientLookup", **TEST_RECIPIENT_LOOKUPS[expected_hash])

    recipient_hash = recipients.extract_hash_from_duns_or_uei(example_uei)
    assert UUID(expected_hash) == recipient_hash

def recipient_children_endpoint(duns, year="latest"):
    endpoint = "/api/v2/recipient/children/{}/".format(duns)
    if year:
        endpoint = "{}?year={}".format(endpoint, year)
    return endpoint

@pytest.mark.django_db
def test_child_recipient_success(client, monkeypatch, elasticsearch_transaction_index):
    """ Testing successful child recipient calls """
    child1_id = "a52a7544-829b-c925-e1ba-d04d3171c09a-C"
    parent_child1_duns = "000000001"
    child2_id = "acb93cfc-e4f8-ecd5-5ac3-fa62f115e8f5-C"
    child2_duns = "000000002"

    # Mock Recipient Profiles
    create_recipient_profile_test_data(*TEST_RECIPIENT_PROFILES.values())

    # Mock Recipient Lookups
    create_recipient_lookup_test_data(*TEST_RECIPIENT_LOOKUPS.values())

    # Mock Transactions
    create_transaction_test_data()

    setup_elasticsearch_test(monkeypatch, elasticsearch_transaction_index)

    # Ignoring nonexistent child hash - 00eadaa1-6e1f-22f2-419b-e5894374db96
    child1_object = {
        "recipient_id": child1_id,
        "name": "PARENT RECIPIENT",
        "duns": parent_child1_duns,
        "uei": "AAAAAAAAAAAA",
        "amount": 100,
        "state_province": "PARENT STATE",
    }
    child2_object = {
        "recipient_id": child2_id,
        "name": "CHILD RECIPIENT",
        "duns": child2_duns,
        "uei": "BBBBBBBBBBBB",
        "amount": 50,
        "state_province": "CHILD STATE",
    }
    expected = [child1_object, child2_object]
    resp = client.get(recipient_children_endpoint(parent_child1_duns, "all"))
    assert resp.status_code == status.HTTP_200_OK
    # testing for equality-only, order unnecessary
    assert sorted(resp.data, key=lambda key: key["recipient_id"]) == expected

@pytest.mark.django_db
def test_child_recipient_failures(client):
    """ Testing failed child recipient calls """
    # Mock Recipient Profiles
    create_recipient_profile_test_data(*TEST_RECIPIENT_PROFILES.values())

    # Mock Recipient Lookups
    create_recipient_lookup_test_data(*TEST_RECIPIENT_LOOKUPS.values())

    # Mock Transactions
    create_transaction_test_data()

    # Testing for non-existent DUNS
    non_existent_duns = "000000003"
    resp = client.get(recipient_children_endpoint(non_existent_duns, "all"))
    assert resp.status_code == status.HTTP_400_BAD_REQUEST
    assert resp.data["detail"] == "Recipient not found: '{}'.".format(non_existent_duns)


#!/usr/bin/env python3
"""
http://adventofcode.com/day/18

Part 1
------
After the million lights incident, the fire code has gotten
stricter: now, at most ten thousand lights are allowed. You
arrange them in a 100x100 grid.

Never one to let you down, Santa again mails you instructions
on the ideal lighting configuration. With so few lights, he
says, you'll have to resort to animation.

Start by setting your lights to the included initial
configuration (your puzzle input). A # means "on", and a .
means "off".

Then, animate your grid in steps, where each step decides the
next configuration based on the current one. Each light's next
state (either on or off) depends on its current state and the
current states of the eight lights adjacent to it (including
diagonals). Lights on the edge of the grid might have fewer
than eight neighbors; the missing ones always count as "off".

For example, in a simplified 6x6 grid, the light marked A has
the neighbors numbered 1 through 8, and the light marked B, which
is on an edge, only has the neighbors marked 1 through 5:

    1B5...
    234...
    ......
    ..123.
    ..8A4.
    ..765.

The state a light should have next is based on its current
state (on or off) plus the number of neighbors that are on:

  - A light which is on stays on when 2 or 3 neighbors are on, and
     turns off otherwise.
  - A light which is off turns on if exactly 3 neighbors are on,
     and stays off otherwise.
  - All of the lights update simultaneously; they all consider the
     same current state before moving to the next.

Here's a few steps from an example configuration of another 6x6 grid:

    Initial state:
    .#.#.#
    ...##.
    #....#
    ..#...
    #.#..#
    ####..

    After 1 step:
    ..##..
    ..##.#
    ...##.
    ......
    #.....
    #.##..

    After 2 steps:
    ..###.
    ......
    ..###.
    ......
    .#....
    .#....

    After 3 steps:
    ...#..
    ......
    ...#..
    ..##..
    ......
    ......

    After 4 steps:
    ......
    ......
    ..##..
    ..##..
    ......
    ......

After 4 steps, this example has four lights on.

In your grid of 100x100 lights, given your initial
configuration, how many lights are on after 100 steps?

Part 2
------
You flip the instructions over; Santa goes on to point out
that this is all just an implementation of Conway's Game of
Life. At least, it was, until you notice that something's
wrong with the grid of lights you bought: four lights, one
in each corner, are stuck on and can't be turned off. The
example above will actually run like this:

    Initial state:
    ##.#.#
    ...##.
    #....#
    ..#...
    #.#..#
    ####.#

    After 1 step:
    #.##.#
    ####.#
    ...##.
    ......
    #...#.
    #.####

    After 2 steps:
    #..#.#
    #....#
    .#.##.
    ...##.
    .#..##
    ##.###

    After 3 steps:
    #...##
    ####.#
    ..##.#
    ......
    ##....
    ####.#

    After 4 steps:
    #.####
    #....#
    ...#..
    .##...
    #.....
    #.#..#

    After 5 steps:
    ##.###
    .##..#
    .##...
    .##...
    #.#...
    ##...#

After 5 steps, this example now has 17 lights on.

In your grid of 100x100 lights, given your initial configuration,
but with the four corners always in the on state, how many
lights are on after 100 steps?
"""

from __future__ import print_function, unicode_literals
from copy import deepcopy
import os
import sys

INFILE = 'inputs/input18.txt'
DIMENSION = 100
STEPS = 100

def count(grid, x, y):
    neighbors = list()

    neighbors.append(grid[x-1][y-1])
    neighbors.append(grid[x-1][y])
    neighbors.append(grid[x-1][y+1])
    neighbors.append(grid[x][y-1])
    neighbors.append(grid[x][y+1])
    neighbors.append(grid[x+1][y-1])
    neighbors.append(grid[x+1][y])
    neighbors.append(grid[x+1][y+1])

    return sum(neighbors)

def life(grid, steps, stuck_corners=False):
    g = deepcopy(grid)

    for i in range(steps):
        g = _life(g, stuck_corners)

    return g

def _life(grid, stuck_corners=False):
    if stuck_corners:
        grid[1][1] = 1
        grid[1][100] = 1
        grid[100][1] = 1
        grid[100][100] = 1

    new_grid = deepcopy(grid)

    for x in range(1, DIMENSION + 1):
        for y in range(1, DIMENSION + 1):
            c = count(grid, x, y)
            s = grid[x][y]

            if s == 1 and c != 2 and c != 3:
                s = 0
            if s == 0 and c == 3:
                s = 1

            new_grid[x][y] = s

    if stuck_corners:
        new_grid[1][1] = 1
        new_grid[1][100] = 1
        new_grid[100][1] = 1
        new_grid[100][100] = 1

    return new_grid

def main():
    # Initial state
    lights = [[0 for x in range(DIMENSION + 2)] for x in range(DIMENSION + 2)]
    with open(INFILE) as f:
        current_line = 1
        current_char = 1

        for line in f:
            for char in line.strip():
                if '#' == char:
                    lights[current_line][current_char] = 1
                current_char += 1
            current_line += 1
            current_char = 1

    # Part 1
    grid = life(lights, STEPS)
    p1count = sum(map(sum, grid))

    # Part 2
    grid = life(lights, STEPS, True)
    p2count = sum(map(sum, grid))

    msg = '[Python]  Puzzle 18-1: {}'
    print(msg.format(p1count))

    msg = '[Python]  Puzzle 18-2: {}'
    print(msg.format(p2count))

if __name__ == '__main__':
    main()


# -*- coding: utf-8 -*-
import http
from http.server import  BaseHTTPRequestHandler
from werkzeug import urls
import os
import json
import traceback
from BLD_Parser import parse_solve
from DB_LOGS import add_log_of_request
def init_env_var(dict_params):

    os.environ["SMART_CUBE"] = "True" if dict_params["SMART_CUBE"] == True else "False"
    os.environ["GEN_PARSED_TO_CUBEDB"] = "True" if dict_params["GEN_PARSED_TO_CUBEDB"] == True else "False"
    os.environ["GEN_PARSED_TO_TXT"] = "True" if dict_params["GEN_PARSED_TO_TXT"] == True else "False"
    os.environ["NAME_OF_SOLVE"] = dict_params["NAME_OF_SOLVE"]
    os.environ["TIME_SOLVE"] = dict_params["TIME_SOLVE"]
    os.environ["COMMS_UNPARSED"] = "True" if dict_params["COMMS_UNPARSED"]  == True else "False"
    os.environ["GEN_WITH_MOVE_COUNT"] = "True" if dict_params["GEN_WITH_MOVE_COUNT"] == True else "False"
    os.environ["DIFF_BETWEEN_ALGS"] = dict_params["DIFF_BETWEEN_ALGS"]
    os.environ["PARSE_TO_LETTER_PAIR"] = "True" if dict_params["PARSE_TO_LETTER_PAIR"] == True else "False"
    os.environ["EDGES_BUFFER"] = dict_params["EDGES_BUFFER"]
    os.environ["CORNER_BUFFER"] = dict_params["CORNER_BUFFER"]
    os.environ["LETTER_PAIRS_DICT"] = dict_params["LETTER_PAIRS_DICT"]
    os.environ["SCRAMBLE"] = dict_params["SCRAMBLE"]
    os.environ["SOLVE"] = dict_params["SOLVE"]
    os.environ["MEMO"] = dict_params["MEMO"]
    os.environ["SOLVE_TIME_MOVES"] = dict_params["SOLVE_TIME_MOVES"]
    os.environ["DATE_SOLVE"] = dict_params["DATE_SOLVE"]
    os.environ["ID"] = dict_params["ID"]

def parse(dict_params):
    init_env_var(dict_params)
    cube = parse_solve(dict_params["SCRAMBLE"], dict_params["SOLVE"])
    parsed_solve = json.dumps(cube.parsed_solve)

    return (parsed_solve,cube)

class S(BaseHTTPRequestHandler):
    def _set_response(self):
        self.send_response(200)
        self.send_header('Content-type', 'text/html; charset=utf-8')
        self.send_header('Access-Control-Allow-Origin', '*')
        self.end_headers()

    def do_OPTIONS(self):
        self.send_response(200, "ok")
        self.send_header('Access-Control-Allow-Origin', '*')
        self.send_header('Access-Control-Allow-Headers', "*")
        self.end_headers()

    def do_POST(self):
        try:
            address = self.client_address[0]

            content_length = int(self.headers['Content-Length'])  # <--- Gets the size of data
            request = self.rfile.read(content_length)  # <--- Gets the data itself
            post_data = json.loads(request)

            data = parse(post_data)
            solve_str = data[0]
            cube = data[1]
            self._set_response()
            self.wfile.write(bytearray((solve_str).encode('utf-8')))
            try:
                add_log_of_request(request, address, '200', cube)
            except Exception as e:
                add_log_of_request(request, address, '404',error=traceback.format_exc())
        except Exception as e:
            traceback.format_exc()
            add_log_of_request(request, address, '404', error=traceback.format_exc())
            self.send_error(404, 'error')

def run_http_server():
    PORT = os.environ['PORT']
    server_address = ('0.0.0.0', int(PORT))
    # server_address = ('127.0.0.1', 8080)
    httpd = http.server.HTTPServer(server_address, S)
    httpd.serve_forever()

def main():
    pass

if __name__ == '__main__':
    main()


f = open('day1.txt')

elves = []
currentCalories = 0

for line in f:
    #print(line.rstrip())
    if line.rstrip() != '':
        currentCalories += int(line.rstrip())
    else:
        elves.append(currentCalories)
        currentCalories = 0

elves.sort()

# Elf with the most calories
print(elves[-1])

# Combined calories of the top 3 elves
print(sum(elves[-3:]))

f.close()


from abc import ABC
from base import BaseDataLoader
from torch.utils.data import Dataset, IterableDataset
import pandas as pd
import os
import torch
from pathlib import Path
import glob
import random

class ScoreDataSet(Dataset):
    def __init__(self, file_path, callback_func=None):
        self.data = pd.read_csv(file_path)
        self.y = self.data["rating"].values
        self.X = self.data.drop(columns=["rating"]).values

    def __getitem__(self, item):
        return self.X[item, :], self.y[item]

    def __len__(self):
        return self.y.shape[0]

class ScoreDataLoader(BaseDataLoader):
    def __init__(self, data_dir, batch_size, drop_last=False, shuffle=True, validation_split=0.0, num_workers=1, training=True):
        self.dataset = ScoreDataSet(data_dir)
        super().__init__(self.dataset, batch_size, shuffle, validation_split, num_workers)

class MultiFilesBase(IterableDataset, ABC):
    def __init__(self, data_dir, glob_rule=None, batch_size=32, drop_lst=False, files_shuffle=True, map_line=None):
        super(MultiFilesBase, self).__init__()
        self.data_dir = Path(data_dir)
        self.glob_rule = glob_rule
        self.batch_size = batch_size
        self.drop_lst = drop_lst
        self.map_line = map_line
        self.files = self._total_files()
        if files_shuffle: random.shuffle(self.files)

    def _total_files(self):
        if self.glob_rule is None:
            return os.listdir(self.data_dir)
        return glob.glob(str(self.data_dir / self.glob_rule))

class MultiFilesDataSetInterable(MultiFilesBase, ABC):
    def __iter__(self):
        X, y = [], []
        for f_name in self.files:
            for line in open(f_name, encoding="utf-8"):
                ids, label = self.map_line(line)
                X.append(ids)
                y.append(label)
                if len(X) >= self.batch_size:
                    yield X, y
                    X, y = [], []
        if len(X) > 0 and not self.drop_lst:
            yield X, y

class MultiFilesInMemDataSetInterable(MultiFilesBase, ABC):
    def __iter__(self):
        X, y = [], []
        for f_name in self.files:
            with open(f_name, encoding="utf-8") as f:
                lines = [i.strip() for i in f.readlines()]
            for line in lines:
                ids, label = self.map_line(line)
                X.append(ids)
                y.append(label)
                if len(X) >= self.batch_size:
                    yield X, y
                    X, y = [], []
        if len(X) > 0 and not self.drop_lst:
            yield X, y

class ScoreDataSetIterable(IterableDataset, ABC):
    def __init__(self, data_dir, batch_size=32, drop_last=False):
        self.data_dir = data_dir
        self.drop_last = drop_last
        self.batch_size = batch_size

    def __iter__(self):
        for file_name in os.listdir(self.data_dir):
            if "csv" not in file_name:
                continue
            file_path = os.path.join(self.data_dir, file_name)
            for chunk in pd.read_csv(file_path, chunksize=self.batch_size):
                if self.drop_last and chunk.shape[0] < self.batch_size:
                    continue
                yield self._map_func(chunk)

    def _map_func(self, df_chunk):
        y = torch.Tensor(df_chunk["label"].values)
        X = torch.Tensor(df_chunk.drop(columns=["label"]).values)
        return X, y

class MultiCSVInmemDataSetIterable(IterableDataset, ABC):
    def __init__(self, data_dir, batch_size=32, drop_last=False):
        self.data_dir = data_dir
        self.drop_last = drop_last
        self.batch_size = batch_size

    def __iter__(self):
        for file_name in os.listdir(self.data_dir):
            if "csv" not in file_name:
                continue
            file_path = os.path.join(self.data_dir, file_name)
            for chunk in pd.read_csv(file_path, chunksize=self.batch_size):
                if self.drop_last and chunk.shape[0] < self.batch_size:
                    continue
                yield self._map_func(chunk)

    def _map_func(self, df_chunk):
        y = torch.Tensor(df_chunk["label"].values)
        X = torch.Tensor(df_chunk.drop(columns=["label"]).values)
        return X, y


import numpy as np
from numpy import exp, sqrt, cos, pi, sin

from base_function import BaseFunction

class HolderTable(BaseFunction):
    target_E = -19.2085
    xmin = np.array([-10.,-10.])
    xmax = np.array([10.,10.])
    stepsize = 2.
    temperature = 2.
    def getEnergy(self, coords):
        x, y = coords
        E = - abs(sin(x)* cos(y) * exp(abs(1. - sqrt(x**2 + y**2)/ pi)))
        return E

    def dabs(self, x):
        """derivative of absolute value"""
        if x < 0: return -1.
        elif x > 0: return 1.
        else: return 0.

    def getEnergyGradient(self, coords):
        x, y = coords
        R = sqrt(x**2 + y**2)
        g = 1. - R / pi
        f = sin(x)* cos(y) * exp(abs(g))
        E = -abs(f)

        dRdx = x / R
        dgdx = - dRdx / pi
        dfdx = cos(x) * cos(y) * exp(abs(g)) + f * self.dabs(g) * dgdx
        dEdx = - self.dabs(f) * dfdx

        dRdy = y / R
        dgdy = - dRdy / pi
        dfdy = -sin(x) * sin(y) * exp(abs(g)) + f * self.dabs(g) * dgdy
        dEdy = - self.dabs(f) * dfdy
        return E, np.array([dEdx, dEdy])

if __name__ == "__main__":
    f = HolderTable()
    f.test_potential(f.get_random_configuration())

    from base_function import makeplot2d
    makeplot2d(f)


#!/usr/bin/env python
# encoding: utf-8
# Date: 2023/02/11
# file: _datetime.py
# Email:
# Author: rakiwine

# epoch	时间开始的点，取决于平台
# UTC	协调世界时（Coordinated Universal Time），格林威治标准时间（GMT）
# DST	夏令时（Daylight Saving Time）

from pytz import utc, timezone
import datetime
from datetime import timezone as _timezone

# 猜测第三方插件原理 返回时区子类
de = timezone('Europe/Berlin')
cn = timezone('Asia/Shanghai')

beijing = _timezone(datetime.timedelta(hours=8))

ts = datetime.datetime.now().timestamp()
# 0001 <= year <= 9999
# 1 <= month <= 12
# 1 <= day <= 给定年月对应的天数
# 0 <= hour < 24
# 0 <= minute < 60
# 0 <= second < 60
# 0 <= microsecond <1000,000
# tzinfo 默认None tzinfo 子类的实例
# fold in [0, 1] 默认0 文档无描述
_datetime = datetime.datetime(year=2023, month=2, day=11, hour=0, minute=0, second=0, microsecond=0, tzinfo=cn)

_date = datetime.date(year=2023, month=2, day=11)
# _date.year, _date.month, _date.day

_time = datetime.time(hour=0, minute=0, second=0, microsecond=0, tzinfo=utc)
# _time.hour, _time.minute, _time.second, _time.microsecond, _time.tzinfo, _time.fold

_tzinfo = datetime.tzinfo()

# 999999999 days -999999999 九亿
# milliseconds 1000     毫秒
# microseconds 1000,000 微秒
_timedelta = datetime.timedelta(weeks=1, days=1, hours=1, minutes=1, seconds=1, milliseconds=1, microseconds=1)
# _timedelta.days _timedelta.microseconds _timedelta.seconds

count = 0
# for item in dir(_datetime):
# for item in dir(_date):
# for item in dir(_time):
# for item in dir(_tzinfo):
for item in dir(_timedelta):
    if not item.startswith("_") and not item.startswith("__"):
        # print("_datetime.{}()".format(item))
        # print("_date.{}()".format(item))
        # print("_time.{}()".format(item))
        # print("_tzinfo.{}()".format(item))
        # print("_timedelta.{}()".format(item))
        count += 1

# print(count)

"""
%Y 四位数的年份表示（000-9999）              %y 两位数的年份表示（00-99）
%m 月份（01-12）
%d 月内中的一天（0-31）
%H 24小时制小时数（0-23）                   %I 12小时制小时数（01-12）
%M 分钟数（00-59）
%S 秒（00-59）
%A 本地完整星期名称                         %a 本地简化星期名称
%B 本地完整的月份名称                       %b 本地简化的月份名称
%c 本地相应的日期表示和时间表示
%j 年内的一天（001-366）
%p 本地A.M.或P.M.的等价符
%U 一年中的星期数（00-53）星期天为星期的开始
%W 一年中的星期数（00-53）星期一为星期的开始
%w 星期（0-6），星期天为星期的开始
%x 本地相应的日期表示
%X 本地相应的时间表示
%Z 当前时区的名称
%% %号本身
"""

# date time datetime 转字符串格式化
def object_to_str():
    def _strftime():
        # 2023-02-11 00:00:01.000001
        _datetime.strftime("%Y-%m-%d %H:%M:%S.%f%z")
        # 00:00:00.000000
        _time.strftime("%H:%M:%S.%f%z")
        # 2023-02-11
        _date.strftime("%Y-%m-%d")

    def _isoformat():
        # timespec 时间规格
        #     'hours': '{:02d}',
        #     'minutes': '{:02d}:{:02d}',
        #     'seconds': '{:02d}:{:02d}:{:02d}',
        #     'milliseconds': '{:02d}:{:02d}:{:02d}.{:03d}',
        #     'microseconds': '{:02d}:{:02d}:{:02d}.{:06d}'

        # 2023-02-11T00:00:01.000001
        _datetime.isoformat(sep='T', timespec='auto')
        # 00:00:00
        _time.isoformat(timespec='auto')
        # 2023-02-11
        _date.isoformat()

# 字符串格式化转 date time datetime
def str_to_object():
    def _strptime():
        # 2023-02-11 00:00:01.000001+00:00
        datetime.datetime.strptime("2023-02-11T00:00:01.000001+00:00", "%Y-%m-%dT%H:%M:%S.%f%z")
        # 2023-02-11 00:00:00
        datetime.datetime.strptime("2023-02-11", "%Y-%m-%d")
        # 1900-01-01 00:00:01.000001+00:00
        datetime.datetime.strptime("00:00:01.000001+00:00", "%H:%M:%S.%f%z")

        import time
        # 时间元组
        # time.struct_time(tm_year=2023, tm_mon=12, tm_mday=2, tm_hour=0, tm_min=0, tm_sec=0, tm_wday=5, tm_yday=336, tm_isdst=-1)
        time.strptime('02/12/23 00:00:00.000000+00:00', '%d/%m/%y %H:%M:%S.%f%z')

    def _fromisoformat():
        # YYYY-MM-DDT[*HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]]
        datetime.datetime.fromisoformat("2023-02-12 00:00:00.000000+00:00")
        # 2023-02-12 00:00:00+00:00

        # YYYY-MM-DD
        datetime.date.fromisoformat("2023-02-12")
        # 2023-02-12

        # HH[:MM[:SS[.fff[fff]]]][+HH:MM[:SS[.ffffff]]]
        datetime.time.fromisoformat("00:00:00.000000+00:00")
        # 00:00:00+00:00

# 对象所能表示的最大日期
# 9999-12-31 23:59:59.999999
datetime.datetime.max
# 9999-12-31
datetime.date.max
# 23:59:59.999999
datetime.time.max
# 999999999 days, 23:59:59.999999
datetime.timedelta.max

# 对象所能表示的最小日期
# 0001-01-01 00:00:00
datetime.datetime.min
# 0001-01-01
datetime.date.min
# 00:00:00
datetime.time.min
# -999999999 days, 0:00:00
datetime.timedelta.min

# 表示日期的最小单位
# 0:00:00.000001
_datetime.resolution
# 1 day, 0:00:00
_date.resolution
# 0:00:00.000001
_time.resolution
# 0:00:00.000001
_timedelta.resolution

# 作用 返回包含日期和时间的字符串
# 参数 此功能不接受任何参数
# 返回 str类型 Sat Feb 11 00:00:00 2023
_datetime.ctime()
_date.ctime()

"""
0	tm_year	（例如，1993）
1	tm_mon	range [1, 12]
2	tm_mday	range [1, 31]
3	tm_hour	range [0, 23]
4	tm_min	range [0, 59]
5	tm_sec	range [0, 61]
6	tm_wday	range [0, 6] ，周一为 0
7	tm_yday	range [1, 366]
8	tm_isdst	0, 1 或 -1；
tm_isdst 可以在夏令时生效时设置为1，而在夏令时不生效时设置为0
值-1表示这是未知的，并且通常会导致填写正确的状态
"""
# 作用 返回 [UTC]时间元组
# 参数 此功能不接受任何参数
# 返回 time.struct_time类型 time.struct_time(tm_year=2023, tm_mon=2, tm_mday=11, tm_hour=0, tm_min=0, tm_sec=1, tm_wday=5, tm_yday=42, tm_isdst=0)
_datetime.utctimetuple()
_datetime.timetuple()
_date.timetuple()

"""
weekday    isoweekday
0	       1            Monday
1	       2            Tuesday
2	       3            Wednesday
3	       4            Thursday
4	       5            Friday
5	       6            Saturday
6	       7            Sunday
"""
# 作用 根据给定的 DateTime 获取周数
# 参数 此功能不接受任何参数
# 返回 int [0123456]
_datetime.weekday()
_date.weekday()
# 返回 int [1234567]
_datetime.isoweekday()
_date.isoweekday()

# 作用 获取当前设备今天日期
# 参数 此功能不接受任何参数
# 返回 datetime.datetime类型 2023-02-13 14:58:57.009273
datetime.datetime.today()
datetime.date.today()

# 作用 一种日历表示方法，类似于我国的农历，西方国家使用比较多，此处不详细展开讨论
# 参数
# 返回
# _datetime.fromordinal()
# _date.fromordinal()

# 作用 获取本地时间
# 参数 时间戳 datetime.datetime.now().timestamp()
# 返回 datetime.datetime类型 2023-02-13 15:04:13.533700 utc -8h
datetime.datetime.utcfromtimestamp(ts)
datetime.datetime.fromtimestamp(ts)
datetime.date.fromtimestamp(ts)

# 作用 返回格式如(year，month，day)的元组
# 参数
# 返回 tuple (2023, 6, 6) 不包含时间
_datetime.isocalendar()
_date.isocalendar()

# 作用 返回公元公历开始到现在的天数公元1年1月1日为1
# 参数 此功能不接受任何参数
# 返回 int 738563
_datetime.toordinal()
_date.toordinal()

# 作用 tzinfo=None 返回 None
# 参数 此功能不接受任何参数
# 返回 None | datetime.timedelta类型 0:00:00
_datetime.dst()
_time.dst()
# _tzinfo.dst(_datetime) 子类未实现 dst

# 作用 以字符串形式返回传递的 DateTime 对象的时区名称
# 参数 此功能不接受任何参数
# 返回 字符串 LMT UTC
_datetime.tzname()
_time.tzname()
# _tzinfo.tzname(_datetime) 子类未实现 tzname

# 作用 返回与给定实例中指定的tzinfo的 UTC偏移量对应的timedelta实例
# 参数 此功能不接受任何参数
# 返回 datetime.timedelta类型 偏移量
_datetime.utcoffset()
_time.utcoffset()
# _tzinfo.utcoffset(_datetime) 子类未实现 utcoffset

# datetime.datetime：表示日期时间的类
# 2023-02-13 08:41:25.698475
_datetime.utcnow()
# 2023-02-13 16:41:37.691550
_datetime.now()
# 2023-02-12
_datetime.date()
# 00:00:01.000001
_datetime.time()

# 作用 修改日期时间为对应时区
# 参数 timezone
# 返回 默认无参8h时区 2023-02-11 23:54:01.000001+08:00
_datetime.astimezone()

# 作用 把指定的date和time对象整合为datetime对象
# 参数 _date, _time
# 返回 datetime.timedelta类型
_datetime.combine(_date, _time)

# 作用 返回时间戳
# 参数 此功能不接受任何参数
# 返回 float类型
_datetime.timestamp()

# 作用 返回日期时间相同的时间时区部分
# 参数 此功能不接受任何参数
# 返回 datetime.time类型
_datetime.timetz()

# datetime.date：表示日期的类

# datetime.time：表示时间的类

# datetime.tzinfo：时区的相关信息

# 作用 此函数使用UTC占用对象的日期和时间，并返回等效的本地时间。
# 它主要用于调整日期和时间
# _tzinfo.fromutc()

# datetime.timedelta：表示时间间隔，即两个时间点的间隔
# 在日期上做天days，小时hour，分钟，秒，毫秒，微妙的时间计算

# 使用seconds时，如果时间差为负数，会变成86399+(时间差)
# 导致计算错误。原因：seconds只计算时间差，没包含日期，
# 一天的秒数为24*60*60=86400，seconds范围为[0, 86399]
# 作用 返回日期时间相差的秒数
# 参数
# 返回 float类型
_timedelta.total_seconds()

# 作用 返回日期时间相差的秒数
# 参数
# 返回 float类型
(_datetime - _datetime).total_seconds()

# 常用
# date time datetime 替换

# year, month, day, hour, minute, second, microsecond, tzinfo, fold
_datetime.replace()
# year, month, day
_date.replace()
# hour, minute, second, microsecond, tzinfo, fold
_time.replace()

_datetime + datetime.timedelta(days=1)
_date + datetime.timedelta(days=1)

# 显示当前日期是本周第几天
dic = {'7': 0, '6': 6, '5': 5, '4': 4, '3': 3, '2': 2, '1': 1}
day_num = _datetime.isoweekday()
day_num = dic[str(day_num)]

# 获取上周周日
weekday_t = (_datetime - datetime.timedelta(days=day_num))
# 获取本周周六周日
weekday_w = (_datetime - datetime.timedelta(days=day_num - 7))
saturday_w = (_datetime - datetime.timedelta(days=day_num - 6))

# 计算两个日期相差的天数、秒数
(_datetime-_datetime).days
(_datetime-_datetime).seconds
(_datetime-_datetime).total_seconds


import json
import random

from fluiddb.common import error, util
from fluiddb.common.defaults import contentTypeForPrimitiveJSON

def _sendBody(request, body, contentType):
    request.setHeader('content-type', contentType)
    request.setHeader('content-length', str(len(body)))
    request.write(body)
    request.finish()

def getBooleanArg(request, argName, default):
    'Get a Boolean argument out of HTTP request arguments.'
    values = request.args.get(argName)
    if values is None:
        return default
    else:
        n = len(values)
        if n == 0:
            # This should never happen. If a request looks like
            # GET /blah?argument
            # where argument is not give a value (e.g. argument=True),
            # then 'argument' will not be in request.args so the
            # request.args.get above will have returned None.
            raise error.InternalError(
                '%s request on %s arg get for %r returned zero length.' %
                (request.method, request.uri, argName))
        elif n == 1:
            return util.strToBool(values[0], default)
        else:
            raise error.MultipleArgumentValues(argName)

def buildHeader(name):
    return "X-FluidDB-%s" % name

def requestId():
    return ''.join([chr(ord('a') + random.randrange(0, 26))
                    for _ in range(16)])

def _serializePrimitiveToJSON(value):
    if type(value) is set:
        value = list(value)
    return json.dumps(value)

primitiveTypeSerializer = {
    contentTypeForPrimitiveJSON: _serializePrimitiveToJSON,
}


from webthing import (SingleThing, Property, Thing, Value, WebThingServer)
import logging
import tornado.ioloop
from datetime import datetime, timedelta
from smartmeter_webthing.meter import Meter

class SmartMeterThing(Thing):

    # regarding capabilities refer https://iot.mozilla.org/schemas
    # there is also another schema registry http://iotschema.org/docs/full.html not used by webthing
    def __init__(self, description: str, meter: Meter):
        Thing.__init__(
            self,
            'urn:dev:ops:SmartMeter-1',
            'SmartMeter',
            ['MultiLevelSensor'],
            description
        )

        self.meter = meter

        self.current_power = Value(meter.current_power)
        self.add_property(
            Property(self,
                     'current_power',
                     self.current_power,
                     metadata={
                         'title': 'current power',
                         "type": "number",
                         'description': 'The current power [Watt]',
                         'readOnly': True,
                     }))

        self.average_produced_power = Value(0)
        self.add_property(
            Property(self,
                     'average_produced_power',
                     self.average_produced_power,
                     metadata={
                         'title': 'average produced power (daily)',
                         "type": "number",
                         'description': 'The daily average power (produced only) [Watt]',
                         'readOnly': True,
                     }))

        self.average_consumed_power = Value(0)
        self.add_property(
            Property(self,
                     'average_consumed_power',
                     self.average_consumed_power,
                     metadata={
                         'title': 'average consumed power (daily)',
                         "type": "number",
                         'description': 'The daily average power (consumed only) [Watt]',
                         'readOnly': True,
                     }))

        self.produced_power_total = Value(meter.produced_power_total)
        self.add_property(
            Property(self,
                     'produced_power_total',
                     self.produced_power_total,
                     metadata={
                         'title': 'produced power total',
                         "type": "number",
                         'description': 'The total produced power [Watt]',
                         'readOnly': True,
                     }))

        self.consumed_power_total = Value(meter.consumed_power_total)
        self.add_property(
            Property(self,
                     'consumed_power_total',
                     self.consumed_power_total,
                     metadata={
                         'title': 'consumed power total',
                         "type": "number",
                         'description': 'The total consumed power [Watt]',
                         'readOnly': True,
                     }))

        self.measurement_time = Value("")
        self.add_property(
            Property(self,
                     'measurement_time',
                     self.measurement_time,
                     metadata={
                         'title': 'measurement time',
                         "type": "str",
                         'description': 'The time values measured [iso datetime]',
                         'readOnly': True,
                     }))

        self.last_error_time = Value("")
        self.add_property(
            Property(self,
                     'last_error_time',
                     self.last_error_time,
                     metadata={
                         'title': 'last error time',
                         "type": "str",
                         'description': 'The time last error occurred [iso datetime]',
                         'readOnly': True,
                     }))

        self.sampling_rate = Value(0)
        self.add_property(
            Property(self,
                     'sampling_rate',
                     self.sampling_rate,
                     metadata={
                         'title': 'sampling rate',
                         "type": "number",
                         'description': 'The sampling rate per minute',
                         'readOnly': True,
                     }))

        self.ioloop = tornado.ioloop.IOLoop.current()
        self.meter.add_listener(self.on_value_changed)

    def on_value_changed(self):
        self.ioloop.add_callback(self.__on_value_changed)

    def __on_value_changed(self):
        self.consumed_power_total.notify_of_external_update(self.meter.consumed_power_total)
        self.produced_power_total.notify_of_external_update(self.meter.produced_power_total)
        self.measurement_time.notify_of_external_update(self.meter.measurement_time.strftime("%Y-%m-%dT%H:%M:%S"))
        self.last_error_time.notify_of_external_update(self.meter.last_error_time.strftime("%Y-%m-%dT%H:%M:%S"))
        self.sampling_rate.notify_of_external_update(int(self.meter.sampling_rate))
        self.average_produced_power.notify_of_external_update(self.meter.average_produced_power)
        self.average_consumed_power.notify_of_external_update(self.meter.average_consumed_power)
        self.current_power.notify_of_external_update(self.meter.current_power)

def run_server(description: str, port: int, sport: str):
    meter = Meter(sport)
    server = WebThingServer(SingleThing(SmartMeterThing(description, meter)), port=port, disable_host_validation=True)
    logging.info('running webthing server http://localhost:' + str(port))
    try:
        server.start()
    except KeyboardInterrupt:
        logging.info('stopping webthing server')
        server.stop()
        logging.info('done')


"""
Identifies new and deleted subscribers by comparing previous subscriber list with latest subscriber list
new_links_filename is a list of inbound urls
old_links_filename is list of urls that have been previously checked
Add the required filename for old nad new links
add name for merged output file that contains merged info from old to new links file
"""
import csv
import os

new_links_filename = 'referring_page.csv'
old_links_filename = "old_links.csv"
new_links_file = os.path.join('data', new_links_filename)
old_links_file = os.path.join('data', old_links_filename)
print("filenames are: ", new_links_file, old_links_file)
updated_links_filename = 'updated_referral_links.csv'
old_urls_only = []
new_urls_only = []

def parse(raw_file, delimiter):
    """
    :param raw_file: probably csv file
    :param delimiter: specify delimiter #TODO add default arg : ','
    :return: parsed data list of dictionaries
    Parses a raw CSV file to a JSON-line object.
    18 October 2018 had ro remove encoding='utf-8' for one of the files I processed. Added it back
    """
    # open csv file
    with open(raw_file, newline='', encoding='utf-8') as opened_file:
        # read csv file
        csv_data = csv.reader(opened_file, delimiter=delimiter)  # first delimiter is csv.reader variable name
        # csv_data object is now an iterator meaning we can get each element one at a time
        # build data structure to return parsed data
        parsed_data = []  # this list will store every row of data
        fields = csv_data.__next__()
        # this will be the column headers; we can use .next() because csv_data is an iterator
        print(fields)
        fields[0] = 'Host'
        print(fields)
        for row in csv_data:
            if row[0] == "":  # there is no text field so no data to process
                pass
            else:
                parsed_data.append(dict(zip(fields, row)))
                # Creates a new dict item for each row with col header as key and stores in a list
            #  racer_count += 1  # This is number of racers not races
        # close csv file
        opened_file.close()
        return parsed_data

# create list containing only urls
old_links_list = parse(old_links_file, ',')
#  print('Old links list:', old_links_list)
for link in old_links_list:
    old_urls_only.append(link['Host'].lower())
#  print('previous urls are:', old_urls_only)

# create list containing new urls
new_links_list = parse(new_links_file, ',')
for link in new_links_list:
    new_urls_only.append(link['Host'].lower())

def create_new_links(old_list, new_list):
    # Creates new list of dictionaries with found field with full details
    new_links_details = []
    new_links_details.append('Host' + ',' + 'Last crawled' + ',' + 'Found?' + ',' + 'old_link' + ','
                             + 'disavow' + ',' + 'comment' + ',' + 'classification')

    for url in new_list:
        found = 'Not Found'
        old_link = ""
        disavow = ""
        comment = ""
        classification = ""
        if ',' in url['Host']:
            url['Host'] = url['Host'].replace(',', '_sgxyz_')
        for link in old_list:
            if link['Host'] in url['Host']:
                found = "Found"
                old_link = link['Host']
                disavow = link['Disavow']
                comment = link['Comment']
                classification = link['Classification']
        new_links_details.append(url['Host'] + ',' + found + ',' + old_link + ','
                                  + disavow + ',' + comment + ',' + classification)
    return new_links_details

print('Current list has:', len(new_urls_only), 'urls')
print('The previous list had: ', len(old_urls_only), 'links')
for e in range(1, 10):
    print('previous links sample:', e, old_urls_only[e])
    print('new links sample:', e, new_urls_only[e])

def create_file(output_file, urls):
    updated_links_file = open(output_file, "w", newline='', encoding='utf-8')
    # newline = '' to prevent blank lines being inserted
    wr = csv.writer(updated_links_file, quoting=csv.QUOTE_ALL)
    for url in urls:
        wr.writerow([url])
    updated_links_file.close()

updated_links = create_new_links(old_links_list, new_links_list)
print(updated_links)
create_file(updated_links_filename, updated_links)


# 10 a + 5 b +  c = _yp
#    a +   b +  c = _n
# ->
#  9 a + 4 b      = _yp - _n
# ->
# a = (_yp - _n - 4b)/9
def calc(n, yp):
  yp_minus_n = yp - n

  for a in range(n+1):
    for b in range(n-a+1):
      if 9 * a + 4 * b == yp_minus_n:
        c = n - a - b
        if c >= 0:
          print('{} {} {}'.format(a, b, c))
          return
  # max_a = int(yp_minus_n / 9)
  # for a in range(min(n, max_a)+1):
  #   diff = int(yp_minus_n - 9 * a)
  #   diff_o = int(diff / 4)
  #   if diff >= 0 and diff % 4 == 0 and diff_o <= n - a:
  #     xa = a
  #     xb = diff_o
  #     xc = n - xa - xb
  #     print(xa, xb, xc)
  #     return

  print(-1, -1, -1)

if __name__ == "__main__":
  _ny = list(map(int, input().split()))
  # assert(len(_ny) == 2)
  _n = _ny[0]
  _y = _ny[1]
  # assert(_y >= 1000 and _y <= 20000000 and _y % 1000 == 0)
  _yp = int(_y / 1000)
  calc(_n, _yp)


import unittest
import twodlearn as tdl
import tensorflow as tf
import tensorflow.keras.layers as tf_layers
import functools
import operator

@tdl.core.create_init_docstring
class TransposeLayer(tdl.core.Layer):
    @tdl.core.SubmodelInit
    def conv(self, units, kernels, strides, padding='same'):
        return tf_layers.Conv2DTranspose(
                units, kernels, strides=strides,
                padding=padding,
                use_bias=False)

    @tdl.core.Submodel
    def activation(self, value):
        return value

    def call(self, inputs):
        output = self.conv(inputs)
        if self.activation is not None:
            output = self.activation(output)
        return output

class StackedTest(unittest.TestCase):
    def test_get_trainable1(self):
        init_shape = (4, 4, 128)
        model = tdl.stacked.StackedLayers()
        model.add(tdl.dense.LinearLayer(
            units=functools.reduce(operator.mul, init_shape, 1)))
        model.add(tf_layers.Reshape(init_shape))
        model.add(TransposeLayer(
            conv={'units': 64, 'kernels': (5, 5), 'strides': (2, 2)}))
        model.add(TransposeLayer(
            conv={'units': 32, 'kernels': (5, 5), 'strides': (2, 2)}))

        input = tf.random.normal([32, 100])
        output = model(input)
        assert len(tdl.core.get_trainable(model)) == 3

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


from __future__ import annotations

from asyncio import (
    AbstractEventLoop,
    AbstractEventLoopPolicy,
    CancelledError,
    Future,
    InvalidStateError,
    Queue as AQueue,
    ensure_future,
    gather,
    get_event_loop,
    new_event_loop,
)
from dataclasses import dataclass
from functools import partial, wraps
from inspect import isawaitable, iscoroutinefunction
from queue import Queue
import sys
import threading
from typing import (
    Any,
    Awaitable,
    Callable,
    Generator,
    Generic,
    Iterable,
    List,
    Optional,
    Sequence,
    Tuple,
    TypeVar,
    Union,
    cast,
    no_type_check,
)
import warnings

from .. import LOG
from ..prim.datetime import TimeDeltaLike, to_timedelta

T = TypeVar("T")
T_co = TypeVar("T_co", covariant=True)
U = TypeVar("U")

_PENDING = "PENDING"
_CANCELLED = "CANCELLED"
_FINISHED = "FINISHED"

def non_reentrant(async_fn):
    if not iscoroutinefunction(async_fn):
        raise ValueError("expected a coroutine function")

    calls = []

    @wraps(async_fn)
    async def _wrap(*args, **kwargs):
        if not calls:
            calls.append(None)
            try:
                return await async_fn(*args, **kwargs)
            finally:
                calls.pop()
        else:
            raise InvalidStateError("calls to %r cannot be re-entrant", async_fn)

    return _wrap

def isolated_async(async_fn):
    """
    Wrap an async function in a thread with its own event loop.

    This function runs by itself in an event loop created specifically for this object on its own thread.

    This function can be used as a decorator to convert an ``async def`` method to a simple method that blocks while
    executing the method on a background thread.

    :param async_fn:
        The ``async`` function to invoke.
    :return:
        A function that, when invoked, passes its parameters to the underlying function on a background thread in an
        isolated event loop.
    """
    queue = Queue()

    @wraps(async_fn)
    def invoke(*args, **kwargs):
        """
        Invoke the wrapped ``async`` method on a background thread, passing in the specified
        arguments, and returning the value that the wrapped method returns, or raises an Exception
        if the ``async`` function throws.

        :param args: The positional arguments to pass.
        :param kwargs: The keyword arguments to pass.
        :return: The value from the ``async`` function.
        """
        thread = threading.Thread(target=partial(_main, args, kwargs))
        thread.start()
        thread.join()

        result, typ, value, traceback = queue.get()
        if typ is not None:
            # if we have exception information, then an exception was thrown; rethrow it
            raise typ(value).with_traceback(traceback)

        else:
            # we don't have an exception, so assume the result is what we need to pass back
            return result

    def _main(args, kwargs):
        try:
            loop = new_event_loop()
            result = loop.run_until_complete(async_fn(*args, **kwargs))
            loop.close()

            queue.put_nowait((result, None, None, None))
        except:
            typ, value, traceback = sys.exc_info()
            queue.put_nowait((None, typ, value, traceback))

    return invoke

def await_then(awaitable: Awaitable[T_co], func: Callable[[T_co], U]) -> Awaitable[U]:
    """
    Call a function on the result of an Awaitable, and then return an Awaitable that is resolved
    with that result.

    If the Awaitable is already "done", then the function is invoked immediately with the result
    of that Awaitable and an immediately-completed Future is returned with the result of that
    callback.

    If either the Awaitable or the function throws an exception, that is returned as a failed
    Future. If the Awaitable is cancelled, the returned Future is also cancelled.

    :param awaitable:
    :param func:
    :return:
    """
    try:
        fut = ensure_future(awaitable)
    except TypeError:
        raise TypeError(f"expected a valid awaitable (got {awaitable} instead)")
    if fut.done():
        if fut.cancelled() or fut.exception() is not None:
            return fut  # type: ignore
        else:
            try:
                return completed(func(fut.result()))
            except Exception as ex:
                fut = get_event_loop().create_future()  # type: ignore
                fut.set_exception(ex)
                return fut  # type: ignore
    else:
        g = get_event_loop().create_future()

        def _propagate(_):
            if fut.cancelled():
                g.cancel()
            elif fut.exception() is not None:
                g.set_exception(fut.exception())
            else:
                try:
                    g.set_result(func(fut.result()))
                except Exception as ex2:
                    g.set_exception(ex2)

        fut.add_done_callback(_propagate)
        return g  # type: ignore

@dataclass
class FailedInvocation:
    """Marker used within execute_in_loop to propagate exceptions thrown
    by coro_fn through the result queue in a way that can be easily detected
    by the queue's reader.
    """

    ex: Exception

def execute_in_loop(
    loop: AbstractEventLoop,
    coro_fn: Callable[[], Union[Awaitable[T_co], T_co]],
    timeout: Optional[TimeDeltaLike] = 30.0,
) -> T_co:
    """
    Run a coroutine in a target loop. Exceptions thrown by the coroutine are
    propagated to the caller. Must NOT be called from a coroutine on the same
    loop!

    :param loop:
    :param coro_fn:
    :param timeout: Seconds to wait for the termination of the coroutine.
    :return: The return value from the coroutine.
    """
    from functools import wraps
    from queue import Queue

    q = Queue()  # type: ignore

    def coro_fn_complete(fut):
        LOG.debug("coro_fn_complete: %s", fut)
        if fut.exception() is None:
            q.put_nowait(fut.result())
        else:
            q.put_nowait(FailedInvocation(fut.exception()))

    @wraps(coro_fn)
    def run():
        if iscoroutinefunction(coro_fn):
            fut = ensure_future(coro_fn())
            fut.add_done_callback(lambda _: coro_fn_complete(fut))

        elif isawaitable(coro_fn):
            fut = ensure_future(coro_fn)
            fut.add_done_callback(lambda _: coro_fn_complete(fut))

        elif callable(coro_fn):
            result = coro_fn()
            if isawaitable(result):
                fut = ensure_future(result)
                fut.add_done_callback(lambda _: coro_fn_complete(fut))
            else:
                q.put_nowait(result)
        else:
            raise ValueError("Received an unknown kind of callback")

    loop.call_soon_threadsafe(run)

    timeout_in_seconds = to_timedelta(timeout).total_seconds()
    result = q.get(timeout=timeout_in_seconds)

    if isinstance(result, FailedInvocation):
        raise result.ex

    return result

def completed(value, loop=None) -> Future:
    if loop is None:
        loop = get_event_loop()
    fut = loop.create_future()
    fut.set_result(value)
    return fut

def failed(exception: BaseException, loop=None) -> Future:
    if loop is None:
        loop = get_event_loop()
    fut = loop.create_future()
    fut.set_exception(exception)
    return fut

def propagate(from_: Future, to: Future) -> None:
    """
    Copy the value that ``from_`` is completed with to ``to``, whenever ``from_`` is completed.
    """
    if from_.done():
        copy_result(from_, to)
    else:
        from_.add_done_callback(lambda _: copy_result(from_, to))

def copy_result(from_: Future, to: Future) -> None:
    if not from_.done():
        raise ValueError("from_ must be a completed Future")
    if to.done():
        raise ValueError("to must NOT be a completed Future")

    if from_.cancelled():
        to.cancel()
    else:
        exception = from_.exception()
        if exception is not None:
            to.set_exception(exception)
        else:
            result = from_.result()
            to.set_result(result)

def to_coroutine(callback: Callable[..., Any]) -> Callable[..., Future]:
    """
    Wrap a function or a coroutine, always producing a coroutine.

    In other words, for a function like

    ```
    def double(x):
        return x + x
    ```

    the result of ``to_coroutine(double)`` would be a function that is equivalent to:

    ```
    async def double(x):
        return x + x
    ```

    For functions that are already coroutines, their behavior is unaffected by the wrapper generated
    from this function.

    :param callback:
        The callback to convert to a coroutine.
    :return:
        A coroutine that calls the specified function.
    """
    if not callable(callback):
        raise ValueError("callback must be callable")

    @wraps(callback)
    def invoke_sync(*args, **kwargs) -> Future:
        loop = get_event_loop()

        try:
            result = callback(*args, **kwargs)
            if isinstance(result, Future):
                return result
            else:
                future = loop.create_future()
                future.set_result(result)
                return future
        except Exception as ex:
            future = loop.create_future()
            future.set_exception(ex)
            return future

    if iscoroutinefunction(callback):
        return lambda *args, **kwargs: ensure_future(callback(*args, **kwargs))
    else:
        return invoke_sync

class LongRunningAwaitable:
    """
    An :class:`Awaitable` that "finishes" once all of the futures that have been added to it are
    finished.
    """

    def __init__(self, awaitables: Optional[Iterable[Awaitable[Any]]] = None):
        self._fut = get_event_loop().create_future()
        self._coros = []  # type: List[Awaitable[Any]]
        if awaitables is not None:
            self.extend(awaitables)

    def append(self, *awaitables: Awaitable[Any]) -> None:
        self.extend(awaitables)

    def extend(self, awaitables: Iterable[Awaitable[Any]]):
        for a in awaitables:
            f = ensure_future(a)
            f.add_done_callback(self._future_finished)
            self._coros.append(f)

    def _future_finished(self, fut):
        self._coros.remove(fut)
        if not self._coros:
            self._fut.set_result(None)

    def __await__(self):
        return self._fut.__await__()

class ServiceQueue(Generic[T]):
    # noinspection PyDeprecation
    def __init__(self) -> None:
        warnings.warn(
            "ServiceQueue is deprecated; there is no planned replacement",
            DeprecationWarning,
            stacklevel=2,
        )
        self._q = []  # type: Union[List[Tuple[T, Future]], AQueue[Tuple[T, Future]]]
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", DeprecationWarning)
            self._service_fut = safe_create_future()
        self._prev_fut = None

    # noinspection PyDeprecation
    def put(self, value: T) -> Awaitable[None]:
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", DeprecationWarning)
            fut = safe_create_future()
        if isinstance(self._q, list):
            self._q.append((value, fut))
        else:
            self._q.put_nowait((value, fut))
        return fut

    def start(self) -> None:
        """
        Allow open asynchronous iterators to begin reading data from the queue. Calling this method
        more than once has no effect.
        """
        if not self._service_fut.done():
            existing_items = cast(list, self._q)  # type: List[Tuple[T, Future]]
            self._q = AQueue()
            for item in existing_items:
                self._q.put_nowait(item)
            self._service_fut.set_result(None)

    def stop(self):
        if not self._service_fut.done():
            raise RuntimeError("Cannot stop an unstarted ServiceQueue")

        loop = get_event_loop()
        fut = loop.create_future()
        self._q.put_nowait((None, fut))
        return fut

    async def next(self) -> Optional[T_co]:
        if not self._service_fut.done():
            await self._service_fut

        if self._prev_fut is not None:
            self._prev_fut.set_result(None)
            self._prev_fut = None

        q = cast(AQueue, self._q)  # type: AQueue[Tuple[T_co, Future]]
        value, fut = await q.get()
        if value is None:
            fut.set_result(None)
            return None
        else:
            self._prev_fut = fut  # type: ignore
            return value

    def __aiter__(self):
        return self

    async def __anext__(self):
        value = await self.next()
        if value is not None:
            return value
        else:
            raise StopAsyncIteration

    def __bool__(self):
        return len(self) > 0

    def __len__(self):
        if isinstance(self._q, list):
            return len(self._q)
        else:
            return self._q.qsize()

    def __repr__(self):
        return repr(self._q)

class ContextFreeFuture(Awaitable[T_co]):
    """
    An awaitable whose loop is defined at the time of either a :meth:`set_result` call or an
    `await`. These futures are more expensive than normal asyncio futures because they are
    thread-safe.
    """

    _result: Optional[T_co] = None
    _exception: Optional[Exception] = None
    _log_traceback = False
    _asyncio_future_blocking = False

    def __init__(self, *, loop: Optional[AbstractEventLoop] = None):
        """
        Initialize the future.

        The optional ``loop`` argument allows explicitly setting the event loop object used by the
        future. Unlike :class:`Future`, If it is not provided, the future does NOT have a loop set,
        and it is assigned at the time that :class:`set_result` or an `await` expression is called,
        or when :class:`set_loop` is explicitly called.

        You may want to provide a loop ahead of time if you know it, and you're really only
        utilizing this class for its thread-safe nature.

        :param loop: An optional loop to assign to the :class:`ContextFreeFuture`.
        """
        if loop is not None and not isinstance(loop, AbstractEventLoop):
            raise ValueError("The provided loop must be a valid event loop")

        from threading import RLock

        self._lock = RLock()
        self._callbacks = []  # type: List[Callable[[ContextFreeFuture[T_co]], None]]
        self._state = _PENDING
        self.__loop = loop  # type: Optional[AbstractEventLoop]
        self._source_traceback = None

    @property
    def _loop(self):
        """
        Return the current loop.

        Because many functions in the asyncio library directly attempt to access the loop of a
        Future for validation purposes, it is necessary for this property to behave in strange ways.
        If this property is accessed in a context where this is a currently running loop, this
        Future will adopt the current running loop as its own, but ONLY if a loop has not yet been
        set. This will usually do the right thing, but in some cases it may be necessary for callers
        to invoke :meth:`set_loop` directly.
        """
        if self.__loop is None:
            with warnings.catch_warnings():
                warnings.simplefilter("ignore", DeprecationWarning)
                # noinspection PyDeprecation
                self.__loop = get_running_loop()
        return self.__loop

    def set_loop(self, loop: AbstractEventLoop) -> None:
        """
        Set the loop affinity for this future.

        It is an error to call this function more than once with different values for the loop.

        :param loop:
        """
        with self._lock:
            if self.__loop is None:
                self.__loop = loop
            elif self.__loop is not loop:
                raise InvalidStateError("This future is already associated with a specific loop.")

    def cancel(self) -> bool:
        """
        Cancel this future.
        :return:
        """
        with self._lock:
            self._log_traceback = False
            if self._state != _PENDING:
                return False

            self._state = _CANCELLED
            self._schedule_callbacks()
            return True

    def set_result(self, result):
        """Mark the future done and set its result.

        If the future is already done when this method is called, raises
        InvalidStateError.
        """
        with self._lock:
            if self._state != _PENDING:
                raise InvalidStateError("{}: {!r}".format(self._state, self))
            self._result = result
            self._state = _FINISHED
            self._schedule_callbacks()

    def set_exception(self, exception):
        """Mark the future done and set an exception.

        If the future is already done when this method is called, raises
        InvalidStateError.
        """
        with self._lock:
            if self._state != _PENDING:
                raise InvalidStateError("{}: {!r}".format(self._state, self))
            if isinstance(exception, type):
                exception = exception()
            if type(exception) is StopIteration:
                raise TypeError(
                    "StopIteration interacts badly with generators "
                    "and cannot be raised into a Future"
                )
            self._exception = exception
            self._state = _FINISHED
            self._schedule_callbacks()
            self._log_traceback = True

    def add_done_callback(
        self, fn: "Callable[[ContextFreeFuture[T_co]], None]", context=None
    ) -> None:
        if context is not None:
            # This used to be a warning, but in newer versions of Python a context
            # is sometimes supplied and nothing seems to particularly go wrong by
            # simply doing nothing with this information.
            pass
        with self._lock:
            if self._loop is not None and self._state != _PENDING:
                self._loop.call_soon_threadsafe(fn, self)
            else:
                self._callbacks.append(fn)

    def _schedule_callbacks(self):
        with self._lock:
            if self.__loop is None:
                self.__loop = get_event_loop()

            # clear out the callbacks list and prevent further additions
            local_callbacks = self._callbacks
            self._callbacks = ()

            for fn in local_callbacks:
                self.__loop.call_soon_threadsafe(fn, self)

    def cancelled(self):
        """Return True if the future was cancelled."""
        with self._lock:
            return self._state == _CANCELLED

    # Don't implement running(); see http://bugs.python.org/issue18699

    def done(self):
        """Return True if the future is done.

        Done means either that a result / exception are available, or that the
        future was cancelled.
        """
        with self._lock:
            return self._state != _PENDING

    def result(self):
        """Return the result this future represents.

        If the future has been cancelled, raises CancelledError.  If the
        future's result isn't yet available, raises InvalidStateError.  If
        the future is done and has an exception set, this exception is raised.
        """
        with self._lock:
            if self._state == _CANCELLED:
                raise CancelledError
            if self._state != _FINISHED:
                raise InvalidStateError("Result is not ready.")
            self._log_traceback = False
            if self._exception is not None:
                raise self._exception
            return self._result

    def exception(self):
        """Return the exception that was set on this future.

        The exception (or None if no exception was set) is returned only if
        the future is done.  If the future has been cancelled, raises
        CancelledError.  If the future isn't done yet, raises
        InvalidStateError.
        """
        with self._lock:
            if self._state == _CANCELLED:
                raise CancelledError
            if self._state != _FINISHED:
                raise InvalidStateError("Exception is not set.")
            self._log_traceback = False
            return self._exception

    def __await__(self) -> Generator[Any, None, T_co]:
        if not self.done():
            self._asyncio_future_blocking = True
            yield self  # This tells Task to wait for completion.
        assert self.done(), "yield from wasn't used with future"
        return self.result()  # May raise too.

class DeferredStartTask:
    """
    A :class:`Task`-like object that delays starting its coroutine until the :meth:`start` method is
    called.
    """

    _asyncio_future_blocking = False

    def __init__(self, cb: Callable[[], Future], start=False, name=None):
        if not callable(cb):
            raise ValueError("cb must be callable")

        if start:
            self._future = cb()
            self._callback = None
        else:
            self._future = get_event_loop().create_future()
            self._callback = cb

        # This is required to be compatible with the interface of a Future.
        self._loop = self._future._loop
        self._name = name or repr(cb)

    def start(self) -> None:
        """
        Actually invoke the underlying function (but only if it hasn't been invoked already).
        """
        cb = self._callback
        if cb is not None:
            self._callback = None
            propagate(from_=ensure_future(cb()), to=self._future)

    def started(self) -> bool:
        return self._callback is None

    def cancelled(self) -> bool:
        return self._future.cancelled()

    def cancel(self) -> bool:
        self._callback = None
        return self._future.cancel()

    def result(self) -> Any:
        return self._future.result()

    def done(self) -> bool:
        return self._future.done()

    def exception(self) -> Optional[BaseException]:
        return self._future.exception()

    def add_done_callback(self, callback: "Callable[[Future], Any]", context=None) -> None:
        if context is None:
            self._future.add_done_callback(callback)
        else:
            self._future.add_done_callback(callback, context=context)  # type: ignore

    def __await__(self):
        return self._future.__await__()

    def __repr__(self):
        state = self._future._state if self.started() else "NOT_STARTED"
        return f"DeferredStartTask({self._name!r}, state={state})"

@no_type_check
def get_running_loop() -> Optional[AbstractEventLoop]:
    warnings.warn(
        "get_running_loop() is deprecated, as support for Python 3.6 will be dropped in dazl 8. "
        "Use Python 3.7+'s asyncio.get_running_loop() instead.",
        DeprecationWarning,
    )
    try:
        from asyncio import get_running_loop

        try:
            return get_running_loop()
        except RuntimeError:
            return None
    except ImportError:
        # noinspection PyProtectedMember
        from asyncio import _get_running_loop

        return _get_running_loop()

# noinspection PyDeprecation
def safe_create_future():
    warnings.warn(
        "safe_create_future() is deprecated; there is no planned replacement.",
        DeprecationWarning,
        stacklevel=2,
    )
    with warnings.catch_warnings():
        warnings.simplefilter("ignore", DeprecationWarning)
        loop = get_running_loop()
    return loop.create_future() if loop is not None else ContextFreeFuture()

@no_type_check
def named_gather(name: str, *awaitables, return_exceptions=False):
    g = gather(*awaitables, return_exceptions=return_exceptions)
    g.__repr__ = staticmethod(lambda _: f"<Gather {name}>")
    return g

class Signal:
    """
    A simple guard that "wakes" up a coroutine from another coroutine.
    """

    # noinspection PyDeprecation
    def __init__(self):
        warnings.warn(
            "Signal is deprecated; there is no planned replacement",
            DeprecationWarning,
            stacklevel=2,
        )
        with warnings.catch_warnings():
            warnings.simplefilter("ignore", DeprecationWarning)
            self._fut = safe_create_future()

    def notify_all(self) -> None:
        """
        Schedule a notification to all coroutines that are `wait`ing.
        """
        if self._fut is not None:
            self._fut.set_result(None)
            self._fut = None

    # noinspection PyDeprecation
    def wait(self) -> Awaitable[None]:
        if self._fut is None:
            with warnings.catch_warnings():
                warnings.simplefilter("ignore", DeprecationWarning)
                self._fut = safe_create_future()
        return self._fut

class UnsettableEventLoopPolicy(AbstractEventLoopPolicy):
    def get_event_loop(self) -> AbstractEventLoop:
        raise Exception("Called get_event_loop")

    def set_event_loop(self, loop: Optional[AbstractEventLoop]) -> None:
        raise Exception("Called set_event_loop")

    def new_event_loop(self) -> AbstractEventLoop:
        raise Exception("Called new_event_loop")

    def get_child_watcher(self) -> Any:
        raise Exception("get_child_watcher")

    def set_child_watcher(self, watcher: Any) -> None:
        raise Exception("set_child_watcher")


#インポート処理
import matplotlib.pyplot as plt
import pandas
import datetime
#変数の初期化
l_warm = []
l_hot = []
l_too_hot = []
year = []
l_warm_high=[]
l_hot_high =[]
l_too_hot_high =[]
l_h_t_h = []
#csvデータを変数に格納
data = pandas.read_csv('C:\\Users\owner\Desktop\python_lesson\data_port_f\\weather\\1990-2018.csv',index_col='date', parse_dates=['date'])
#ループ（年）
for i in range(30):
    #ループ（日）用の開始位置と終了位置を設定、
    start = data.index.searchsorted(datetime.datetime(2018-i, 1, 1))
    end = data.index.searchsorted(datetime.datetime(2019-i, 1, 1))
    t = data[start:end].values
    #ループ（日）用の初期化
    warm_count = 0
    hot_count = 0
    too_hot_count = 0
    leap = 0
    #リストyearに処理する「年」を格納していく。
    year.append(2018-i)
    #うるう年の判断
    if (2018-i)%400 == 0:
        leap = 366
    elif (2018-i)%100 == 0:
        leap = 365
    elif (2018-i)%4 == 0:
        leap = 366
    else:
        leap = 365
    #ループ（日）
    for d in range(leap):
        tmp = 0
        hum = 0
        disc = 0
        #温度と湿度をそれぞれ変数に格納
        tmp = t[d][0]
        hum = t[d][3]
        #不快指数の計算
        disc = round((0.81*tmp)+(0.01*hum)*((0.99*tmp)-14.3)+46.3,2)
        #if disc >= 65 and disc <= 70:#不快指数が心地いいレベル
        if disc >= 75 and disc < 80:
            warm_count += 1
        elif disc >= 80 and disc < 85:
            hot_count += 1
        elif disc >= 85:
            too_hot_count += 1
    #それぞれの変数に格納（リスト）
    l_h_t_h.append(hot_count + too_hot_count) #不快指数上位の日数
    l_warm.append(warm_count) #75~79の日数
    l_hot.append(hot_count) #80~84の日数
    l_too_hot.append(too_hot_count) #85~の日数
    #テキストを表示する高さを決めるための変数
    l_warm_high.append(warm_count)  #75~79の高さ
    l_hot_high.append(warm_count + hot_count) #80~84の高さ
    l_too_hot_high.append(warm_count + hot_count + too_hot_count) #85~の高さ

#テキストの表示
for x, y, z in zip(year, l_warm_high,l_too_hot_high):
    plt.text(x, round(y/2,0), str(y), ha='center', va='bottom')
    plt.text(x,90,str(x)+"\ntotal\n"+str(z))
for x, y, z in zip(year,l_hot_high,l_hot ):
    if z != 0:
        plt.text(x, y-round(z/2,0), z , ha='center', va='bottom')
if too_hot_count == 0:
    for x, y ,z in zip(year, l_too_hot_high,l_too_hot):
        if z != 0:
            plt.text(x, y-round(z/2,0), z, ha='center', va='bottom')
plt.title("hotday 1989 - 2018")
#不快指数75以上の日を色分けして積み上げ棒グラフにする。
p1 = plt.bar(year,l_warm,color="orange")
p2 = plt.bar(year,l_hot,color="#FF5B70",bottom=l_warm)
p3 = plt.bar(year,l_too_hot,color="red",bottom=l_hot_high,align="center")
#表示する範囲を指定
plt.plot(1989, 100)
#グラフの表示
plt.show()
#不快指数80以上の日をまとめて棒グラフで表示する。
for x, y in zip(year,l_h_t_h):
    plt.text(x,39,str(x)+"\n"+str(y),ha='center', va='bottom')
p4 = plt.bar(year,l_h_t_h)
#グラフの表示
plt.show()


import vaex
import os
import pprint

# Define file paths
requests_csv = "requests.csv"
requests_hdf5 = requests_csv + '.hdf5'

domains_csv = "domains.csv"
domains_hdf5 = domains_csv + '.hdf5'

export_csv_folder = "domains2022_2023.csv"

# Load the requests HDF5 if it exists, if not, convert CSV to HDF5 for requests to make this fast
df_requests = vaex.open(requests_hdf5) if os.path.isfile(requests_hdf5) else vaex.from_csv(requests_csv, convert=True, chunk_size=5_000_000, progress=True)

print("Requests loaded with success")

# Process 'Date' column in requests
df_requests['Date'] = df_requests['Date'].str.replace('Z', '').astype('datetime64[ns]')
df_requests_filtered_by_date = df_requests[df_requests['Date'].dt.year >= 2022]

print("Requests date filtered with success")

# Load the domains HDF5 if it exists, if not, convert CSV to HDF5 for domains to make this fast
df_domains = vaex.open(domains_hdf5) if os.path.isfile(domains_hdf5) else vaex.from_csv(domains_csv, convert=True, chunk_size=5_000_000, progress=True)

print("Domains loaded with success")

# Join the two dataframes on 'Request ID' column
#result_domains_filtered_by_date = df_domains.join(df_requests_filtered_by_date[['Request ID', 'Date']], on='Request ID', how='left')
result_domains_filtered_by_date = df_domains.join(df_requests_filtered_by_date[['Request ID', 'Date']], on='Request ID', how='inner')

print("Domains filtered by date with success")

# Count and print the number of rows in the resulting dataframe
print(f'Theres a total of {result_domains_filtered_by_date.count()} domains filtered by date.')

#result_domains_filtered_by_date.export_csv_arrow("arrow_" + export_csv_folder, progress=True)
result_domains_filtered_by_date.export_csv(export_csv_folder, progress=True)


from tkinter import *
from tkinter import ttk

# cores
cor1 = "#d9dbda" #Silver
cor2 = "#FFAB40" #Orange
cor3 = "#ffffff" #White
cor4 = "#6aa7f7" #Blue Clear

window = Tk()
window.title("Calculadora")
window.geometry("235x310")
window.config(bg='black')
window.minsize(235,310)
window.maxsize(235,310)

# Frames
frame_tela = Frame(window, width=235, height=50, bg=cor1)
frame_tela.grid(row=0, column=0)
frame_body = Frame(window, width=235, height=268)
frame_body.grid(row=1, column=0)

# Variables
all_values = ''

# Functions

    #Input numbers in Screen
def entry_values(values):
    #Make the global values
    global all_values

    all_values += str(values)

    #Input valors from screen
    values_text.set(all_values)

    #Calculate numbers in Screen
def calculate():
    result = eval(all_values)
    values_text.set(result)

    #Clear numbers in Screen
def clear_screen():
    global all_values
    all_values = ''
    values_text.set('')

# Label
values_text = StringVar()
create_label = Label(frame_tela, textvariable=values_text, width=16, height=2, padx=7, relief=FLAT, anchor="e", justify=RIGHT, font=('Ivy 18'), bg=cor1)
create_label.place(x=0, y=0)

# Buttons
b_1 = Button(frame_body, text="%", width=11, height=2, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('%'))
b_1.place(x=0, y=0)
b_2 = Button(frame_body, text="C", width=5, height=2, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= clear_screen)
b_2.place(x=118, y=0)
b_3 = Button(frame_body, text="/", width=5, height=2, bg=cor2, fg=cor3, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('/'))
b_3.place(x=177, y=0)

b_4 = Button(frame_body, text="7", width=5, height=2, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('7'))
b_4.place(x=0, y=52)
b_5 = Button(frame_body, text="8", width=5, height=2, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('8'))
b_5.place(x=59, y=52)
b_6 = Button(frame_body, text="9", width=5, height=2, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('9'))
b_6.place(x=118, y=52)
b_7 = Button(frame_body, text="*", width=5, height=2, bg=cor2, fg=cor3, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('*'))
b_7.place(x=177, y=52)

b_8 = Button(frame_body, text="4", width=5, height=2, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('4'))
b_8.place(x=0, y=104)
b_9 = Button(frame_body, text="5", width=5, height=2, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('5'))
b_9.place(x=59, y=104)
b_10 = Button(frame_body, text="6", width=5, height=2, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('6'))
b_10.place(x=118, y=104)
b_11 = Button(frame_body, text="+", width=5, height=2, bg=cor2, fg=cor3, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('+'))
b_11.place(x=177, y=104)

b_12 = Button(frame_body, text="3", width=5, height=2, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('3'))
b_12.place(x=0, y=156)
b_13 = Button(frame_body, text="2", width=5, height=2, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('2'))
b_13.place(x=59, y=156)
b_14 = Button(frame_body, text="1", width=5, height=2, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('1'))
b_14.place(x=118, y=156)
b_15 = Button(frame_body, text="-", width=5, height=2, bg=cor2, fg=cor3, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('-'))
b_15.place(x=177, y=156)

b_1 = Button(frame_body, text="0", width=5, height=2, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('0'))
b_1.place(x=0, y=208)
b_2 = Button(frame_body, text=".", width=5, height=2, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= lambda: entry_values('.'))
b_2.place(x=59, y=208)
b_3 = Button(frame_body, text="=", width=11, height=2, bg=cor4, fg=cor3, font=('Ivy 13 bold'), relief=RAISED, overrelief=RIDGE, command= calculate)
b_3.place(x=118, y=208)

window.mainloop()