from __future__ import unicode_literals
from __future__ import print_function
from __future__ import division
from __future__ import absolute_import
from future import standard_library
standard_library.install_aliases()
from builtins import *
import itertools
import logging
import pymongo
import arrow
import pandas as pd

import emission.storage.timeseries.timequery as estt

import emission.core.get_database as edb
import emission.core.wrapper.rawtrip as ecwrt
import emission.core.wrapper.entry as ecwe
import emission.core.wrapper.userinput as ecwui

import emission.storage.timeseries.abstract_timeseries as esta
import emission.storage.timeseries.cache_series as estsc
import emission.storage.decorations.timeline as esdt
import emission.storage.decorations.analysis_timeseries_queries as esda

EPOCH_MINIMUM = 0
EPOCH_MAXIMUM = 2**31 - 1

# helpers for getting start/enter and end/exit times of a trip/place
begin_of = lambda te: te['data'].get('start_ts', te['data'].get('enter_ts'))
end_of = lambda te: te['data'].get('end_ts', te['data'].get('exit_ts'))

def get_raw_sections_for_trip(user_id, trip_id):
    return get_sections_for_trip("segmentation/raw_section", user_id, trip_id)

def get_cleaned_sections_for_trip(user_id, trip_id):
    return get_sections_for_trip("analysis/cleaned_section", user_id, trip_id)

def get_raw_stops_for_trip(user_id, trip_id):
    return get_stops_for_trip("segmentation/raw_stop", user_id, trip_id)

def get_cleaned_stops_for_trip(user_id, trip_id):
    return get_stops_for_trip("analysis/cleaned_stop", user_id, trip_id)

def get_raw_timeline_for_trip(user_id, trip_id):
    """
    Get an ordered sequence of sections and stops corresponding to this trip.
    """
    return esdt.Timeline(esda.RAW_STOP_KEY, esda.RAW_SECTION_KEY,
                         get_raw_stops_for_trip(user_id, trip_id),
                         get_raw_sections_for_trip(user_id, trip_id))

def get_cleaned_timeline_for_trip(user_id, trip_id):
    """
    Get an ordered sequence of sections and stops corresponding to this trip.
    """
    return esdt.Timeline(esda.CLEANED_STOP_KEY, esda.CLEANED_SECTION_KEY,
                         get_cleaned_stops_for_trip(user_id, trip_id),
                         get_cleaned_sections_for_trip(user_id, trip_id))

def get_sections_for_trip(key, user_id, trip_id):
    # type: (UUID, object_id) -> list(sections)
    """
    Get the set of sections that are children of this trip.
    """
    query = {"user_id": user_id, "data.trip_id": trip_id,
             "metadata.key": key}
    logging.debug("About to execute query %s with sort_key %s" % (query, "data.start_ts"))
    section_doc_cursor = edb.get_analysis_timeseries_db().find(query).sort(
        "data.start_ts", pymongo.ASCENDING)
    return [ecwe.Entry(doc) for doc in section_doc_cursor]

def get_stops_for_trip(key, user_id, trip_id):
    """
    Get the set of sections that are children of this trip.
    """
    query = {"user_id": user_id, "data.trip_id": trip_id,
             "metadata.key": key}
    logging.debug("About to execute query %s with sort_key %s" % (query, "data.enter_ts"))
    stop_doc_cursor = edb.get_analysis_timeseries_db().find(query).sort(
        "data.enter_ts", pymongo.ASCENDING)
    return [ecwe.Entry(doc) for doc in stop_doc_cursor]

def _get_next_cleaned_timeline_entry(ts, tl_entry):
    """
    Find the next trip or place in the timeline
    """
    if ("end_place" in tl_entry.data):
        return ts.get_entry_from_id(esda.CLEANED_PLACE_KEY, tl_entry.data.end_place)
    elif ("starting_trip" in tl_entry.data):
        starting_trip = ts.get_entry_from_id(esda.CLEANED_TRIP_KEY, tl_entry.data.starting_trip)
        # if there is no cleaned trip, fall back to untracked time
        if starting_trip is None:
            logging.debug("Starting trip %s is not tracked, checking untracked time..." % tl_entry.data.starting_trip)
            starting_trip = ts.get_entry_from_id(esda.CLEANED_UNTRACKED_KEY, tl_entry.data.starting_trip)
        return starting_trip
    else:
        return None

def get_user_input_for_trip(trip_key, user_id, trip_id, user_input_key):
    ts = esta.TimeSeries.get_time_series(user_id)
    trip_obj = ts.get_entry_from_id(trip_key, trip_id)
    return get_user_input_for_timeline_entry(ts, trip_obj, user_input_key)

# Additional checks to be consistent with the phone code
# www/js/diary/services.js
# Since that has been tested the most
# If we no longer need these checks (maybe with trip editing), we can remove them
def valid_user_input_for_timeline_entry(ts, tl_entry, user_input):
    # we know that the trip is cleaned so we can use the fmt_time
    # but the confirm objects are not necessarily filled out
    fmt_ts = lambda ts, tz: arrow.get(ts).to(tz)

    entry_start = begin_of(tl_entry)
    entry_end = end_of(tl_entry)
    if entry_start is None:
        # a place will have no enter time if it is the first place in the timeline
        # so we will set the start time as low as possible for the purpose of comparison
        entry_start = EPOCH_MINIMUM
    if entry_end is None:
        # a place will have no exit time if the user hasn't left there yet
        # so we will set the end time as high as possible for the purpose of comparison
        entry_end = EPOCH_MAXIMUM

#     logging.warn("Comparing user input %s (%s) of type %s: %s -> %s, trip of type %s %s (%s) -> %s (%s)" %
#         (user_input.data.label, user_input.get_id(), user_input.metadata.key,
#         fmt_ts(user_input.data.start_ts, user_input.metadata.time_zone),
#         fmt_ts(user_input.data.end_ts, user_input.metadata.time_zone),
#         tl_entry.get_id(),
#         fmt_ts(entry_start, user_input.metadata.time_zone), entry_start,
#         fmt_ts(entry_end, user_input.metadata.time_zone), entry_end))

    logging.debug("Comparing user input %s: %s -> %s, trip %s -> %s, start checks are (%s && %s) and end checks are (%s || %s)" % (
        user_input.data.label,
        fmt_ts(user_input.data.start_ts, user_input.metadata.time_zone),
        fmt_ts(user_input.data.end_ts, user_input.metadata.time_zone),
        fmt_ts(entry_start, user_input.metadata.time_zone), fmt_ts(entry_end, user_input.metadata.time_zone),
        (user_input.data.start_ts >= entry_start),
        (user_input.data.start_ts < entry_end),
        (user_input.data.end_ts <= entry_end),
        ((user_input.data.end_ts - entry_end) <= 15 * 60)
    ))
    start_checks = (user_input.data.start_ts >= entry_start and
        user_input.data.start_ts < entry_end)
    end_checks = (user_input.data.end_ts <= entry_end or
        ((user_input.data.end_ts - entry_end) <= 15 * 60))
    if start_checks and not end_checks:
        logging.debug("Handling corner case where start check matches, but end check does not")
        next_entry_obj = _get_next_cleaned_timeline_entry(ts, tl_entry)
        if next_entry_obj is not None:
            next_entry_end = end_of(next_entry_obj)
            if next_entry_end is None: # the last place will not have an exit_ts
                end_checks = True # so we will just skip the end check
            else:
                end_checks = user_input.data.end_ts <= next_entry_end
                logging.debug("Second level of end checks when the next trip is defined (%s <= %s) = %s" % (
                    user_input.data.end_ts, next_entry_end, end_checks))
        else:
            end_checks = True
            logging.debug("Second level of end checks when the next trip is not defined = %s" % end_checks)
        if end_checks:
            # If we have flipped the values, check to see that there is sufficient overlap
            # https://github.com/e-mission/e-mission-docs/issues/476#issuecomment-747587041
            overlapDuration = min(user_input.data.end_ts, entry_end) - max(user_input.data.start_ts, entry_start)
            logging.debug("Flipped endCheck, overlap(%s)/trip(%s) = %s" %
                (overlapDuration, tl_entry.data.duration, (overlapDuration / tl_entry.data.duration)));
            end_checks = (overlapDuration/tl_entry.data.duration) > 0.5;
    return start_checks and end_checks

def valid_user_input(ts, trip_obj):
    def curried(user_input):
        return valid_user_input_for_timeline_entry(ts, trip_obj, user_input)
    return curried

def final_candidate(filter_fn, potential_candidates):
    potential_candidate_objects = [ecwe.Entry(c) for c in potential_candidates]
    extra_filtered_potential_candidates = list(filter(filter_fn, potential_candidate_objects))
    if len(extra_filtered_potential_candidates) == 0:
        return None

    # In general, all candiates will have the same start_ts, so no point in
    # sorting by it. Only exception to general rule is when user first provides
    # input before the pipeline is run, and then overwrites after pipeline is
    # run
    sorted_pc = sorted(extra_filtered_potential_candidates, key=lambda c:c["metadata"]["write_ts"])

    # for debug logs, we'll print out label if it exists; else use the start or enter time of the input
    entry_detail = lambda c: getattr(c.data, "label", \
                                getattr(c.data, "start_fmt_time", \
                                getattr(c.data, "enter_fmt_time", None)))
    logging.debug("sorted candidates are %s" %
        [{"write_fmt_time": c.metadata.write_fmt_time, "detail": entry_detail(c)} for c in sorted_pc])
    most_recent_entry = sorted_pc[-1]
    logging.debug("most recent entry is %s, %s" %
        (most_recent_entry.metadata.write_fmt_time, entry_detail(most_recent_entry)))
    return most_recent_entry

def get_not_deleted_candidates(filter_fn, potential_candidates):
    potential_candidate_objects = [ecwe.Entry(c) for c in potential_candidates]
    extra_filtered_potential_candidates = list(filter(filter_fn, potential_candidate_objects))
    if len(extra_filtered_potential_candidates) == 0:
        logging.debug(f"in get_not_deleted_candidates, no candidates, returning []")
        return []

    # We want to retain all ACTIVE entries that have not been DELETED
    all_active_list = [efpc for efpc in extra_filtered_potential_candidates if "status" not in efpc.data or efpc.data.status == ecwui.InputStatus.ACTIVE]
    all_deleted_id = [efpc["data"]["match_id"] for efpc in extra_filtered_potential_candidates if "status" in efpc.data and efpc.data.status == ecwui.InputStatus.DELETED]
    # TODO: Replace this with filter and a lambda if we decide not to match by ID after all
    not_deleted_active = [efpc for efpc in all_active_list if efpc["data"]["match_id"] not in all_deleted_id]
    logging.info(f"Found {len(all_active_list)} active entries, {len(all_deleted_id)} deleted entries -> {len(not_deleted_active)} non deleted active entries")
    return not_deleted_active

def get_time_query_for_timeline_entry(timeline_entry, force_start_end=True):
    begin_of_entry = begin_of(timeline_entry)
    end_of_entry = end_of(timeline_entry)
    inferred_time_type = lambda timeline_entry: "data.start_ts" if "start_ts" in timeline_entry.data else "data.enter_ts"
    timeType = "data.start_ts" if force_start_end else inferred_time_type
    if begin_of_entry is None:
        # a place will have no enter time if it is the first place in the timeline
        # so we will set the start time as low as possible for the purpose of comparison
        entry_start = EPOCH_MINIMUM
    if end_of_entry is None:
        # the last place (user's current place) will not have an exit_ts, so
        # every input from its enter_ts onward is fair game
        end_of_entry = EPOCH_MAXIMUM
    return estt.TimeQuery(timeType, begin_of_entry, end_of_entry)

def get_user_input_for_timeline_entry(ts, timeline_entry, user_input_key):
    # When we start supporting user inputs for places, we need to decide whether they will have
    # start/end or enter/exit. Depending on the decision, we can either remove support for
    # force_start_end (since we always use start/end) or pass in False (so we
    # use start/end or enter/exit appropriately)
    tq = get_time_query_for_timeline_entry(timeline_entry)
    potential_candidates = ts.find_entries([user_input_key], tq)
    return final_candidate(valid_user_input(ts, timeline_entry), potential_candidates)

# This is almost an exact copy of get_user_input_for_trip_object, but it
# retrieves an interable instead of a dataframe. So almost everything is
# different and it is hard to unify the implementations. Switching the existing
# function from get_data_df to find_entries may help us unify in the future

def get_user_input_from_cache_series(user_id, timeline_entry, user_input_key):
    # When we start supporting user inputs for places, we need to decide whether they will have
    # start/end or enter/exit. Depending on the decision, we can either remove support for
    # force_start_end (since we always use start/end) or pass in False (so we
    # use start/end or enter/exit appropriately)
    ts = esta.TimeSeries.get_time_series(user_id)
    tq = get_time_query_for_timeline_entry(timeline_entry)
    potential_candidates = estsc.find_entries(user_id, [user_input_key], tq)
    return final_candidate(valid_user_input(ts, timeline_entry), potential_candidates)

def get_additions_for_timeline_entry_object(ts, timeline_entry):
    addition_keys = ["manual/trip_addition_input", "manual/place_addition_input"]
    # This should always be start/end
    # https://github.com/e-mission/e-mission-docs/issues/880#issuecomment-1509875714
    tq = get_time_query_for_timeline_entry(timeline_entry)
    potential_candidates = ts.find_entries(addition_keys, tq)
    return get_not_deleted_candidates(valid_user_input(ts, timeline_entry), potential_candidates)

def valid_timeline_entry(ts, user_input):
    def curried(confirmed_obj):
        return valid_user_input_for_timeline_entry(ts, confirmed_obj, user_input)
    return curried

# Find the trip or place that the user input belongs to to
def get_confirmed_obj_for_user_input_obj(ts, ui_obj):
    # the match check that we have is:
    # user input can start after trip/place start
    # user input can end before trip/place end OR within 15 minutes after
    # Given those considerations, there is no principled query for trip/place data
    # that fits into our query model
    # the trip/place start is before the user input start, but that can go until eternity
    # and the trip/place end can be either before or after the user input end
    # we know that the trip/place end is after the user input start, but again, that
    # can go on until now.
    # As a workaround, let us assume that the trip/place start is no more than a day
    # before the start of the ui object, which seems like a fairly conservative
    # assumption
    ONE_DAY = 24 * 60 * 60
    tq = estt.TimeQuery("data.start_ts", ui_obj.data.start_ts - ONE_DAY,
        ui_obj.data.start_ts + ONE_DAY)

    # iff the input's key is one of these, the input belongs on a place
    # all other keys are only used for trip inputs
    place_keys = ["manual/place_user_input", "manual/place_addition_input"]
    if ui_obj['metadata']['key'] in place_keys:
        # if place, we'll query the same time range, but with 'enter_ts'
        tq.timeType = "data.enter_ts"
        potential_candidates = ts.find_entries(["analysis/confirmed_place"], tq)
    else:
        potential_candidates = ts.find_entries(["analysis/confirmed_trip"], tq)

    return final_candidate(valid_timeline_entry(ts, ui_obj), potential_candidates)

def filter_labeled_trips(mixed_trip_df):
    """
    mixed_trip_df: a dataframe with mixed labeled and unlabeled entries
    Returns only the labeled entries
    """
    if len(mixed_trip_df) == 0:
        return mixed_trip_df
    labeled_ct = mixed_trip_df[mixed_trip_df.user_input != {}]
    logging.debug("After filtering, found %s labeled trips" % len(labeled_ct))
    logging.debug(labeled_ct.head())
    return labeled_ct

def expand_userinputs(labeled_ct):
    """
    labeled_ct: a dataframe that contains potentially mixed trips.
    Returns a dataframe with the labels expanded into the main dataframe
    If the labels are simple, single level kv pairs (e.g. {mode_confirm:
    bike}), the expanded columns can be indexed very simply, like the other
    columns in the dataframe. Trips without labels are represented by N/A

    TODO: Replace by pandas.io.json.json_normalize?
    TODO: Currently duplicated from
    https://github.com/e-mission/em-public-dashboard/blob/main/viz_scripts/scaffolding.py

    Should remove it from there
    """
    if len(labeled_ct) == 0:
        return labeled_ct
    label_only = pd.DataFrame(labeled_ct.user_input.to_list(), index=labeled_ct.index)
    logging.debug(label_only.head())
    expanded_ct = pd.concat([labeled_ct, label_only], axis=1)
    assert len(expanded_ct) == len(labeled_ct), \
        ("Mismatch after expanding labels, expanded_ct.rows = %s != labeled_ct.columns %s" %
            (len(expanded_ct), len(labeled_ct)))
    logging.debug("After expanding, columns went from %s -> %s" %
        (len(labeled_ct.columns), len(expanded_ct.columns)))
    logging.debug(expanded_ct.head())
    return expanded_ct

def has_final_labels(confirmed_trip_data):
    return (confirmed_trip_data["user_input"] != {}
            or confirmed_trip_data["expectation"]["to_label"] == False)

# Create an alternate method to work on the dataframe column-wise
# instead of iterating over each individual row for improved performance
def has_final_labels_df(df):
    # print(df.expectation)
    # print(pd.DataFrame(df.expectation.to_list(), index=df.index))
    to_list_series = pd.DataFrame(df.expectation.to_list(), index=df.index).to_label
    return df[(df.user_input != {})
            | (to_list_series == False)]

def get_max_prob_label(inferred_label_list):
    # Two columns: "labels" and "p"
    label_prob_df = pd.DataFrame(inferred_label_list)
    # logging.debug(label_prob_df)
    # idxmax returns the index corresponding to the max data value in each column
    max_p_idx = label_prob_df.p.idxmax()
    # logging.debug(max_p_idx)
    # now we look up the labels for that index
    return label_prob_df.loc[max_p_idx].labels

def expand_finallabels(labeled_ct):
    """
    labeled_ct: a dataframe that contains potentially mixed trips.
    Returns a dataframe with the user input labels and the high confidence
    inferred labels expanded into the main dataframe.  If the labels are
    simple, single level kv pairs (e.g. {mode_confirm: bike}), the expanded columns
    can be indexed very simply, like the other columns in the dataframe. Trips
    without labels are represented by N/A
    """
    if len(labeled_ct) == 0:
        return labeled_ct
    user_input_only = pd.DataFrame(labeled_ct.user_input.to_list(), index=labeled_ct.index)
    # Drop entries that are blank so we don't end up with duplicate entries in the concatenated dataframe.
    # without this change, concat might involve N/A rows from user entries,
    # inserted because the index is specified manually
    # then if they have high confidence entries, we will end up with
    # duplicated entries for N/A and the yellow labels
    user_input_only.dropna('index', how="all", inplace=True)
    logging.debug("user_input_only %s" % user_input_only.head())

    # see testExpandFinalLabelsPandasFunctionsNestedPostFilter for a step by step
    # walkthrough of how this section works. Note that
    # testExpandFinalLabelsPandasFunctionsNestedPostFilter has an alternate
    # implementation that we don't choose because it generates a UserWarning

    # Note that we could have entries that have both user inputs and high
    # confidence inferred values. This could happen if the user chooses to go
    # into "All Labels" and label high-confidence values. That's why the
    # algorithm
    # https://github.com/e-mission/e-mission-docs/issues/688#issuecomment-1000981037
    # specifies that we look for inferred values only if the user input does
    # not exist
    expectation_expansion = pd.DataFrame(labeled_ct.expectation.to_list(), index=labeled_ct.index)
    high_confidence_no_userinput_df = labeled_ct[
        (labeled_ct.user_input == {}) & (expectation_expansion.to_label == False)
    ]
    high_confidence_no_userinput_df.dropna('index', how="all", inplace=True)
    if len(high_confidence_no_userinput_df) > 0:
        high_confidence_inferred_labels = high_confidence_no_userinput_df.inferred_labels
        high_confidence_max_p_inferred_labels = high_confidence_inferred_labels.apply(get_max_prob_label)
        high_confidence_max_p_inferred_labels_only = pd.DataFrame(
                high_confidence_max_p_inferred_labels.to_list(),
                index=high_confidence_inferred_labels.index)
        logging.debug("high confidence inferred %s" % high_confidence_max_p_inferred_labels_only.head())

        assert pd.Series(labeled_ct.loc[
                high_confidence_max_p_inferred_labels_only.index].user_input == {}).all(), \
            ("Did not filter out all user inputs before expanding high confidence labels %s" %
                labeled_ct.loc[high_confidence_max_p_inferred_labels_only.index].user_input)
    else:
        high_confidence_max_p_inferred_labels_only = pd.DataFrame()

    # see testExpandFinalLabelsPandasFunctions for a step by step walkthrough of this section
    naive_concat = pd.concat([user_input_only, high_confidence_max_p_inferred_labels_only], axis=0)
    # print(naive_concat)
    label_only = naive_concat.reindex(labeled_ct.index)

    expanded_ct = pd.concat([labeled_ct, label_only], axis=1)
    assert len(expanded_ct) == len(labeled_ct), \
        ("Mismatch after expanding labels, expanded_ct.rows = %s != labeled_ct.columns %s" %
            (len(expanded_ct), len(labeled_ct)))
    logging.debug("After expanding, columns went from %s -> %s" %
        (len(labeled_ct.columns), len(expanded_ct.columns)))
    logging.debug(expanded_ct.head())
    return expanded_ct


import json
import ptvsd
import sys
import requests
import boto3

ptvsd.enable_attach(address=('0.0.0.0', 5678), redirect_output=True)

print("waiting for debugger to attach...")

sys.stdout.flush()

ptvsd.wait_for_attach()

print("attached")

# import requests

def create_dynamo_table(event, context, table_name_value, enable_streams=False, read_capacity=1, write_capacity=1,region='us-west-2'):

    table_name = table_name_value
    print('creating table: ' + table_name)
    responseObject = {}
    responseObject['headers'] = {}
    responseObject['headers']['content-type'] = 'application/json'

    try:

        client = boto3.client(service_name='dynamodb', region_name=region)
        table = (client.create_table(TableName=table_name,
                                    AttributeDefinitions=[
                                        {'AttributeName': 'EventId', 'AttributeType': 'S'},
                                        {'AttributeName': 'EventDay', 'AttributeType': 'N' }
                                        ],
                                    KeySchema=[{'AttributeName': 'EventId', 'KeyType': 'HASH'},
                                        {'AttributeName': 'EventDay','KeyType': 'RANGE'},
                                        ],
                                    ProvisionedThroughput={'ReadCapacityUnits': read_capacity, 'WriteCapacityUnits': write_capacity}))

        print(table)
        responseObject['statusCode'] = 200
        responseObject['body'] = json.dumps(table)
    except Exception as e:
        print(str(type(e)))
        print(e.__doc__)
        responseObject['statusCode'] = 500
        responseObject['body'] = json.dumps(e.__doc__)

    return responseObject

def create_handler(event, context):
    table_name = 'user-visits'
    return create_dynamo_table(event, context, table_name, False, 1, 1)


#
# Day 3: Rucksack Reorganization
# https://adventofcode.com/2022/day/3
#
import string

def calculate(lines: list[str]):
    SCORE_KEY = list(string.ascii_lowercase) + list(string.ascii_uppercase)
    score = 0
    for i in range(0, len(lines), 3):
        sack1 = set(lines[i].strip())
        sack2 = set(lines[i + 1].strip())
        sack3 = set(lines[i + 2].strip())
        common = (sack1 & sack2 & sack3).pop()
        score += SCORE_KEY.index(common) + 1
    return score

with open("input.txt") as f:
    lines = f.readlines()
print(calculate(lines))


"""Console script for bgcflow."""
import subprocess
import sys
from pathlib import Path

import click

import bgcflow
from bgcflow.bgcflow import cloner, deployer, get_all_rules, snakemake_wrapper
from bgcflow.mkdocs import generate_mkdocs_report
from bgcflow.projects_util import copy_final_output, projects_util

CONTEXT_SETTINGS = dict(help_option_names=["-h", "--help"])

@click.group(context_settings=CONTEXT_SETTINGS)
@click.version_option(version=bgcflow.__version__)
def main():
    """
    A snakemake wrapper and utility tools for BGCFlow (https://github.com/NBChub/bgcflow)
    """
    pass

@main.command()
@click.argument("destination")
@click.option("--branch", default="main", help="BGCFlow branch/release to use")
def deploy(**kwargs):
    """
    [EXPERIMENTAL] Deploy BGCFlow locally using snakedeploy.

    DESTINATION: path to deploy BGCFlow
    """
    deployer(**kwargs)

@main.command()
@click.argument("destination")
@click.option(
    "--branch",
    default="main",
    help="BGCFlow branch. (DEFAULT: `dev-snakemake-wrapper`)",
)
def clone(**kwargs):
    """
    Use git to clone BGCFlow to local directory.

    DESTINATION: path to clone BGCFlow

    BRANCH: BGCFlow branch to clone. Currently using development branch: `dev-snakemake-wrapper`
    """
    cloner(**kwargs)

@main.command()
@click.option(
    "--bgcflow_dir",
    default=".",
    help="Location of BGCFlow directory. (DEFAULT: Current working directory.)",
)
@click.option(
    "--snakefile",
    default="workflow/Snakefile",
    help="Location of the Snakefile relative to BGCFlow directory. (DEFAULT: workflow/Snakefile)",
)
@click.option(
    "--wms-monitor",
    default="http://127.0.0.1:5000",
    help="Panoptes address. (DEFAULT: http://127.0.0.1:5000)",
)
@click.option(
    "-c",
    "--cores",
    default=8,
    help="Use at most N CPU cores/jobs in parallel. (DEFAULT: 8)",
)
@click.option("-n", "--dryrun", is_flag=True, help="Test run.")
@click.option(
    "-t",
    "--touch",
    is_flag=True,
    help="Touch output files (mark them up to date without really changing them).",
)
def run(**kwargs):
    """
    A snakemake CLI wrapper to run BGCFlow. Automatically run panoptes.

    """
    snakemake_wrapper(**kwargs)

@main.command()
@click.option(
    "--bgcflow_dir",
    default=".",
    help="Location of BGCFlow directory. (DEFAULT: Current working directory)",
)
@click.option("--describe", help="Get description of a given rule.")
@click.option("--cite", help="Get citation of a given rule.")
def rules(**kwargs):
    """
    Get description of available rules from BGCFlow.

    """
    get_all_rules(**kwargs)

@main.command()
@click.option(
    "--bgcflow_dir",
    default=".",
    help="Location of BGCFlow directory. (DEFAULT: Current working directory)",
)
@click.option(
    "--project",
    help="Initiate a new BGCFlow project. Insert project name: `bgcflow init --project <TEXT>`",
)
@click.option(
    "--use_own_rules",
    is_flag=True,
    help="Generate rule selection template in PEP file instead of using Global rules. Use with `--project` option.",
)
@click.option(
    "--prokka_db", help="Path to custom reference file. Use with `--project` option."
)
@click.option(
    "--gtdb_tax", help="Path to custom taxonomy file. Use with `--project` option."
)
@click.option(
    "--samples_csv", help="Path to samples file. Use with `--project` option."
)
def init(**kwargs):
    """
    Create projects or initiate BGCFlow config. Use --project to create a new BGCFlow project.

    Usage:
    bgcflow init --> check current directory for existing config dir. If not found, generate from template.
    bgcflow init --project <TEXT> --> generate a new BGCFlow project in the config directory.

    """
    try:
        projects_util(**kwargs)
    except FileNotFoundError as e:
        click.echo(
            "ERROR: Cannot find BGCFlow directory.\nPoint to the right directory using `--bgcflow_dir <destination>` or clone BGCFlow using `bgcflow clone <destination>`"
        )
        print(e)

@main.command()
@click.argument("project")
@click.option("--copy", help="Destination path to copy results.")
@click.option(
    "--bgcflow_dir",
    default=".",
    help="Location of BGCFlow directory. (DEFAULT: Current working directory)",
)
# @click.option('--tree',  is_flag=True, help='Show output directory tree structure of a given project.)')
def get_result(**kwargs):
    """
    View a tree of a project results or get a copy using Rsync.

    PROJECT: project name
    """
    if kwargs["copy"] is None:
        project_dir = (
            Path(kwargs["bgcflow_dir"]) / f"data/processed/{kwargs['project']}"
        )
        subprocess.call(["tree", "-L", "2", project_dir])
    else:
        copy_final_output(**kwargs)

@main.command()
@click.option("--port", default=8001, help="Port to use. (DEFAULT: 8001)")
@click.option(
    "--file_server",
    default="http://localhost:8002",
    help="Port to use for fileserver. (DEFAULT: http://localhost:8002)",
)
@click.option(
    "--bgcflow_dir",
    default=".",
    help="Location of BGCFlow directory. (DEFAULT: Current working directory)",
)
@click.option("--project", help="Name of the project. (DEFAULT: all)")
def serve(**kwargs):
    """
    Generate static HTML report for BGCFlow run(s)
    """
    if kwargs["project"] is None:
        click.echo(
            "Use `bgcflow serve --project <project name>` to generate report for each project.\nTo see Snakemake run summary, use `bgcflow serve --project snakemake_report`."
        )
    elif kwargs["project"] == "snakemake_report":
        output_dir = Path(kwargs["bgcflow_dir"]) / "data"
        workflow_dir = Path(kwargs["bgcflow_dir"]) / "workflow"
        assert (
            output_dir.is_dir()
        ), "ERROR: Cannot find BGCFlow directory. Use --bgcflow_dir to set the right location."
        subprocess.call(
            f"(cd {workflow_dir.parent.resolve()} && snakemake --report index.html)",
            shell=True,
        )
        subprocess.call(
            f"(cd {workflow_dir.resolve()} && jupyter nbconvert --execute --to html --output {output_dir.resolve()}/processed/index.html {workflow_dir.resolve()}/notebook/99-entry_point.ipynb --no-input --template classic)",
            shell=True,
        )
        subprocess.call(
            [
                "python",
                "-m",
                "http.server",
                "--directory",
                kwargs["bgcflow_dir"],
                str(kwargs["port"]),
            ]
        )
    else:
        bgcflow_dir = kwargs["bgcflow_dir"]
        project_name = kwargs["project"]
        port_id = kwargs["port"]
        file_server = kwargs["file_server"]
        generate_mkdocs_report(
            bgcflow_dir, project_name, port_id, file_server, ipynb=False
        )

@click.option(
    "--bgcflow_dir",
    default=".",
    help="Location of BGCFlow directory. (DEFAULT: Current working directory.)",
)
@click.option(
    "-c",
    "--cores",
    default=8,
    help="Use at most N CPU cores/jobs in parallel. (DEFAULT: 8)",
)
@click.option("-n", "--dryrun", is_flag=True, help="Test run.")
@main.command()
def build(**kwargs):
    """
    Use DBT to build DuckDB database from BGCFlow results.
    """
    dryrun = ""
    bgcflow_dir = Path(kwargs["bgcflow_dir"])
    if kwargs["dryrun"]:
        dryrun = "--dryrun"

    subprocess.call(
        f"cd {bgcflow_dir.resolve()} && snakemake --use-conda -c {kwargs['cores']} --snakefile workflow/Database --keep-going {dryrun}",
        shell=True,
    )

if __name__ == "__main__":
    sys.exit(main())  # pragma: no cover


import setuptools

import version

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

setuptools.setup(
    name="uncertainty-wizard",
    version=version.RELEASE,
    author="Michael Weiss",
    author_email="code@mweiss.ch",
    description="Quick access to uncertainty and confidence of Keras networks.",
    long_description=long_description,
    long_description_content_type="text/markdown",
    url="https://github.com/testingautomated-usi/uncertainty_wizard",
    packages=setuptools.find_packages(),
    classifiers=[
        "Development Status :: 4 - Beta",
        "Programming Language :: Python :: 3",
        "Topic :: Scientific/Engineering :: Artificial Intelligence",
        "License :: OSI Approved :: MIT License",
        "Operating System :: OS Independent",
    ],
    python_requires='>=3.6',
)


# -*-coding:utf-8-*-
"""
File Name: mouse_response_and_type_conversion.py
Program IDE: PyCharm
Date: 10:04
Create File By Author: Hong
"""
import cv2 as cv
import numpy as np

# 在图像上画矩形框
x1 = -1
y1 = -1
x2 = -1
y2 = -1

# canvas = np.zeros((300, 300, 3), dtype=np.uint8)
canvas = cv.imread('images/2.png', cv.IMREAD_COLOR)
img = np.copy(canvas)

# 回调，系统调用回调函数解决你的问题
# 鼠标响应回调函数，参数固定；对应鼠标事件、横坐标、纵坐标、flags和其他参数
def mouse_drawing(event, x, y, flags, param):
    # print(x, y)
    global x1, y1, x2, y2
    if event == cv.EVENT_LBUTTONDOWN:
        x1 = x
        y1 = y
    if event == cv.EVENT_MOUSEMOVE:
        if x1 < 0 or y1 < 0:
            return
        x2 = x
        y2 = y
        dx = x2 - x1
        dy = y2 - y1
        if dx > 0 and dy > 0:
            # 擦除重叠
            # canvas[:, :] = 0
            canvas[:, :, :] = img[:, :, :]
            cv.rectangle(canvas, (x1, y1), (x2, y2), (255, 0, 0), 2, 8, 0)
    if event == cv.EVENT_LBUTTONUP:
        x2 = x
        y2 = y
        dx = x2 - x1
        dy = y2 - y1
        if dx > 0 and dy > 0:
            # canvas[:, :] = 0
            canvas[:, :, :] = img[:, :, :]
            cv.rectangle(canvas, (x1, y1), (x2, y2), (255, 0, 0), 2, 8, 0)

        x1 = -1
        y1 = -1
        x2 = -1
        y2 = -1

def mouse_response():
    cv.namedWindow('Mouse Response', cv.WINDOW_AUTOSIZE)
    # 再某个窗口上设置鼠标响应函数
    cv.setMouseCallback('Mouse Response', mouse_drawing)

    while True:
        cv.imshow('Mouse Response', canvas)
        c = cv.waitKey(1)
        if c == 27:
            break

    cv.destroyAllWindows()

# 图像像素类型转换和归一化
def pixel_normalization(image_path: str):
    img = cv.imread(image_path, cv.IMREAD_COLOR)
    # 可以显示整数和浮点数像素图片
    # 图像归一化
    # 方法1
    # print(img/255.0)
    cv.imshow('input', img / 255.0)

    # 方法2
    result = np.zeros_like(np.float32(img))
    cv.normalize(img, result, 0, 1, cv.NORM_MINMAX, dtype=cv.CV_32F)
    print(result)
    cv.imshow('result', result)

    cv.waitKey(0)
    cv.destroyAllWindows()

if __name__ == '__main__':
    path = 'images/2.png'
    mouse_response()
    # pixel_normalization(path)


import numpy as np
import copy
import json
import imageio
import math
import os
import functools
import torch
from torch import nn
from torch.utils.data import Dataset

# Code based on:
# https://github.com/openai/baselines/blob/master/baselines/deepq/replay_buffer.py

# Expects tuples of (state, next_state, action, reward, done)
class ReplayBuffer(object):
    def __init__(self, max_size=1e6):
        self.storage = []
        self.max_size = max_size

    def add(self, data):
        if len(self.storage) == self.max_size:
            self.storage.pop(0)
        self.storage.append(data)

    # @profile
    def sample(self, batch_size):
        ind = np.random.randint(0, len(self.storage), size=batch_size)

        # X, Y, U, R, D = self.storage[ind[0]]
        # x = np.empty((batch_size, *X.shape))
        # y = np.empty((batch_size, *Y.shape))
        # u = np.empty((batch_size, *U.shape))
        # r = np.empty((batch_size, 1))
        # d = np.empty((batch_size, 1))

        # for i, index in enumerate(ind):
        #     X, Y, U, R, D = self.storage[index]
        #     x[i] = X
        #     y[i] = Y
        #     u[i] = U
        #     r[i] = R
        #     d[i] = D
        # result = (x, y, u, r, d)

        x, y, u, r, d = [], [], [], [], []

        for i in ind:
            X, Y, U, R, D = self.storage[i]
            x.append(np.array(X, copy=False))
            y.append(np.array(Y, copy=False))
            u.append(np.array(U, copy=False))
            r.append(np.array(R, copy=False))
            d.append(np.array(D, copy=False))

        # import ipdb; ipdb.set_trace()
        result = (np.stack(x),
                  np.stack(y),
                  np.stack(u),
                  np.stack(r).reshape(-1, 1),
                  np.stack(d).reshape(-1, 1))
        return result

    def __len__(self):
        return len(self.storage)

    def sample_seq(self, batch_size, seq_len):
        ind = np.random.randint(0, len(self.storage) - seq_len + 1, size=batch_size)
        x, y, u, r, d = [], [], [], [], []

        for i in ind:
            transition_sequence = self.storage[i:i+seq_len]
            # take the sequence [(xyurd), (xyurd), (xyurd), (xyurd)]
            # and turn it into [(xxxx), (yyyy), (uuuu), (rrrr), (dddd)]
            X, Y, U, R, D = list(zip(*transition_sequence))
            x.append(np.array(X, copy=False))
            y.append(np.array(Y, copy=False))
            u.append(np.array(U, copy=False))
            r.append(np.array(R, copy=False))
            # import ipdb; ipdb.set_trace()
            d.append(np.array(D, copy=False))

        # import ipdb; ipdb.set_trace()
        result = (np.stack(x),
                  np.stack(y),
                  np.stack(u),
                  np.stack(r).reshape(batch_size, seq_len),
                  np.stack(d).reshape(batch_size, seq_len))
        return result

class ReplayDataset(Dataset):
    def __init__(self, max_size=1e6):
        self.storage = []
        self.max_size = max_size

    def add(self, data):
        if len(self.storage) == self.max_size:
            self.storage.pop(0)
        self.storage.append((
            data[0].astype('float32'),
            data[1].astype('float32'),
            data[2].astype('float32'),
            data[3],
            data[4]))

    def save(self, path):
        os.makedirs(path, exist_ok=True)

        stacked_arrays = [np.stack([d[i] for d in self.storage]) for i in range(5)]
        manifest = {
            'type': 'float32',
            'shapes': [array.shape for array in stacked_arrays]
        }
        torch.save(manifest, "{}/manifest.pt".format(path))

        saved_arrays = [np.memmap("{}/{}.npmm".format(path, i), dtype='float32', mode='write', shape=stacked_arrays[i].shape)
                        for i in range(5)]
        for saved_array, stacked_array in zip(saved_arrays, stacked_arrays):
            saved_array[:] = stacked_array[:]
            saved_array.flush()

    def load(self, path):
        manifest = torch.load("{}/manifest.pt".format(path))
        saved_arrays = [np.memmap("{}/{}.npmm".format(path, i), mode='r', dtype=manifest['type'], shape=manifest['shapes'][i])
                        for i in range(5)]
        self.storage = [tuple((np.array(saved_array[i]) for saved_array in saved_arrays))
                        for i in range(saved_arrays[0].shape[0])]
        self.storage = list(self.storage)

    def __len__(self):
        return len(self.storage)

    def __getitem__(self, i):
        return self.storage[i]

class DiskReplayDataset(Dataset):
    def __init__(self, path, max_size=1e6):
        self.storages = None
        self.path = path
        self.max_size = int(max_size)

        self.pointer = 0
        # self.size = 0

    def create_disk_arrays(self, data):
        def type_for(d):
            d_type = np.array(d).dtype
            if 'float' in str(d_type): d_type = 'float32'
            return d_type
        def shape_for(d): return (self.max_size,) + d.shape if isinstance(d, np.ndarray) else (self.max_size,)
        types = [type_for(d) for d in data]
        shapes = [shape_for(d) for d in data]
        os.makedirs(self.path, exist_ok=True)
        manifest = {
            'types': types,
            'shapes': shapes
        }
        torch.save(manifest, "{}/manifest.pt".format(self.path))
        self.storages = [np.memmap("{}/{}.npmm".format(self.path, i), dtype=types[i], mode='write', shape=shapes[i])
                         for i in range(len(data))]

    def add(self, data):
        if self.storages is None:
            def shape(d): return d.shape if isinstance(d, np.ndarray) else (1,)
            # import ipdb; ipdb.set_trace()
            sizes = tuple([(self.max_size,) + shape(data_elem) for data_elem in data])
            self.create_disk_arrays(data)
        address = self.pointer % self.max_size
        for storage, data_elem in zip(self.storages, data):
            storage[address] = data_elem
        self.pointer += 1

    def save(self, path):
        manifest = {
            'types': [s.dtype for s in self.storages],
            'shapes': [s.shape for s in self.storages],
            'pointer': self.pointer,
        }
        torch.save(manifest, "{}/manifest.pt".format(self.path))
        for storage in self.storages:
            storage.flush()

    def load(self, path):
        manifest = torch.load("{}/manifest.pt".format(path))
        self.storages = [np.memmap("{}/{}.npmm".format(path, i), mode='r',
                                   dtype=manifest['types'][i],
                                   shape=manifest['shapes'][i])
                        for i in range(5)]
        self.pointer = manifest['pointer']

    def __len__(self):
        return min(self.max_size, self.pointer)

    def __getitem__(self, i):
        return tuple((np.array(storage[i]) for storage in self.storages))

class EmbeddedReplayDataset(Dataset):
    def __init__(self, max_size=1e6, traj_len=4):
        self.storage = []
        self.max_size = max_size
        self.traj_len = traj_len

    def add(self, data):
        if len(self.storage) == self.max_size:
            self.storage.pop(0)
        self.storage.append((
            data[0].astype('float32'),
            data[1].astype('float32'),
            data[2].astype('float32'),
            data[3].astype('float32'),
            data[4],
            data[5],
            data[6]))

    def __len__(self):
        return len(self.storage) - self.traj_len

    def __getitem__(self, i):
        transition_sequence = self.storage[i:i+self.traj_len]
        # take the sequence [(xyurd), (xyurd), (xyurd), (xyurd)]
        # and turn it into [(xxxx), (yyyy), (uuuu), (rrrr), (dddd)]
        X, Y, U, E, I, R, D = list(zip(*transition_sequence))
        result = (
            np.array(X, copy=False),
            np.array(Y, copy=False),
            np.array(U, copy=False),
            np.array(E, copy=False),
            np.array(I, copy=False),#.reshape(-1, 1),
            np.array(R, copy=False),#.reshape(-1, 1),
            np.array(D, copy=False))#.reshape(-1, 1))
        # for r in result: print(r.shape)
        # import ipdb; ipdb.set_trace()
        return result

# Expects tuples of (state, next_state, action, embedded_plan, plan_step, reward, done)
class EmbeddedReplayBuffer(object):
    def __init__(self, max_size=1e6):
        self.storage = []
        self.max_size = max_size

    def add(self, data):
        if len(self.storage) == self.max_size:
            self.storage.pop(0)
        self.storage.append(data)

    def sample(self, batch_size):
        ind = np.random.randint(0, len(self.storage), size=batch_size)
        x, y, u, e, i, r, d = [], [], [], [], [], [], []

        for j in ind:
            X, Y, U, E, I, R, D = self.storage[j]
            x.append(np.array(X, copy=False))
            y.append(np.array(Y, copy=False))
            u.append(np.array(U, copy=False))
            e.append(np.array(E, copy=False))
            i.append(np.array(I, copy=False))
            r.append(np.array(R, copy=False))
            d.append(np.array(D, copy=False))

        result = (np.array(x),
                  np.array(y),
                  np.array(u),
                  np.array(e),
                  np.array(i).reshape(-1, 1),
                  np.array(r).reshape(-1, 1),
                  np.array(d).reshape(-1, 1))
        return result

    def __len__(self):
        return len(self.storage)

    def sample_seq(self, batch_size, seq_len):
        ind = np.random.randint(0, len(self.storage) - seq_len + 1, size=batch_size)
        x, y, u, e, i, r, d = [], [], [], [], [], [], []

        for j in ind:
            transition_sequence = self.storage[j:j+seq_len]
            # take the sequence [(xyurd), (xyurd), (xyurd), (xyurd)]
            # and turn it into [(xxxx), (yyyy), (uuuu), (rrrr), (dddd)]
            X, Y, U, E, I, R, D = list(zip(*transition_sequence))
            x.append(np.array(X, copy=False))
            y.append(np.array(Y, copy=False))
            u.append(np.array(U, copy=False))
            e.append(np.array(E, copy=False))
            i.append(np.array(I, copy=False))
            r.append(np.array(R, copy=False))
            d.append(np.array(D, copy=False))

        result = (np.stack(x),
                  np.stack(y),
                  np.stack(u),
                  np.stack(e),
                  np.stack(i).reshape(batch_size, seq_len),
                  np.stack(r).reshape(batch_size, seq_len),
                  np.stack(d).reshape(batch_size, seq_len))
        return result

def serialize_opt(opt):
    # import ipdb; ipdb.set_trace()
    cleaned_opt = copy.deepcopy(vars(opt))
    return json.dumps(cleaned_opt, indent=4, sort_keys=True)

def write_options(opt, location):
    with open(location + "/opt.json", 'w') as f:
        serial_opt = serialize_opt(opt)
        print(serial_opt)
        f.write(serial_opt)
        f.flush()

def save_gif(filename, inputs, bounce=False, color_last=False, duration=0.05):
    images = []
    for tensor in inputs:
        tensor = tensor.cpu()
        if not color_last:
            tensor = tensor.transpose(0,1).transpose(1,2)
        tensor = tensor.clamp(0,1)
        images.append((tensor.cpu().numpy() * 255).astype('uint8'))
    if bounce:
        images = images + list(reversed(images[1:-1]))
    imageio.mimsave(filename, images)

def conv_out_dim(in_planes, out_planes, in_height, in_width, kernel_size,
                 stride=1, padding=0, dilation=1):
    dilated_kernel = dilation * (kernel_size - 1)
    out_height = math.floor(
        (in_height + 2 * padding - dilated_kernel - 1) / stride + 1)
    out_width = math.floor(
        (in_width + 2 * padding - dilated_kernel - 1) / stride + 1)
    return out_height, out_width

def conv_in_dim(out_height, out_width, kernel_size,
                 stride=1, padding=0, dilation=1):
    dilated_kernel = dilation * (kernel_size - 1)
    # (out_height - 1) * stride = in_height + 2 * padding - dilated_kernel - 1
    in_height = math.ceil(
        (out_height - 1) * stride - 2 * padding + dilated_kernel + 1)
    in_width = math.ceil(
        (out_width - 1) * stride - 2 * padding + dilated_kernel + 1)
    return in_height, in_width

def conv_transpose_in_dim(out_height, out_width, kernel_size,
                          stride=1, padding=0, dilation=1):
    # dilated_kernel = dilation * (kernel_size - 1)
    dilated_kernel = kernel_size
    in_height = math.ceil(
        (out_height - dilated_kernel + 2 * padding) / stride + 1)
    in_width = math.ceil(
        (out_width - dilated_kernel + 2 * padding) / stride + 1)
    return in_height, in_width

def conv_transpose_out_dim(in_height, in_width, kernel_size,
                          stride=1, padding=0, dilation=1):
    # dilated_kernel = dilation * (kernel_size - 1)
    dilated_kernel = kernel_size
    out_height = math.ceil(
        (in_height - 1) * stride - 2 * padding + dilated_kernel)
    out_width = math.floor(
        (in_width - 1) * stride - 2 * padding + dilated_kernel)
    return out_height, out_width

def conv_list_out_dim(conv_layers, in_width, in_height):
    for layer in conv_layers:
        # import ipdb; ipdb.set_trace()
        if isinstance(layer, nn.Conv2d):
            in_height, in_width = conv_out_dim(layer.in_channels, layer.out_channels,
                    in_height, in_width, layer.kernel_size[0], layer.stride[0],
                    layer.padding[0], layer.dilation[0])
            last_channels = layer.out_channels
    return in_width, in_height, last_channels

def prod(l):
    return functools.reduce(lambda x, y: x * y, l)

def flat_str(x):
    x = x.cpu().detach().view([-1]).numpy()
    fmt_string = "{:+06.3f}\t" * len(x)
    return fmt_string.format(*x)


import pandas as pd
from sentence_transformers import SentenceTransformer
from sklearn.metrics.pairwise import cosine_similarity

from transformers import AutoTokenizer, AutoModel
import torch

from typing import List

from patent_phrase_similarity.data.analysis.visualize_datasets import plot_score_vs_test_score
from patent_phrase_similarity.data.transformation.cpc_datasets import Datasets, CPCDatasets

def get_similar_score_v1(model, context: str, similar_sentences: List[str]) -> List[float]:
    sentence_embeddings = model.encode([context] + similar_sentences)
    print("Sentences Shape", sentence_embeddings.shape)

    similarity_distance = cosine_similarity(
        [sentence_embeddings[0]],
        sentence_embeddings[1:]
    )[0]
    return similarity_distance

def get_similar_score_v2(tokenizer, model, context: str, similar_sentences: List[str]) -> List[float]:
    tokens = {'input_ids': [], 'attention_mask': []}

    _sentences = [context] + similar_sentences
    for sentence in sentences:
        # encode each sentence and append to dictionary
        new_tokens = tokenizer.encode_plus(sentence, max_length=128,
                                           truncation=True, padding='max_length',
                                           return_tensors='pt')
        tokens['input_ids'].append(new_tokens['input_ids'][0])
        tokens['attention_mask'].append(new_tokens['attention_mask'][0])

    # reformat list of tensors into single tensor
    tokens['input_ids'] = torch.stack(tokens['input_ids'])
    tokens['attention_mask'] = torch.stack(tokens['attention_mask'])

    outputs = model(**tokens)
    outputs.keys()

    embeddings = outputs.last_hidden_state

    attention_mask = tokens['attention_mask']
    print("Attention Mask Tensor", attention_mask.shape)

    mask = attention_mask.unsqueeze(-1).expand(embeddings.size()).float()
    # print(mask.shape)

    masked_embeddings = embeddings * mask

    # Then we sum the remained of the embeddings along axis 1:
    summed = torch.sum(masked_embeddings, 1)

    # Then sum the number of values that must be given attention in each position of the tensor:
    summed_mask = torch.clamp(mask.sum(1), min=1e-9)

    # Finally, we calculate the mean as the sum of the embedding activations summed
    # divided by the number of values that should be given attention in each position summed_mask:
    mean_pooled = summed / summed_mask

    # convert from PyTorch tensor to numpy array
    mean_pooled = mean_pooled.detach().numpy()

    # calculate
    similarity_distance = cosine_similarity(
        [mean_pooled[0]],
        mean_pooled[1:]
    )[0]

    return similarity_distance

if __name__ == '__main__':
    model_V1 = SentenceTransformer('bert-base-nli-mean-tokens')

    tokenizer = AutoTokenizer.from_pretrained('sentence-transformers/bert-base-nli-mean-tokens')
    model_v2 = AutoModel.from_pretrained('sentence-transformers/bert-base-nli-mean-tokens')
    sentences = [
        "Three years later, the coffin was still full of Jello.",
        "The fish dreamed of escaping the fishbowl and into the toilet where he saw his friend go.",
        "The person box was packed with jelly many dozens of months later.",
        "He found a leprechaun in his walnut shell."
    ]
    # similar_v1 = get_similar_score_v1(sentences[0], sentences[1:])
    # similar_v2 = get_similar_score_v2(sentences[0], sentences[1:])
    #
    # print(similar_v1)
    # print(similar_v2)

    # context = [
    #     'HUMAN NECESSITIES',
    #     'AGRICULTURE',
    #     'FORESTRY',
    #     'ANIMAL HUSBANDRY',
    #     'HUNTING',
    #     'TRAPPING',
    #     'FISHING',
    #     'SOIL WORKING IN AGRICULTURE OR FORESTRY',
    #     'PARTS, DETAILS, OR ACCESSORIES OF AGRICULTURAL MACHINES OR IMPLEMENTS, IN GENERAL ',
    #     'PLANTING',
    #     'SOWING',
    #     'FERTILISING ',
    #     'HARVESTING',
    #     'MOWING',
    #     'PROCESSING OF HARVESTED PRODUCE',
    #     'HAY OR STRAW PRESSES',
    #     'DEVICES FOR STORING AGRICULTURAL OR HORTICULTURAL PRODUCE ',
    #     'HORTICULTURE',
    #     'CULTIVATION OF VEGETABLES, FLOWERS, RICE, FRUIT, VINES, HOPS OR SEAWEED',
    #     'FORESTRY',
    #     'WATERING ',
    #     'NEW PLANTS OR ',
    #     ' PROCESSES FOR OBTAINING THEM',
    #     'PLANT REPRODUCTION BY TISSUE CULTURE TECHNIQUES',
    #     'MANUFACTURE OF DAIRY PRODUCTS ',
    #     'ANIMAL HUSBANDRY',
    #     'CARE OF BIRDS, FISHES, INSECTS',
    #     'FISHING',
    #     'REARING OR BREEDING ANIMALS, NOT OTHERWISE PROVIDED FOR',
    #     'NEW BREEDS OF ANIMALS',
    #     'SHOEING OF ANIMALS',
    #     'CATCHING, TRAPPING OR SCARING OF ANIMALS ',
    #     'APPARATUS FOR THE DESTRUCTION OF NOXIOUS ANIMALS OR NOXIOUS PLANTS',
    #     'PRESERVATION OF BODIES OF HUMANS OR ANIMALS OR PLANTS OR PARTS THEREOF ',
    #     'BIOCIDES, e.g. AS DISINFECTANTS, AS PESTICIDES OR AS HERBICIDES ',
    #     'PEST REPELLANTS OR ATTRACTANTS',
    #     'PLANT GROWTH REGULATORS'
    # ]
    #
    # similar_vector = get_similar_score_v1('\n'.join(context), ['panel', 'panel frame'])
    # print(similar_vector)
    # print("Difference:", 100 * abs(similar_vector[0] - similar_vector[1]), "%")
    #
    # similar_vector = get_similar_score_v1('\n'.join(context), ['distributor pipe', 'pipe'])
    # print(similar_vector)
    # print("Difference:", 100 * abs(similar_vector[0] - similar_vector[1]), "%")
    #
    # similar_vector = get_similar_score_v1('\n'.join(context), ['distributor pipe', 'liquid channels'])
    # print(similar_vector)
    # print("Difference:", 100 * abs(similar_vector[0] - similar_vector[1]), "%")
    #
    # similar_vector = get_similar_score_v1('\n'.join(context), ['distributor pipe', 'optical pipe'])
    # print(similar_vector)
    # print("Difference:", 100 * abs(similar_vector[0] - similar_vector[1]), "%")

    datasets = Datasets()
    cpc_datasets = CPCDatasets()

    train_df = datasets.get_train_df()
    cpc_train_df = cpc_datasets.merge_with_df(train_df)

    cpc_train_df['test_score'] = cpc_train_df.apply(lambda row: get_similar_score_v1(model_V1, row['anchor'], [row['target']])[0], axis=1)
    # similar_vector = get_similar_score_v1('distributor pipe', ['optical pipe'])
    # print(similar_vector)
    # print("Difference:", 100 * abs(similar_vector[0] - similar_vector[1]), "%")

    plot_score_vs_test_score(cpc_train_df, column_a='score', column_b='test_score')


class Solution(object):
    def buildTree(self, preorder, inorder):
        if not preorder or  not inorder:
            return  None

        # firt elementin  preorder is root,  found the index in preorder and separate them
        root = TreeNode(preorder[0])
        index = inorder.index(preorder[0])
        # length of left branch in preorder is 1(root) to index + 1,
        root.left = self.buildTree(preorder[1:index+1], inorder[:index])
        root.right = self.buildTree(preorder[index+1:], inorder[index+1:])
        return root


#Desafio 31
#Débora Janini
#Este desafio fiz com base em de duas colegas,
#aonde pude ver ferraemntas novas do python e entender

N = int(input())
array = list(map(int, input().split()))

menor = min(array) #min retorna o menor
posicao = array.index(menor) #index retorna o indice, então
#index do menor valor no array
print(f'Menor valor: {menor}')
print(f'Posicao: {posicao}')


## This module aims to analyze the effect of angle distribuiton
import numpy as np
import math as mt
import matplotlib.pyplot as plt
import Kinematics
import scipy.integrate as integrate
import scipy.optimize as opt

#Particle Property
#kpc
kpc_in_cm = 3.08567758e21
#light speed
vc = 3e10

#Neutrino
M_nu = 0.32 # Unit:ev/c2
E_total_nu = 3.6e53*6.24150913e11 #Total energy of neutrinos #Transfer 2e51erg to unit of MeV
E_per_nu = 10e6 #Mean energy of each neutrino #estimated value

#DM
M_DM = 1e03

#NFW Parameter
rho_s = 0.184e9
rs=24.42*kpc_in_cm

#cross section (Neutrino and DM)
cs = 1e-30

def angle_norm(beta,r,R):
    def f(psi):
        rp = (R**2+r**2-2*R*r*np.cos(psi))**0.5
        cos_theta_psi = ((R**2+(r*np.cos(psi))**2-2*R*r*np.cos(psi))/(R**2+r**2-2*R*r*np.cos(psi)))**0.5

        def g(psi):
            def theta(psi):
                return np.arctan(1/(1/(np.tan(psi))-r/(R*np.sin(psi))))

            theta = theta(psi)
            sec = 1/np.cos(theta)

            return 4*np.tan(theta)*(sec**2)*(1-beta*beta)/((sec**2-beta**2)**2)/np.sin(theta)
        return np.sin(psi)*g(psi)*cos_theta_psi/(rp**2)/2.

    theta_max = np.pi/2
    def psi(theta):
        return theta - np.arcsin(r/R*np.sin(theta))
    psi_max = psi(theta_max)
    return integrate.nquad(f, [[0,psi_max]])[0]

def DM_number(m_dm,e_per_nu,start,end,n_total):
    beta = (E_per_nu**2- M_nu**2)**0.5/(E_per_nu+M_DM)
    gamma = (1-beta**(2))**0.5
    time_delay = np.sum((start-end)**2)**0.5*(1/beta-1)/(vc)

    R = (np.sum((start-end)**2))**0.5
    l = end -start
    def f(r,theta):
        psi = theta - np.arcsin(r/R*np.sin(theta))
        dpsi_dtheta = 1- r/R*np.cos(theta) /(1-(r/R*np.sin(theta))**2)**0.5
        x=(np.sum((start + np.array([r*np.cos(psi),0,r*np.sin(psi)]))**2))**0.5/rs
        cos_theta_psi=((R**2+(r*np.cos(psi))**2-2*R*r*np.cos(psi))/(R**2+r**2-2*R*r*np.cos(psi)))**0.5
        theta = np.arctan(1/(1/(np.tan(psi))-r/(R*np.sin(psi))))
        sec = 1/np.cos(theta)
        dn_domega= (sec**3)*(1-beta*beta)/((sec**2-beta**2)**2)/np.pi

        return np.sin(psi) *dpsi_dtheta *R/(R**2+r**2-2*R*r*np.cos(psi))*dn_domega/(x*(1+x)*(1+x))

    k = n_total*rho_s*cs/m_dm/(4*np.pi)
    r0 = 0.01*rs
    result =integrate.dblquad(f, 0, np.pi/2., lambda theta: r0, lambda theta: R)
    print(result[1])
    L_dm = result[0]*2*np.pi*k/R
    print("DM Number(1/cm^2):"+str(L_dm))
    return L_dm

def DM_flux(m_dm,e_per_nu,start,end,n_total,t):
    beta = (E_per_nu**2- M_nu**2)**0.5/(E_per_nu+M_DM)
    a =(vc)*t
    #print(beta)
    gamma = (1-beta**(2))**0.5
    time_delay = np.sum((start-end)**2)**0.5*(1/beta-1)/(vc)
    R = (np.sum((start-end)**2))**0.5
    l = end -start
    def get_dtheta_dt(r,t):
        def get_theta():
            def f(theta):
                #v = vc *beta *((1-beta**2)/(np.cos(theta)**(-2)-beta**2))**0.5
                eta  = 2* np.arctan(np.tan(theta)/(1-beta**2)**0.5)
                root = ((1+np.cos(eta))**2 + (np.sin(eta)**2) *(1-beta**2))**0.5
                v = vc *beta *root/(1+beta**2*np.cos(eta))
                l = v*(t-r/vc)
                return l**2+ r**2 - R**2 + 2*r*l*np.cos(theta)
            sol = opt.fsolve(f, np.pi/4)
            return sol[0]
        theta = np.abs(get_theta())
        psi = theta - np.arcsin(r/R*np.sin(theta))
        eta  = 2* np.arctan(np.tan(theta)/(1-beta**2)**0.5)
        l = R*np.sin(psi)/np.sin(theta)
        #v = vc *beta *((1-beta**2)/(np.cos(theta)**(-2)-beta**2))**0.5
        eta  = 2* np.arctan(np.tan(theta)/(1-beta**2)**0.5)
        root = ((1+np.cos(eta))**2 + (np.sin(eta)**2) *(1-beta**2))**0.5

        v = vc *beta *root/(1+beta**2*np.cos(eta))
        sec = np.cos(theta)**(-1)
        dl_dtheta = r*np.sin(theta)-r**2*np.sin(2*theta)/((R**2-r**2*np.sin(theta)**2)**0.5)
        #dv_dtheta = -vc*beta*np.sin(eta/2.)/2. *2*sec**2*(1-beta*beta)**0.5/(sec**2-beta**2)
        d_eta_dtheta = 2*sec**2*(1-beta*beta)**0.5/(sec**2-beta**2)

        eba = (1+beta**2*np.cos(eta))
        dv_dtheta = vc*beta *d_eta_dtheta* (  root*(beta**2*np.sin(eta)) - eba/root*(np.sin(eta)+beta**2*np.sin(eta)*np.cos(eta))  )/eba**2

        dt_dtheta = dl_dtheta/v -l/(v**2)*dv_dtheta

        return 1/dt_dtheta, theta, psi

    def f(r):
        dtheta_dt, theta, psi = get_dtheta_dt(r,t)
        dpsi_dtheta = 1- r/R*np.cos(theta) /(1-(r/R*np.sin(theta))**2)**0.5
        x=(np.sum((start + np.array([r*np.cos(psi),0,r*np.sin(psi)]))**2))**0.5/rs
        cos_theta_psi=((R**2+(r*np.cos(psi))**2-2*R*r*np.cos(psi))/(R**2+r**2-2*R*r*np.cos(psi)))**0.5

        sec = 1/np.cos(theta)
        dn_domega= (sec**3)*(1-beta*beta)/((sec**2-beta**2)**2)/np.pi

        return np.sin(psi) *dpsi_dtheta *R/(R**2+r**2-2*R*r*np.cos(psi))*dn_domega/(x*(1+x)*(1+x)) *dtheta_dt

    k = n_total*rho_s*cs/m_dm/(4*np.pi)
    r0 = 0.01*rs
    result = integrate.quad(f,r0,R)[0]
    if result<0:
        return 0
    L_dm = result*2*np.pi*k/R
    return L_dm

def DM_number_original(m_dm,e_per_nu,start,end,n_total):
    beta = (E_per_nu**2- M_nu**2)**0.5/(E_per_nu+M_DM)
    gamma = (1-beta**(2))**0.5
    time_delay = np.sum((start-end)**2)**0.5*(1/beta-1)/(vc)

    R = (np.sum((start-end)**2))**0.5
    l = end -start
    def f(t):
        r=(np.sum((start+l*t)**2))**0.5
        x= r/rs
        return 1/(x*(1+x)*(1+x))
    k = n_total*rho_s*cs/m_dm/(4*np.pi) /R
    r0 = 0.01*rs/R
    L_dm = integrate.nquad(f, [[r0,1.]])[0]*k
    print("DM Number original(1/cm^2):"+str(L_dm))
    return  L_dm

def Spectrum(m_dm,e_per_nu,start,end,n_total):
    beta = (E_per_nu**2- M_nu**2)**0.5/(E_per_nu+M_DM)
    gamma = (1-beta**(2))**0.5
    time_delay = np.sum((start-end)**2)**0.5*(1/beta-1)/(vc)

    R = (np.sum((start-end)**2))**0.5
    l = end -start
    def dL_dEdR(r,theta):

        dE_dtheta = M_DM *(beta**2)*np.sin(theta)/(1-beta**2)
        def f(r):
            psi = theta - np.arcsin(r/R*np.sin(theta))
            x=(np.sum((start + np.array([r*np.cos(psi),0,r*np.sin(psi)]))**2))**0.5/rs
            cos_theta_psi= np.cos(theta-psi)
            sec = 1/np.cos(theta)
            dpsi_dtheta = 1- r/R*np.cos(theta) /(1-(r/R*np.sin(theta))**2)**0.5
            dn_domega= (sec**3)*(1-beta*beta)/((sec**2-beta**2)**2)/np.pi

            return np.sin(psi)*cos_theta_psi*R /(R**2+r**2-2*R*r*np.cos(psi))*dn_domega*dpsi_dtheta/(x*(1+x)*(1+x))
        return  f(r)

    E_0 = M_DM*1.001
    E_f = M_DM/(1-beta**2)*(1+(beta**2))*0.999

    norm = integrate.dblquad(dL_dEdR, 0, np.pi/2, lambda theta: 0, lambda theta: R)[0]*2*np.pi
    print(norm)
    def dL_dE(theta):

        sec = 1/np.cos(theta)
        dE_dtheta = M_DM *(beta**2)/(1-beta**2) *4*(gamma**2)*np.tan(theta)*(sec**2) /(1+(gamma**2)*(np.tan(theta)**2))
        def f(r):
            psi = theta - np.arcsin(r/R*np.sin(theta))
            x=(np.sum((start + np.array([r*np.cos(psi),0,r*np.sin(psi)]))**2))**0.5/rs
            cos_theta_psi= np.cos(theta-psi)
            sec = 1/np.cos(theta)
            dpsi_dtheta = 1- r/R*np.cos(theta) /(1-(r/R*np.sin(theta))**2)**0.5
            dn_domega= (sec**3)*(1-beta*beta)/((sec**2-beta**2)**2)/np.pi

            return np.sin(psi)*cos_theta_psi*R /(R**2+r**2-2*R*r*np.cos(psi))*dn_domega*dpsi_dtheta/(x*(1+x)*(1+x))
        return  integrate.nquad(f, [[0.01*R,R]])[0]  /dE_dtheta

    theta =np.linspace(0.001,np.pi/2,1000)
    E = [M_DM/(1-beta**2)*(1+(beta**2)*(1-(gamma**2)*(np.tan(theta[i])**2)) /(1+(gamma**2)*(np.tan(theta[i])**2)))for i in range(0,1000)]

    spec = [dL_dE(theta[i])/norm for i in range(0,1000)]

    plt.plot(E, spec, color ='blue')
    plt.xlabel('E(eV)')
    plt.ylabel('dL_chi/dE(1/cm**2 eV)')

    plt.show()

if __name__== '__main__':

    beta = (E_per_nu**2- M_nu**2)**0.5/(E_per_nu+M_DM)
    gamma = (1-beta**(2))**0.5
    print(beta)
    print("Angle Norm:"+str(angle_norm(beta,0.5,1)))

    start=np.array([8.7*0.0*kpc_in_cm,0,0.*3.08567758e18])
    end =np.array([8.7*kpc_in_cm,0,0.*3.08567758e18])

    ref = DM_number(M_DM,E_per_nu ,start,end,E_total_nu/E_per_nu)

    t0 = kpc_in_cm/(vc)

    mode = 1
    if mode==0:
        N = 100
        s = np.linspace(-3,-0.5,100)
        #t = [8.7*(0.99+10**(s[i]))*t0 for i in range(len(s))]

        t = np.linspace(8.7*(0.99+9e-3),8.7*(0.99+1e-2),N)*t0
        flux = [DM_flux(M_DM,E_per_nu ,start,end,E_total_nu/E_per_nu,t[i]) for i in range(len(t))]

        t2 = np.linspace(8.7*(0.99+1e-2),8.7*(0.99+1e-1),N)*t0
        flux2 = [DM_flux(M_DM,E_per_nu ,start,end,E_total_nu/E_per_nu,t2[i]) for i in range(len(t))]

        t3 = np.linspace(8.7*(0.99+1e-1),8.7*(0.99+1e-0),N)*t0
        flux3 = [DM_flux(M_DM,E_per_nu ,start,end,E_total_nu/E_per_nu,t3[i]) for i in range(len(t))]
        #ref = DM_number_original(M_DM,E_per_nu ,start,end,E_total_nu/E_per_nu)

        inter = [(flux[i+1]+flux[i])/2*(t[i+1]-t[i])for i in range(len(t)-1)]
        inter2 = [(flux2[i+1]+flux2[i])/2*(t2[i+1]-t2[i])for i in range(len(t)-1)]
        inter3 = [(flux3[i+1]+flux3[i])/2*(t3[i+1]-t3[i])for i in range(len(t)-1)]

        t=np.concatenate((t, t2), axis=None)
        t=np.concatenate((t, t3), axis=None)
        flux=np.concatenate((flux, flux2), axis=None)
        flux=np.concatenate((flux, flux3), axis=None)
        print("ratio:"+str(np.sum(inter+inter2+inter3)/ref))
        plt.plot(t,flux)
        plt.xscale('log')
        plt.yscale('log')
        plt.show()
    elif mode==1:
        s = np.linspace(-8,-4,100)
        r0 = 0.01*rs
        delta_t = 8.7*t0 #- r0/vc
        t = [ delta_t+ 8.7*(10**(s[i]))*t0 for i in range(len(s))]
        flux = [DM_flux(M_DM,E_per_nu ,start,end,E_total_nu/E_per_nu,t[i]) for i in range(len(t))]
        plt.plot(t-delta_t*np.ones(len(t)),flux)
        plt.xscale('log')
        plt.yscale('log')
        plt.xlabel('t(s)')
        plt.ylabel('Flux (#/s/cm^2)')

        plt.show()
        inter = [(flux[i+1]+flux[i])/2*(t[i+1]-t[i])for i in range(len(t)-1)]
        print("ratio:"+str(np.sum(inter)/ref))


# %% preliminaries
import sys, os

from pylab import *
from treefarm import *
from treefarm.minimizers.flatgp import FlatGPMinimizer, expected_improvement
from treefarm.core.utils import get_minium_states
from treefarm.core.space_utils import get_subspace, to_space
from time import sleep
import GPy

kernel_dict = {
    'RBF' : GPy.kern.RBF,
    'EXP' : GPy.kern.Exponential,
    'BIAS': GPy.kern.Bias,
    'LINEAR' : GPy.kern.Linear,
}

K = convert(set(kernel_dict.keys()))
K.symbol = 'K'
K = op(kernel_dict.get)(K)(1)

G = join()
G <<= K+G | K*G | K
G = simplify(G)

if os.path.exists('wild_kernel_names.npy'):
    names = list(np.load('wild_kernel_names.npy'))
else:
    names = []

if os.path.exists('wild_kernel_search.npy'):
    perf_stor = list(np.load('wild_kernel_search.npy'))
else:
    perf_stor = []

def str_deep(kern):
    try :
        L = [str_deep(k) for k in kern.parts]
        out = kern.name + '(' + ','.join(L) + ')'
    except:
        out = kern.name
    return out

@operation
def test_kernel(kernel):

    def f(x):
        return sin(x) * x / 2 + x**2 / 20 - 10*exp(-(x - 10)**2) + 8

    search_space = op(f)(R[-1000:1000])

    print('test kernel:', str_deep(kernel))

    outer_iterations = 10
    for i in range(outer_iterations):
        print('iteration', i, end='')

        obj = minimize(
            search_space = search_space,
            max_iter = 30,
            minimizer = FlatGPMinimizer(search_space, kernel=kernel),
            )
        obj.run()
        if 'min_perfs' not in locals():
            min_perfs = np.array(get_minium_states(obj.minimizer.protocol))
        else:
            min_perfs += np.array(get_minium_states(obj.minimizer.protocol))
        print(':', min_perfs[-1]/(i+1))

    out = min_perfs / outer_iterations
    perf_stor.append(out)
    names.append(str_deep(kernel))
    return out[-1]

kernel_ss = test_kernel(G)

min_obj = minimize(kernel_ss, max_iter=10)

#min_obj.run()

def plot_and_dump():
    _perf_stor = np.array(perf_stor)
    _perf_stor.dump('wild_kernel_search.npy')
    np.array(names).dump('wild_kernel_names.npy')

    # %%
    figure("Performances")
    for k, mperfs in zip(names, _perf_stor):
        plot(mperfs, label=str(k))
    legend()

    figure("log-Performances")
    for k, mperfs in zip(names, _perf_stor):
        plot(np.log(mperfs), label=str(k))
    legend()
    show()


from hypothesis import given, assume, strategies as st
from quadratic import quadratic
import cmath

@given(a = st.floats(min_value=-10000, max_value=10000),
       b = st.floats(min_value=-10000, max_value=10000),
       c = st.floats(min_value=-10000, max_value=10000))
def test_quad(a, b, c):
    assume(abs(a) >= 0.0001)
    x1, x2 = quadratic(a, b, c)
    assert cmath.isclose(a*x1**2 + b*x1 + c, 0.0, abs_tol=0.0001)
    assert cmath.isclose(a*x1**2 + b*x1 + c, 0.0, abs_tol=0.0001)

if __name__ == '__main__':

    test_quad()


# Copyright (C) 2020-2021  Burak Martin (see 'AUTHOR' for full notice)

"""
Enable/disable parallelism, caching and nogil. The program needs to be restarted to take effect since these options
only effect numba functions which need to be recompiled.
"""

parallel = True
cache = True
nogil = True


load("@obazl_rules_ocaml//ocaml:providers.bzl", "BuildConfig", "OpamConfig")

opam_pkgs = {
    "ocaml": ">= 4.04.0",
    "dune": ">=  1.2.0",
    "ounit": "with-test & >=  1.0.2",
    "ppx_sexp_conv": "with-test & >=  v0.9.0",
    "stringext": ["1.4.0"],
    "angstrom": ["0.14.0"],
}

opam = OpamConfig(
    version = "2.0",
    builds = {
        "4.12": BuildConfig(
            default = True,
            switch = "4.12",
            compiler = "4.12",
            packages = opam_pkgs,
            install = True,
        ),
    },
)


def gcd(n1,n2):
    while n2 >0:
        n1,n2 = n2 , n1%n2
    return n1

def solution(denum1, num1, denum2, num2):
    # 1. 두 분수의 합 계산
    boonmo = num1 * num2
    boonja = denum1 * num2 + denum2 * num1

    # 2. 최대공약수 계산
    gcd_value = gcd(boonmo, boonja)

    # 3. gcd 로 나눈 값을 answer에 담기
    answer = [boonja / gcd_value, boonmo / gcd_value]
    return answer

프로그래머스/lv0/120808. 분수의 덧셈/분수의 덧셈.py


import torch
from torch import nn
import torch.nn.functional as F

from utils import gelu, LayerNorm
from transformer import TransformerLayer, Embedding, LearnedPositionalEmbedding, SelfAttentionMask
from label_smoothing import LabelSmoothing

class BIGLM(nn.Module):
    def __init__(self, local_rank, vocab, embed_dim, ff_embed_dim, num_heads, dropout, layers, smoothing_factor, approx=None):
        super(BIGLM, self).__init__()
        self.vocab = vocab
        self.embed_dim = embed_dim

        self.tok_embed = Embedding(self.vocab.size, embed_dim, self.vocab.padding_idx)
        self.pos_embed = LearnedPositionalEmbedding(embed_dim, device=local_rank)

        self.layers = nn.ModuleList()
        for i in range(layers):
            self.layers.append(TransformerLayer(embed_dim, ff_embed_dim, num_heads, dropout, with_external=True))
        self.emb_layer_norm = LayerNorm(embed_dim)
        self.one_more = nn.Linear(embed_dim, embed_dim)
        self.one_more_layer_norm = LayerNorm(embed_dim)
        self.out_proj = nn.Linear(embed_dim, self.vocab.size)

        self.attn_mask = SelfAttentionMask(device=local_rank)
        self.smoothing = LabelSmoothing(local_rank, self.vocab.size, self.vocab.padding_idx, smoothing_factor)

        self.dropout = dropout
        self.device = local_rank

        self.approx = approx
        self.reset_parameters()

    def reset_parameters(self):
        nn.init.constant_(self.one_more.bias, 0.)
        nn.init.normal_(self.one_more.weight, std=0.02)
        nn.init.constant_(self.out_proj.bias, 0.)
        nn.init.normal_(self.out_proj.weight, std=0.02)

    def label_smotthing_loss(self, y_pred, y, y_mask, avg=True):
        seq_len, bsz = y.size()

        y_pred = torch.log(y_pred.clamp(min=1e-8))
        loss = self.smoothing(y_pred.view(seq_len * bsz, -1), y.view(seq_len * bsz, -1))
        if avg:
            return loss / torch.sum(y_mask)
        else:
            return loss / bsz

    def nll_loss(self, y_pred, y, y_mask, avg=True):
        cost = -torch.log(torch.gather(y_pred, 2, y.view(y.size(0), y.size(1), 1)))
        cost = cost.view(y.shape)
        y_mask = y_mask.view(y.shape)
        if avg:
            cost = torch.sum(cost * y_mask, 0) / torch.sum(y_mask, 0)
        else:
            cost = torch.sum(cost * y_mask, 0)
        cost = cost.view((y.size(1), -1))
        ppl = 2 ** cost
        return cost.sum().item(), ppl.sum().item()

    def work_incremental(self, enc, src_padding_mask, ys_inp, ys_tpl, ys_seg, ys_pos, incremental_state=None):
        seq_len, bsz = ys_inp.size()
        x = self.tok_embed(ys_inp) + self.pos_embed(ys_inp) + self.tok_embed(ys_tpl) + self.tok_embed(ys_seg) + self.tok_embed(ys_pos)
        x = self.emb_layer_norm(x)
        padding_mask = torch.eq(ys_inp, self.vocab.padding_idx)
        if not padding_mask.any():
            padding_mask = None

        if incremental_state is None:
            self_attn_mask = self.attn_mask(seq_len)
            incremental_state = {}
        else:
            x = x[-1, :, :].unsqueeze(0)
            self_attn_mask = None

        for layer in self.layers:
            x, _ ,_ = layer.work_incremental(x, self_padding_mask=padding_mask, \
                                             self_attn_mask=self_attn_mask, \
                                             external_memories = enc, \
                                             external_padding_mask = src_padding_mask, \
                                             incremental_state = incremental_state)

        x = self.one_more_layer_norm(gelu(self.one_more(x)))
        probs = torch.softmax(self.out_proj(x), -1)

        _, pred_y = probs.max(-1)
        return probs, pred_y, incremental_state

    def work(self, enc, src_padding_mask, ys_inp, ys_tpl, ys_seg, ys_pos):
        seq_len, bsz = ys_inp.size()
        self_attn_mask = self.attn_mask(seq_len)
        x = self.tok_embed(ys_inp) + self.pos_embed(ys_inp) + self.tok_embed(ys_tpl) + self.tok_embed(ys_seg) + self.tok_embed(ys_pos)
        x = self.emb_layer_norm(x)
        x = F.dropout(x, p=self.dropout, training=self.training)
        padding_mask = torch.eq(ys_inp, self.vocab.padding_idx)
        if not padding_mask.any():
            padding_mask = None
        for layer in self.layers:
            x, _ ,_ = layer(x, self_padding_mask=padding_mask, \
                               self_attn_mask = self_attn_mask, \
                               external_memories = enc, \
                               external_padding_mask = src_padding_mask,)

        x = self.one_more_layer_norm(gelu(self.one_more(x)))
        probs = torch.softmax(self.out_proj(x), -1)

        _, pred_y = probs.max(-1)

        return probs, pred_y

    def encode(self, xs_tpl, xs_seg, xs_pos):
        padding_mask = torch.eq(xs_tpl, self.vocab.padding_idx)
        x = self.tok_embed(xs_tpl)  + self.tok_embed(xs_seg) + self.tok_embed(xs_pos)
        x = self.emb_layer_norm(x)
        return x, padding_mask

    def ppl(self, xs_tpl, xs_seg, xs_pos, ys_truth, ys_inp, ys_tpl, ys_seg, ys_pos, msk):
        enc, src_padding_mask = self.encode(xs_tpl, xs_seg, xs_pos)
        seq_len, bsz = ys_inp.size()
        self_attn_mask = self.attn_mask(seq_len)
        x = self.tok_embed(ys_inp) + self.pos_embed(ys_inp) + self.tok_embed(ys_tpl) + self.tok_embed(ys_seg) + self.tok_embed(ys_pos)
        x = self.emb_layer_norm(x)
        x = F.dropout(x, p=self.dropout, training=self.training)
        padding_mask = torch.eq(ys_truth, self.vocab.padding_idx)
        if not padding_mask.any():
            padding_mask = None
        for layer in self.layers:
            x, _ ,_ = layer(x, self_padding_mask=padding_mask, \
                               self_attn_mask = self_attn_mask, \
                               external_memories = enc, \
                               external_padding_mask = src_padding_mask,)

        x = self.one_more_layer_norm(gelu(self.one_more(x)))
        pred = torch.softmax(self.out_proj(x), -1)
        nll, ppl = self.nll_loss(pred, ys_truth, msk)
        return nll, ppl, bsz

    def forward(self, xs_tpl, xs_seg, xs_pos, ys_truth, ys_inp, ys_tpl, ys_seg, ys_pos, msk):
        enc, src_padding_mask = self.encode(xs_tpl, xs_seg, xs_pos)
        seq_len, bsz = ys_inp.size()
        self_attn_mask = self.attn_mask(seq_len)
        x = self.tok_embed(ys_inp) + self.pos_embed(ys_inp) + self.tok_embed(ys_tpl) + self.tok_embed(ys_seg) + self.tok_embed(ys_pos)
        x = self.emb_layer_norm(x)
        x = F.dropout(x, p=self.dropout, training=self.training)
        padding_mask = torch.eq(ys_truth, self.vocab.padding_idx)
        if not padding_mask.any():
            padding_mask = None
        for layer in self.layers:
            x, _ ,_ = layer(x, self_padding_mask=padding_mask, \
                               self_attn_mask = self_attn_mask, \
                               external_memories = enc, \
                               external_padding_mask = src_padding_mask,)

        x = self.one_more_layer_norm(gelu(self.one_more(x)))
        pred = torch.softmax(self.out_proj(x), -1)

        loss = self.label_smotthing_loss(pred, ys_truth, msk)

        _, pred_y = pred.max(-1)
        tot_tokens = msk.float().sum().item()
        acc = (torch.eq(pred_y, ys_truth).float() * msk).sum().item()

        nll, ppl = self.nll_loss(pred, ys_truth, msk)
        return (pred_y, ys_truth), loss, acc, nll, ppl, tot_tokens, bsz


import requests
from lxml import etree
import json
from pyecharts import Map  # 0.1.9.4

class nCoV_2019:
    def __init__(self):
        self.headers = {
            "User-Agent": "Mozilla/5.0 (iPhone; CPU iPhone OS 13_2_3 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/13.0.3 Mobile/15E148 Safari/604.1"
        }
        self.url = "https://ncov.dxy.cn/ncovh5/view/pneumonia_peopleapp"

    def parse_url(self):
        # 发送get请求网页
        r = requests.get(url=self.url, headers=self.headers)
        # 我们用断言来判断他的状态码手否为200，如果不是200则会报错
        assert r.status_code == 200
        # 这里是要用xpath 来提取我想要的信息
        html = etree.HTML(r.content.decode())
        # 获取id为getListByCountryTypeService1 script标签里的数据
        # 通过split函数以'}'分割成一个列表
        # html.xpath('//*[@id="getListByCountryTypeService1"]//text()')[0] 本身列表只有一个数据 类型为str 我只要取出来 我就能用字符串函数
        results = html.xpath('//*[@id="getListByCountryTypeService1"]//text()')[0].split('}')[:-3]
        return results

    # 拿到数据后观察数据
    # 1.我们要把无关的字符删除，
    # 2.我们用data_dict存取每个省份的数据 确诊 死亡 治愈 三个字段

    def getDataList(self, results):
        data_list = []
        for result in results:
            # 申明一个字典，存放数据，一个循环存放完，入data_list里，在清空，相当于一个临时存储变量
            data_dict = {}
            # 修改第一条数据
            if results.index(result) == 0:
                # replace(old,new)
                result = result.replace('try { window.getListByCountryTypeService1 = [', '')
            # 去除开头多的',' 并且将str类型的一个'字典'  转换成一个真正的字典
            result = json.loads(result.lstrip(',') + '}')
            # 省份
            data_dict['provinceShortName'] = result['provinceShortName']
            # 确诊人数
            data_dict['confirmedCount'] = result['confirmedCount']
            # 死亡人数
            data_dict['deadCount'] = result['deadCount']
            # 治愈人数
            data_dict['curedCount'] = result['curedCount']
            data_list.append(data_dict)
        return data_list

    def main(self):
        results = self.parse_url()
        data_list = self.getDataList(results)
        return data_list

nCoV_2019 = nCoV_2019()
data_list = nCoV_2019.main()
# 省份列表
provinceShortName_list = []
# 确诊人数列表
confirmedCount_list = []
# 死亡人数列表
deadCount_list = []
# 治愈人数列表
curedCount_list = []
# 列表赋值
for i in data_list:
    provinceShortName_list.append(i['provinceShortName'])
    confirmedCount_list.append(i['confirmedCount'])
    deadCount_list.append(i['deadCount'])
    curedCount_list.append(i['curedCount'])

# 画图
map = Map("中国疫情分布图", '', width=1980, height=1024, title_text_size=35)
# is_label_show 显示每个店 is_visualmap 显示颜色以及注释 maptype地区
map.add("", provinceShortName_list, confirmedCount_list, visual_range=[0, 1000], maptype='china', is_visualmap=True,
        visual_text_color='#000', is_label_show=True)
map.show_config()
map.render(path='./中国疫情图.html')


"""
The directories module: Provides paths to all directories used in the
package.

This module helps with the relative paths of the directories in this
package. It helps with overcoming the hassle of re-writing & hardcoding
paths used for reference.

At a glance, the structure of the module is following:
 - ai_dir{}:            Dictionary of all the important directories used
                        in the package.
 - local_dir{}:         Dictionary of all directories in `D:/` drive.

See https://github.com/xames3/charlotte for cloning the repository.
"""
#   History:
#
#   < Checkout my github repo for history and latest stable build >
#
#   1.1.1 - Improved the type hints by using the typing module.
#           Made the code more* PEP-8 compliant.
#           Updated paths as per new configuration.
#   1.1.0 - Stories are now part of `./data/stories/` directory.
#   1.0.0 - First code.

from os.path import join
from pathlib import Path
from typing import Text
from win32api import GetLogicalDriveStrings

PARENT = Path.cwd()

def _drives(drive_letter: Text) -> Text:
    """Returns drive letter.

    drive_letter: Drive letter to be searched for.

    Returns the drive letter from all the valid and present partitions.
    This assures that the user does not use any drive letter which is
    not present on the system.
    """
    partitions = GetLogicalDriveStrings().split('\000')[:-1]
    drive = {}
    try:
        for index in range(len(partitions)):
            keys = (Path(partitions[index]).parts[0].split(':\\')[0]).lower()
            values = partitions[index]
            drive[keys] = values
        return drive[drive_letter[0].lower()]
    except KeyError as error:
        missing_drive = str(error).strip('\'')
        print(f'Could not find {missing_drive.title()}:\\ drive.')

ai_dir = {
    'data': PARENT/'data/',
    'logs': PARENT/'logs',
    'models': PARENT/'models',
    'backup': PARENT/'backup',
    'temp': PARENT/'temp',
    'tests': PARENT/'tests',
    'utils': PARENT/'utils',
    'actions': PARENT/'utils/actions',
    'assists': PARENT/'utils/assists',
    'knowledge': PARENT/'data/knowledge',
    'stories': PARENT/'data/stories',
    'csv': PARENT/'data/knowledge/csv'
}

local_dir = {
    'bittorrent': join(_drives('d'), 'Bittorrents'),
    'documents': join(_drives('d'), 'Documents'),
    'films': join(_drives('d'), 'Films'),
    'photos': join(_drives('d'), 'Photos'),
    'music': join(_drives('d'), 'Music'),
    'xa': join(_drives('d'), 'XA'),
    'videos': join(_drives('d'), 'Videos'),
    'web': join(_drives('d'), 'Web')
}