__copyright__ = "Copyright 2020, 3Liz"
__license__ = "GPL version 3"
__email__ = "info@3liz.org"
__revision__ = "$Format:%H$"

from functools import partial

from qgis.PyQt import (
    QtWidgets,
)
from qgis.PyQt.QtWidgets import (
    QPushButton,
)
from qgis.core import (
    Qgis,
)

from webbrowser import open_new
from processing import execAlgorithmDialog
from lizsync.qgis_plugin_tools.tools.i18n import tr
from lizsync.qgis_plugin_tools.tools.resources import load_ui, plugin_name

FORM_CLASS = load_ui('lizsync_dockwidget_base.ui')

class LizsyncDockWidget(QtWidgets.QDockWidget, FORM_CLASS):

    def __init__(self, iface, parent=None):
        """Constructor."""
        super().__init__(parent)

        self.iface = iface
        self.setupUi(self)

        # Buttons directly linked to an algorithm
        self.algorithms = [
            'create_database_structure',
            'upgrade_database_structure',
            'initialize_central_database',

            'deploy_database_server_package',
            'package_central_database',
            'synchronize_database',

            'build_mobile_project',
            'send_projects_and_files_to_clone_ftp',

            'package_all',
            'deploy_all',
        ]
        for alg in self.algorithms:
            button = self.findChild(QPushButton, 'button_{0}'.format(alg))
            if not button:
                continue
            button.clicked.connect(partial(self.runAlgorithm, alg))

        # Buttons not linked to algs
        #
        # Help on database
        button = self.findChild(QPushButton, 'button_help_database')
        if button:
            button.clicked.connect(self.help_database)

    def runAlgorithm(self, name):

        if name not in self.algorithms:
            self.iface.messageBar().pushMessage(
                tr("Error"),
                tr("This algorithm cannot be found") + ' {}'.format(name),
                level=Qgis.Critical
            )
            return

        # Run alg
        param = {}
        alg_name = 'lizsync:{0}'.format(name)
        execAlgorithmDialog(alg_name, param)

    @staticmethod
    def help_database():
        """
        Display the help on database structure
        """
        name = plugin_name().lower()
        open_new(r'https://3liz.github.io/qgis-%s-plugin/' % name)


from argparse import ArgumentParser
from script.oci import OCIManager, Citation
from requests import get
from json import loads, load
from re import sub, findall
from urllib.parse import unquote, quote
from datetime import datetime
from csv import DictReader, DictWriter
from os.path import isdir, exists
from os import walk, sep, makedirs

HTTP_HEADERS = {"User-Agent": "CROCI / Create New Citations (via OpenCitations - "
                              "http://opencitations.net; mailto:contact@opencitations.net)"}
BASE_URL = "http://dx.doi.org/"
CROCI_BASE = "https://w3id.org/oc/index/croci/"

class DOIManager(object):
    def __init__(self):
        self.api = "https://doi.org/api/handles/"

    def normalize(self, doi_entity):
        try:
            doi_string = sub("\s+", "", unquote(doi_entity[doi_entity.index("10."):]))
            return doi_string.lower().strip()
        except:  # Any error in processing the DOI will return None
            return None

    def call_doi(self, doi_entity):
        doi = self.normalize(doi_entity)
        r = get(self.api + quote(doi), headers=HTTP_HEADERS, timeout=30)
        if r.status_code == 200:
            r.encoding = "utf-8"
            json_res = loads(r.text)
            return json_res.get("responseCode")

    def is_valid(self, doi_entity):
        result = self.call_doi(doi_entity)
        return result == 1

class DataCiteManager(object):
    def __init__(self):
        self.date = {}
        self.api = "https://api.datacite.org/works/%s"
        self.dm = DOIManager()

    def call_datacite(self, doi_entity):
        doi = self.dm.normalize(doi_entity)
        r = get(self.api + quote(doi), headers=HTTP_HEADERS, timeout=30)
        if r.status_code == 200:
            r.encoding = "utf-8"
            json_res = loads(r.text)
            return json_res

    def __get_date(self, json_obj):
        return json_obj.get("published")

    def __retrive_all(self, doi):
        json_obj = self.call_datacite(doi)
        if json_obj.get("data") and json_obj["data"].get("attributes"):
            self.date[doi] = self.__get_date(json_obj["data"]["attributes"])

    def __get_item(self, doi_entity, c):
        doi = self.dm.normalize(doi_entity)
        if doi not in c:
            json_obj = self.call_datacite(doi)
            self.date[doi] = self.__get_date(json_obj["data"]["attributes"])
        return c.get(doi)

    def get_date(self, doi_entity):
        return self.__get_item(doi_entity, self.date)

class CrossrefManager(object):
    def __init__(self):
        self.issn = {}
        self.date = {}
        self.orcid = {}
        self.api = "https://api.crossref.org/works/%s"
        self.dm = DOIManager()

    def call_crossref(self, doi_entity):
        doi = self.dm.normalize(doi_entity)
        r = get(self.api + quote(doi), headers=HTTP_HEADERS, timeout=30)
        if r.status_code == 200:
            r.encoding = "utf-8"
            json_res = loads(r.text)
            return json_res.get("message")

    @staticmethod
    def contains(obj, key, value):
        field = None
        if obj:
            field = obj.get(key)
        return field and value in field

    def __get_orcid(self, json_obj):
        result = []
        if json_obj:
            authors = json_obj.get("author")
            if authors:
                for author in authors:
                    orcid = author.get("ORCID")
                    if orcid:
                        orcid = findall("....-....-....-....", orcid)
                        if orcid:
                            result.append(orcid[0])
        return result

    def __get_issn(self, json_obj):
        result = []
        if CrossrefManager.contains(json_obj, "type", "journal"):
            issns = json_obj["ISSN"]
            if issns:
                for issn in issns:
                    norm_issn = sub("\W", "", issn).upper()
                    result.append(norm_issn)
        return result

    def __get_date(self, json_obj):
        if json_obj:
            date = json_obj.get("issued")
            if date:
                date_list = date["date-parts"][0]
                if date_list is not None:
                    l_date_list = len(date_list)
                    if l_date_list != 0 and date_list[0] is not None:
                        if l_date_list == 3 and \
                                ((date_list[1] is not None and date_list[1] != 1) or
                                 (date_list[2] is not None and date_list[2] != 1)):
                            result = datetime(date_list[0], date_list[1], date_list[2], 0, 0).strftime('%Y-%m-%d')
                        elif l_date_list == 2 and date_list[1] is not None:
                            result = datetime(date_list[0], date_list[1], 1, 0, 0).strftime('%Y-%m')
                        else:
                            result = datetime(date_list[0], 1, 1, 0, 0).strftime('%Y')
                        return result

    def get_date(self, doi_entity):
        return self.__get_item(doi_entity, self.date)

    def get_issn(self, doi_entity):
        return self.__get_item(doi_entity, self.issn)

    def get_orcid(self, doi_entity):
        return self.__get_item(doi_entity, self.orcid)

    def __get_item(self, doi_entity, c):
        doi = self.dm.normalize(doi_entity)
        if doi not in c:
            json_obj = self.call_crossref(doi)
            self.issn[doi] = self.__get_issn(json_obj)
            self.date[doi] = self.__get_date(json_obj)
            self.orcid[doi] = self.__get_orcid(json_obj)
        return c.get(doi)

    def share_issn(self, doi_entity_1, doi_entity_2):
        result = False

        doi_entity_1_issns = self.get_issn(doi_entity_1)
        doi_entity_2_issns = self.get_issn(doi_entity_2)
        while not result and doi_entity_1_issns:
            result = doi_entity_1_issns.pop(0) in doi_entity_2_issns

        return result

    def share_orcid(self, doi_entity_1, doi_entity_2):
        result = False

        doi_entity_1_orcid = self.get_orcid(doi_entity_1)
        doi_entity_2_orcid = self.get_orcid(doi_entity_2)
        while not result and doi_entity_1_orcid:
            result = doi_entity_1_orcid.pop(0) in doi_entity_2_orcid

        return result

class ORCIDManager(object):
    def __init__(self, key, m_list=[]):
        self.orcid = {}
        self.api = "https://pub.orcid.org/v2.1/search?q="
        self.dm = DOIManager()
        self.header = {"Content-Type": "application/json"}
        if key:
            self.header["Authorization"] = "Bearer %s" % key
        self.header.update(HTTP_HEADERS)
        self.m_list = m_list

    def call_orcid(self, doi_entity):
        doi = self.dm.normalize(doi_entity)
        r = get(self.api + quote("doi-self:\"%s\" OR doi-self:\"%s\"" % (doi, doi.upper())),
                headers=self.header, timeout=30)
        if r.status_code == 200:
            r.encoding = "utf-8"
            json_res = loads(r.text)
            return json_res.get("result")

    def get_orcid(self, doi_entity):
        doi = self.dm.normalize(doi_entity)
        if doi not in self.orcid:
            json_obj = self.call_orcid(doi)
            result = []
            for item in json_obj:
                orcid = item.get("orcid-identifier")
                if orcid:
                    result.append(orcid["path"])
            self.orcid[doi] = result
        for m in self.m_list:
            if doi in m.orcid:
                for orcid in m.get_orcid(doi):
                    if orcid not in self.orcid[doi]:
                        self.orcid[doi].append(orcid)

        return self.orcid[doi]

    def share_orcid(self, doi_entity_1, doi_entity_2):
        result = False

        doi_entity_1_orcid = self.get_orcid(doi_entity_1)
        doi_entity_2_orcid = self.get_orcid(doi_entity_2)
        while not result and doi_entity_1_orcid:
            result = doi_entity_1_orcid.pop(0) in doi_entity_2_orcid

        return result

class CSVManager(object):
    @staticmethod
    def open_csv(fd_path, metadata=False, delimiter=","):
        result = []

        f_paths = set()
        if exists(fd_path):
            if isdir(fd_path):
                for cur_dir, cur_subdir, cur_files in walk(fd_path):
                    for cur_file in cur_files:
                        if cur_file.endswith(".csv"):
                            f_paths.add(cur_dir + sep + cur_file)
            else:
                if fd_path.endswith(".csv"):
                    f_paths.add(fd_path)

        for f_path in f_paths:
            meta = {}
            with open(f_path) as f:
                cur_citations = list(DictReader(f, delimiter=delimiter))
                if metadata:
                    with open(f_path.replace(".csv", ".json")) as mf:
                        meta = load(mf)
                result.append((cur_citations, meta))

        return result

    @staticmethod
    def list_citations(csv_result):
        result = []
        for citations, metadata in csv_result:
            result.extend(citations)
        return result

    @staticmethod
    def create_set_from_csv(csv_obj, key):
        result = set()

        for row in csv_obj:
            result.add(row[key])

        return result

    @staticmethod
    def store_row(o, t, csv_obj, rdf_graph, is_prov=False):
        d_path = o + sep + "csv" + sep + t[:7].replace("-", sep) + sep
        r_path = o + sep + "rdf" + sep + t[:7].replace("-", sep) + sep

        if is_prov:
            header = ["oci", "agent", "source", "datetime"]
            d_path = d_path.replace(o + sep, o + sep + ".." + sep + "prov" + sep)
            r_path = r_path.replace(o + sep, o + sep + ".." + sep + "prov" + sep)
        else:
            header = ["oci", "citing", "cited", "creation", "timespan", "journal_sc", "author_sc"]

        if not exists(d_path):
            makedirs(d_path)
        if not exists(r_path):
            makedirs(r_path)

        f_path = d_path + t + ".csv"
        f_exists = exists(f_path)
        with open(f_path, "a") as f:
            dw = DictWriter(f, header)
            if not f_exists:
                dw.writeheader()
            dw.writerow(csv_obj)

        t_path = r_path + t + ".ttl"
        with open(t_path, "a") as f:
            rdf_string = Citation.format_rdf(rdf_graph, "nt")
            f.write(rdf_string)

def get_date(doi, d, m_list):
    clean_d = None
    for y, m, d in findall("^([0-9][0-9][0-9][0-9])([0-9][0-9])?([0-9][0-9])?$", sub("[^\d]", "", d)):
        clean_d = y + ("-" + m if m else "") + ("-" + d if d else "")

    while not clean_d and m_list:
        clean_d = m_list.pop(0).get_date(doi)

    return clean_d

if __name__ == "__main__":
    arg_parser = ArgumentParser("cnc.py (Create New Citations",
                                description="This tool allows one to take a four column CSV file describing"
                                            "DOI-to-DOI citations, and to store it according to CSV used by"
                                            "the OpenCitations Indexes so as to be added to CROCI. It uses"
                                            "several online services to check several things to create the"
                                            "final CSV file.")

    arg_parser.add_argument("-i", "--input", required=True, nargs="+",
                            help="The input CSV with new citation data.")
    arg_parser.add_argument("-d", "--data", required=True,
                            help="The directory containing all the CSV files already added in CROCI.")
    arg_parser.add_argument("-o", "--orcid", default=None,
                            help="ORCID API key to be used to query them.")
    arg_parser.add_argument("-l", "--lookup", required=True,
                            help="The lookup table for producing OCIs.")

    args = arg_parser.parse_args()

    print("Retrieve new citation data")
    exi_citations = CSVManager.list_citations(CSVManager.open_csv(args.data))

    print("Retrieve existing citation data")
    exi_ocis = CSVManager.create_set_from_csv(exi_citations, "oci")

    print("Create the DOI Manager")
    doim = DOIManager()

    print("Create the Crossref Manager")
    cm = CrossrefManager()

    print("Create the DataCite Manager")
    dm = DataCiteManager()

    print("Create the ORCID Manager")
    om = ORCIDManager(args.orcid, [cm])

    print("Create the OCI Manager")
    ocim = OCIManager(lookup_file=args.lookup)
    cur_time = datetime.now().strftime('%Y-%m-%dT%H:%M:%S')

    citations_already_present = 0
    new_citations_added = 0
    error_in_dois_syntax = 0
    error_in_dois_existence = 0
    all_citations = 0

    for f in args.input:
        try:
            if isdir(f):
                print("\nProcessing files in '%s'" % f)
            else:
                print("\nProcessing file '%s'" % f)
            all_new_citations = CSVManager.open_csv(f, metadata=True)
            for new_citations, new_meta in all_new_citations:
                all_citations += len(new_citations)
                for new_citation in new_citations:
                    citing_doi, cited_doi = \
                        doim.normalize(new_citation["citing_id"]), doim.normalize(new_citation["cited_id"])
                    if citing_doi and cited_doi:
                        oci = ocim.get_oci(citing_doi, cited_doi, "050").replace("oci:", "")
                        if oci not in exi_ocis:
                            exi_ocis.add(oci)
                            if doim.is_valid(citing_doi) and doim.is_valid(cited_doi):
                                print("Create citation data for 'oci:%s' between DOI '%s' and DOI '%s', from '%s'" %
                                      (oci, citing_doi, cited_doi, new_meta["source"]))
                                citing_pub_date, cited_pub_date = \
                                    get_date(citing_doi, new_citation["citing_publication_date"], [cm, dm]), \
                                    get_date(cited_doi, new_citation["cited_publication_date"], [cm, dm])
                                cit = Citation(oci,
                                               BASE_URL + quote(citing_doi), citing_pub_date,
                                               BASE_URL + quote(cited_doi), cited_pub_date,
                                               None, None,
                                               new_meta["agent"], new_meta["source"], cur_time,
                                               "CROCI", "doi", BASE_URL + "([[XXX__decode]])", "reference",
                                               cm.share_issn(citing_doi, cited_doi),
                                               om.share_orcid(citing_doi, cited_doi))

                                # Store in CSV and RDF
                                cit_json = loads(cit.get_citation_json())
                                cit_rdf = cit.get_citation_rdf(CROCI_BASE, False, False, False)
                                cit_json_prov = loads(cit.get_citation_json_prov())
                                cit_rdf_prov = cit.get_citation_prov_rdf(CROCI_BASE)
                                CSVManager.store_row(args.data, cur_time, cit_json, cit_rdf)
                                CSVManager.store_row(args.data, cur_time, cit_json_prov, cit_rdf_prov, True)
                                new_citations_added += 1
                            else:
                                print("WARNING: some DOIs, among '%s' and '%s', do not exist" % (citing_doi, cited_doi))
                                error_in_dois_existence += 1
                        else:
                            print("WARNING: the citation between DOI '%s' and DOI '%s' has been already processed" %
                                  (citing_doi, cited_doi))
                            citations_already_present += 1
                    else:
                        print("WARNING: some DOIs, among '%s' and '%s', is syntactically incorrect" %
                              (citing_doi, cited_doi))
                        error_in_dois_syntax += 1
        except Exception as e:
            print(e.message)

    print("\n# Summary\nNumber of new citations added: %s\nNumber of citations already present in CROCI: %s\nNumber "
          "of citations not added due to a wrong DOI specification: %s (syntax error) and %s (not found "
          "error)\nNumber of citations not processed due to an exception: %s" %
          (new_citations_added, citations_already_present, error_in_dois_syntax, error_in_dois_existence,
           (all_citations -
            (new_citations_added + citations_already_present + error_in_dois_syntax + error_in_dois_existence))))


import pandas as pd
import time
from datetime import datetime
from kafka import KafkaProducer

# Read CSV file into a DataFrame
# Replace 'your_file.csv' with the actual file name
df = pd.read_csv('ecommerce.csv', low_memory=False)

# Kafka producer configuration
producer = KafkaProducer(bootstrap_servers='localhost:9094',
                         value_serializer=lambda v: str(v).encode('utf-8'))

# Iterate over rows and simulate real-time data flow
for index, row in df.iterrows():
    order_info = {
        'item_id': int(row['item_id']),
        'status': str(row['status']),
        'created_at': str(row['created_at']),
        'price': float(row['price']),
        'qty_ordered': int(row['qty_ordered']),
        'grand_total': float(row['grand_total']),
    }

    # Send data to Kafka topic
    producer.send('sales', value=order_info)

    # Simulate a delay to represent real-time processing
    time.sleep(10)


'''
By using this source code, you acknowledge that this software in source code form remains a confidential information of AnyLog, Inc.,
and you shall not transfer it to any other party without AnyLog, Inc.'s prior written consent. You further acknowledge that all right,
title and interest in and to this source code, and any copies and/or derivatives thereof and all documentation, which describes
and/or composes such source code or any such derivatives, shall remain the sole and exclusive property of AnyLog, Inc.,
and you shall not edit, reverse engineer, copy, emulate, create derivatives of, compile or decompile or otherwise tamper or modify
this source code in any way, or allow others to do so. In the event of any such editing, reverse engineering, copying, emulation,
creation of derivative, compilation, decompilation, tampering or modification of this source code by you, or any of your affiliates (term
to be broadly interpreted) you or your such affiliates shall unconditionally assign and transfer any intellectual property created by any
such non-permitted act to AnyLog, Inc.
'''

# Conversion table to allow propper dbms names and table names
translate_dict_ = {}
for x in range (256):

    char_x = chr(x)
    if char_x == '_' or char_x == ' ' or char_x == '-' or char_x == '.' or char_x == '/' or char_x == '\\' or char_x == ':':
        char_y = '_'
    else:
        if (char_x >= 'A' and char_x <= 'Z') or  (char_x >= 'a' and char_x <= 'z') or (char_x >= '0' and char_x <= '9'):
           continue                 # No need to translate

        char_y = "0x%02x" % x    # The string showing x in hex

    translate_dict_[x] = char_y

import copy

active_state_ = {         # A structure containing info per traversak and selected report data

}

# -----------------------------------------------------------------------------------
# Test if the user is assigned to the active_state struct
# -----------------------------------------------------------------------------------
def is_with_user(user_name):
    global active_state_
    return user_name in active_state_

# -----------------------------------------------------------------------------------
# Set new user
# -----------------------------------------------------------------------------------
def set_new_user(user_name):
    '''
    Set a new user in active_state_ struct + initiate initial user settings
    '''
    global active_state_

    active_state_[user_name] = {
        "lists" : {},           # Dictionaries of nodes maintained as f (user) and a unique name
        "reports" : {
                        "edge_nodes" : {}         # a dictionary of edge nodes selected in the tree navigation
                    },
        "selected"  :   "My_Report",
        "path" :    [],         # navigation as f(user)
        "level" : 0,            # The current location in the path
        "connected" : False,     # User is not connected
    }
    set_new_state(user_name, "My_Report", True)

# -----------------------------------------------------------------------------------
# Test for existance of a policy in a list of nodes selected to be monitored
# -----------------------------------------------------------------------------------
def is_in_info_list(user_name, list_name, policy_id):
    '''
    Selected policies are maintained as f(user)
    test if the policy exists in the list of policies

    param: list_name - an ID of the list. i.e. "monitored"
    '''
    user_info = active_state_[user_name]["lists"]
    if not list_name in user_info:
        return False
    return policy_id in user_info[list_name]

# -----------------------------------------------------------------------------------
# Updates a list of nodes selected to be monitored
# -----------------------------------------------------------------------------------
def add_to_info_list(user_name, list_name, policy_id, info):
    '''
     Selected policies are maintained as f(user)
     Add a policy to the list

     param: list_name - an ID of the list. i.e. "monitored"
     '''
    user_info = active_state_[user_name]["lists"]
    if not list_name in user_info:
        user_info[list_name] = {}

    user_info[list_name][policy_id] = info
# -----------------------------------------------------------------------------------
# Get a list of nodes selected to be monitored
# -----------------------------------------------------------------------------------
def get_info_list(user_name, list_name):
    user_info = active_state_[user_name]["lists"]
    if not list_name in user_info:
        info_list = None
    else:
        info_list = user_info[list_name]
    return info_list
# -----------------------------------------------------------------------------------
# is user connected
# -----------------------------------------------------------------------------------
def is_user_connnected(user_name):
    '''
    Return True if usser "connected" flag is set to True
    '''
    return (user_name in active_state_ and  active_state_[user_name]["connected"])

# -----------------------------------------------------------------------------------
# set user connected
# -----------------------------------------------------------------------------------
def set_user_connnected(user_name):
    if user_name in active_state_:
        active_state_[user_name]["connected"] = True

# -----------------------------------------------------------------------------------
# Register an element for the user
# -----------------------------------------------------------------------------------
def register_element(user_name, element_key, element):
    '''
    keep info as f(user + key)
    '''
    user_info = active_state_[user_name]
    user_info[element_key] = element
# -----------------------------------------------------------------------------------
# Register an element for the user
# -----------------------------------------------------------------------------------
def get_element(user_name, element_key):
    '''
    keep info as f(user + key)
    '''

    if user_name in active_state_:
        user_info = active_state_[user_name]
        if element_key in user_info:
            element = user_info[element_key]
        else:
            element = None
    else:
        element = None
    return element
# -----------------------------------------------------------------------------------
# Get the name of the visualization platform
# -----------------------------------------------------------------------------------
def get_platform_name(user_name, report_name):
    global active_state_
    user_info = active_state_[user_name]

    platform = None
    if report_name in user_info['reports']:
        if 'platform' in user_info['reports'][report_name]:
            platform =  user_info['reports'][report_name]['platform']
    return platform

# -----------------------------------------------------------------------------------
# Get the 'selected' report name
# -----------------------------------------------------------------------------------
def get_report_name(user_name):
    '''
    Return the default report for this user
    '''
    global active_state_
    user_info = active_state_[user_name]

    if 'selected' in user_info:
        report_name = user_info['selected']
    else:
        report_name = None
    return report_name

# -----------------------------------------------------------------------------------
# Save the last selection for the reports dates
# -----------------------------------------------------------------------------------
def set_dates_selection(user_name, report_name, from_date, to_date):
    global active_state_
    user_info = active_state_[user_name]

    if report_name in user_info['reports']:
        user_info['reports'][report_name]['dates'] = (from_date, to_date)

# -----------------------------------------------------------------------------------
# Get the last selection for the reports dates
# -----------------------------------------------------------------------------------
def get_dates_selection(user_name, report_name ):
    global active_state_
    from_date = None
    to_date = None
    user_info = active_state_[user_name]

    if report_name in user_info['reports']:
        if 'dates' in user_info['reports'][report_name]:
            from_date, to_date = user_info['reports'][report_name]['dates']
    return [from_date, to_date]
# -----------------------------------------------------------------------------------
# Set the name of the visualization platform for the report
# -----------------------------------------------------------------------------------
def set_platform_name(user_name, report_name, platform):

    global active_state_
    user_info = active_state_[user_name]

    if report_name in user_info['reports']:
        user_info['reports'][report_name]['platform'] = platform

# -----------------------------------------------------------------------------------
# Get user Path overview
# Example reply:
'''
    Name              Names of Info Fields       Names of policies keys            Values from Queries (based on policies keys)
 (from Config)            (from Config)             (From Config)

[('Manufacturer', ['ID', 'Name', 'URL'],       ['id', 'name', 'url'],       [['9990b1b7d5ed51508cdca8f53d6a6621', 'Orics', 'http://orics.com/']]),
 ('Company',      ['ID', 'Customer'],          ['id', 'customer'],          [['0d255db48d048f80e32953a836b27495', 'TuscanBrands']
                                                                             ['0d597850005688024900ab432245563e', 'Costco']])
 ]

 Note - last layer provides all children
'''
# -----------------------------------------------------------------------------------
def get_path_overview(user_name, level, parent_menu):
    '''
    Return the step name and the name from the data instance at this layer
    '''
    global active_state_

    user_info = active_state_[user_name]

    path_info = user_info["path"]  # the report maintains the path info
    path_steps = []
    path_level = user_info["level"]
    # Set the path to the data location
    for index in range(level - 1):
        step_name = parent_menu[index][0]
        if index < len(path_info):
            if path_info[index]["data"]:
                step_data = path_info[index]["data"]
                step_keys = path_info[index]["keys"]
                step_title = path_info[index]["title"]
                policy_type = get_policy_type(step_data)
                if policy_type:
                    policy = step_data[policy_type]     # Get the data from the JSON structure
                    columns_val = []
                    for key in step_keys:
                        if key in policy:
                            value = str(policy[key])
                        else:
                            value = ""
                        columns_val.append(value)
                    path_steps.append( (step_name, step_title, step_keys, [columns_val]) )

    return path_steps

# -----------------------------------------------------------------------------------
# Return the list of nodes that are candidate to a report
# -----------------------------------------------------------------------------------
def get_selected_nodes(user_name:str):
    '''
    Return the nodes that were selected by the user as an option to a report
    '''
    return active_state_[user_name]['reports']['edge_nodes']

# -----------------------------------------------------------------------------------
# Test if the policy is in the selected nodes
# -----------------------------------------------------------------------------------
def is_node_selected(user_name:str, policy_id:str):
    return policy_id in active_state_[user_name]['reports']['edge_nodes']

# -----------------------------------------------------------------------------------
#
# Return a structure representing each node
# Node info includes:
#                     node_info["dbms_name"] = db_name
#                     node_info["table_name"] = tb_name
#                     node_info["policy"] = policy
#
# -----------------------------------------------------------------------------------
def get_table_with_selected_nodes(user_name, policy_keys, add_dbms_name, add_table_name):
    selected_nodes = get_selected_nodes(user_name)
    table_info = []
    for node_info in selected_nodes.values():
        row_info = []
        policy = node_info['policy']
        policy_type = get_policy_type(policy)
        for key in policy_keys:
            if key in policy[policy_type]:
                value = policy[policy_type][key]
            else:
                value = None
            row_info.append(value)         # Add the value from the policy
        if add_dbms_name:
            row_info.append(node_info["dbms_name"])
        if add_table_name:
            row_info.append(node_info["table_name"])
        table_info.append(row_info)
    return table_info
# -----------------------------------------------------------------------------------
# Add a node to the selected nodes list.
# -----------------------------------------------------------------------------------
def add_selected_node(user_name: str, policy_id: str, node_info:dict):
    active_state_[user_name]['reports']['edge_nodes'][policy_id] = node_info

# -----------------------------------------------------------------------------------
# Reset or start a new state
# -----------------------------------------------------------------------------------
def set_new_state(user_name, report_name, is_default):
    '''
    Set a new state for a user in active_state_ struct
    '''
    global active_state_

    active_state_[user_name]['reports'][report_name] = { }
    active_state_[user_name]['reports'][report_name]["entries"] = {} # The selected entries

    if is_default:
        active_state_[user_name]['selected'] = report_name

# -----------------------------------------------------------------------------------
# Delete a report
# -----------------------------------------------------------------------------------
def delete_report(user_name, report_name):
    user_reports = active_state_[user_name]['reports']
    if len(user_reports) == 1:
        # Only reset the report as one report needs to be available
        set_new_state(user_name, report_name, True)
    else:
        del user_reports[report_name]
        if active_state_[user_name]['selected'] == report_name:
            # The deleted report is the default - set a different report as the default
            next_report = list(user_reports.keys())[0]
            active_state_[user_name]['selected'] == next_report

# -----------------------------------------------------------------------------------
# Get the report selected by the user
# -----------------------------------------------------------------------------------
def get_report_selected(user_name):
    global active_state_

    if user_name in active_state_:
        report_name = active_state_[user_name]["selected"]
    else:
        report_name = "Default"
    return report_name
# -----------------------------------------------------------------------------------
# Update the path with the entries visited by the user
# The path is maintained as a f(report)
# -----------------------------------------------------------------------------------
def update_status(user_name, parent_menu, list_keys, table_title, id, data):

    '''
    Keep the user path state as f(user_name + report_used)
    The info maintained:
        data - the user data
        keys - the keys tp pull the info from the JSON
    '''

    global active_state_

    user_info = active_state_[user_name]

    path_info = user_info["path"]  # the report maintains the path info

    # Set the path to the data location
    for index, step in enumerate(parent_menu):
        step_name = step[0]
        if index >= len(path_info):
            path_info.append( { "name" : step_name, "data" : None, "keys": None, "title": None, "id": None})
        elif path_info[index]["name"] != step_name:
            path_info[index]["name"] = step_name
            path_info[index]["data"] = None
            path_info[index]["keys"] = None     # The keys to pull data from the JSON
            path_info[index]["title"] = None  # The title rrelating to the keys
            path_info[index]["id"] = None

    path_info[index]["name"] = step_name
    path_info[index]["data"] = data    # Keep the data of that layer
    path_info[index]["keys"] = list_keys  # Keep the data of that layer
    path_info[index]["title"] = table_title  # Keep the printout title
    path_info[index]["id"] = id
    user_info["level"] = index  # Keep current location

# -----------------------------------------------------------------------------------
# Return the list of reports associated with the user
# -----------------------------------------------------------------------------------
def get_user_reports(user_name):
    global active_state_
    '''
    Return the klist of user reports
    '''

    user_reports = active_state_[user_name]["reports"]
    return list(user_reports.keys())

# -----------------------------------------------------------------------------------
# Get the selection entries for the report
# -----------------------------------------------------------------------------------
def get_report_entries(user_name, report_name):
    if report_name and report_name in active_state_[user_name]["reports"]:
        report_entries = active_state_[user_name]["reports"][report_name]['entries']
    else:
        report_entries = None
    return report_entries

# -----------------------------------------------------------------------------------
# Remove an entry from the report
# -----------------------------------------------------------------------------------
def remove_selected_entry(user_name, report_name, entry):
    '''
    Delete the entry from the list of entries in the report.
    '''

    if report_name and report_name in active_state_[user_name]["reports"]:
        report_entries = active_state_[user_name]["reports"][report_name]
        if entry in report_entries['entries']:
            del report_entries['entries'][entry]

# -----------------------------------------------------------------------------------
# Configure a new report or change report setting
# -----------------------------------------------------------------------------------
def set_report(user_name, form_info):
    '''
    Configure a new report or change report setting
    '''

    selection_counter = 0
    ret_val = True
    err_msg = None
    if 'report_name' in form_info:
        report_name = form_info['report_name']
    else:
        report_name = ""        # user did not select an existing report

    if 'new_report' in form_info and len(form_info['new_report']):
        report_name = ""        # Ignore report selection
        new_report = form_info['new_report']
        if len(new_report) == new_report.count(' '):
            new_report = ""       # All spaces
        else:
            new_report = new_report.replace(' ','_')
    else:
        new_report = ""

    if 'rename' in form_info and len(form_info['rename']):
        new_name = form_info['rename']
        if ' ' in new_name:
            if len(new_name) == new_name.count(' '):
                new_name = ""       # All spaces
            else:
                new_name = new_name.replace(' ','_')
    else:
        new_name = ""

    if 'make_default' in form_info:
        selection_counter += 1
        is_default = form_info['make_default']
    else:
        is_default = False

    if 'reset' in form_info:
        selection_counter += 1
        reset = form_info['reset']
    else:
        reset = False

    if 'delete' in form_info:
        selection_counter += 1
        is_delete = form_info['delete']
    else:
        is_delete = False

    if new_report and report_name:
        ret_val = False
        err_msg = "Duplicate selections: select existing report or new report"
    else:
        conflicting_selections = False

        # Test conflicting choices
        if selection_counter == 3 or (is_delete and (selection_counter != 1 or new_report)):
            conflicting_selections = True

        # Test conflicting rename + new report
        elif  new_name and new_report:
            conflicting_selections = True

        if conflicting_selections:
            ret_val = False
            err_msg = "Wrong selections: conflicting report selections"
        else:
            # Test report not selected
            if not report_name and (is_delete or reset or new_name) or \
                        (is_default and not report_name and not new_name and not new_report):
                ret_val = False
                err_msg = "Report name not selected"
            else:

                if is_delete:
                    delete_report(user_name, report_name)
                elif new_report:
                    if get_report_info(user_name, report_name):
                        ret_val = False
                        err_msg = "Duplicate report name: %s" % report_name
                    else:
                        set_new_state(user_name, new_report, is_default)
                elif reset:
                    set_new_state(user_name, report_name, is_default)
                elif new_name:
                    # replace the report info to a different name
                    if get_report_info(user_name, new_name):
                        ret_val = False
                        err_msg = "Duplicate report name: %s" % new_name
                    else:
                        ret_val, err_msg = rename_report(user_name, report_name, new_name, is_default)
                elif is_default:
                    active_state_[user_name]['selected'] = report_name

    return [ret_val, err_msg]

# -----------------------------------------------------------------------------------
# Update AL command to retrieve info with info from the parent
# -----------------------------------------------------------------------------------
def rename_report(user_name, report_name, new_name, is_default):

    ret_val = True
    err_msg = None
    user_reports = active_state_[user_name]['reports']
    if report_name in user_reports:
        if new_name in user_reports:
            ret_val = False
            err_msg = "Duplicate report name: %s" % report_name
        else:
            report_struct = user_reports[report_name]
            active_state_[user_name]['reports'][new_name] = report_struct
            del active_state_[user_name]['reports'][report_name]

            if active_state_[user_name]['selected'] == report_name:
                # keep default if old name was the default
                active_state_[user_name]['selected'] = new_name
    else:
        ret_val = False
        err_msg = "Wrong report name: %s" % report_name

    if ret_val and is_default:
        active_state_[user_name]['selected'] = new_name
    return [ret_val, err_msg]
# -----------------------------------------------------------------------------------
# Update AL command to retrieve info with info from the parent
# -----------------------------------------------------------------------------------
def update_command(user_name, selection, command):

    '''
    If the bring command references the parent, bring the info from the parents.
    selection - describes the parents path.
    Example:
        "blockchain get tag where machine = [machine][id]  bring.unique.json [tag][name] [tag][description] [tag][id] separator = ,"
        --> [machine][id] is taken from the parents usinf the path described in the selection variable
    '''
    cmd_words = command.split()
    value = None
    if len(cmd_words) > 7:
        if cmd_words[3] == "where" and cmd_words[5] == '=':
            for index, word in enumerate(cmd_words[6:]):
                if word == 'bring' or word.startswith("bring."):
                    break       # End of WHERE part
                value = None
                if word[0] == '[' and word[-1] == ']':
                    keys_list = word[1:].split('[')         # The list of keys to use to retrieve from the JSON
                    if len(keys_list) > 1:             # at least 2 keys (the first is the policy type)
                        parent_type = keys_list[0][:-1]
                        parent_policy = get_policy(user_name, selection)   # Get the policy of the parent from the path
                        if parent_policy:
                            if parent_type in parent_policy:
                                # pull the attribute value
                                value = parent_policy
                                for entry in keys_list:
                                    if isinstance(value,dict):
                                        key = entry[:-1]    # Remove closing brakets
                                        if key in value:
                                            value = value[key]
                                        else:
                                            value = None
                                            break
                                    else:
                                        value = None
                                        break
                if value:
                    cmd_words[6 + index] = value    # Replace with value from parent
                else:
                    break
    if value:
        # command text was replaced with values from parents
        updated_cmd = ' '.join(cmd_words)
    else:
        updated_cmd = command

    return updated_cmd
# -----------------------------------------------------------------------------------
# Get the info selected for the report
# -----------------------------------------------------------------------------------
def get_report_info(user_name, report_name):
    '''
    Return a link to the info cpllected on the report.
    Includig: DBMS and Tables for output
    '''
    global active_state_

    user_info = active_state_[user_name]

    if report_name in user_info["reports"]:
        report_info = user_info["reports"][report_name]
    else:
        report_info = None
    return report_info

# -----------------------------------------------------------------------------------
# Get a policy from the path
# -----------------------------------------------------------------------------------
def get_policy(user_name, selection):

    global active_state_

    user_info = active_state_[user_name]

    path_info = user_info["path"]  # the user path info

    selection_list = selection.split('@')

    policy = None

    parent_level = (len(selection_list) - 2)    # Note: parent level starts at 0

    if user_info["level"] >= parent_level:
        # No parent policy with the path provided

        for index in range (parent_level + 1):
            entry = selection_list[index]
            if path_info[index]["name"] != entry:
                break

        if index == parent_level:
            policy = path_info[index]["data"]

    return policy
# -------------------------------------------------------------------------
# Add selected Entry to the list of entries in the report
# -------------------------------------------------------------------------
def add_entry_to_report(user_name, dbms_name, table_name, json_entry):

    '''
    Add an entry to the report -
    Every report structure includes the list of Edge elements (and their parents) that participate in the report
    '''

    global active_state_

    user_info = active_state_[user_name]

    report_selected = user_info["selected"]

    # Get a dictionary with all the selected edge nodes for the report
    edge_selected = active_state_[user_name]['reports'][report_selected]["entries"] # The selected entries

    policy_type = get_policy_type(json_entry)
    if policy_type:
        if "id" in json_entry[policy_type]:
            policy_id = json_entry[policy_type]["id"]
        else:
            policy_id = None    # Missing ID for the policy
    else:
        # The JSON is not a policy
        if "id" in json_entry:
            policy_id = json_entry["id"]
        else:
            policy_id = None    # Missing ID for the json struct

    if policy_id:
        # Copy the path anf pathe elements to the list of selected items to print
        if not policy_id in edge_selected:
            # Not a duplicated node
            edge_selected[policy_id] = {}
            # The Path that determined the selected edge that is added to the report
            edge_selected[policy_id]["path"] = copy.deepcopy(active_state_[user_name]['path'])

            db_name = get_sql_name(json_entry, dbms_name)    # Pull the dbms name from the policy
            tb_name = get_sql_name(json_entry, table_name)  # Pull the dbms name from the policy

            edge_selected[policy_id]["dbms_name"] = db_name
            edge_selected[policy_id]["table_name"] = tb_name
            edge_selected[policy_id]["policy"] = json_entry

# -------------------------------------------------------------------------
# Get a dbms or a table name from the JSON structure
# -------------------------------------------------------------------------
def get_sql_name(json_entry, extract_key):
    '''
    Given a policy in JSON format and a key to extract the value from the policy,
    return the value.
    Replace spaces with underscore, return small letters and replace SQL allowable characters
    :param json_entry: The Policy
    :param extract_key: The key to use. For example [tag][name]
    :return: The derived value
    '''

    sql_name = extract_policy_value(json_entry, extract_key)  # Pull the dbms name from the policy
    if sql_name:
        sql_name = reset_str_chars(sql_name)  # Make a dbms name (without spaces etc.)
    else:
        # The extract key is the value to return
        sql_name = reset_str_chars(extract_key)  # Make a dbms name (without spaces etc.)
    return sql_name

# -------------------------------------------------------------------------
# Remove special chars that conflict with naming convention
# Database names and table names are set with alphanumeric characters
# -------------------------------------------------------------------------
def reset_str_chars( source_str ):
    global translate_dict_
    source_lower = source_str.lower()
    return source_lower.translate ( translate_dict_ )

# ======================================================================================================================
# Get the type of policy
# ======================================================================================================================
def get_policy_type(policy):

    if len(policy) == 1:
        # Policy has one entry at the root
        try:
            policy_type = next(iter(policy))
        except:
            policy_type = None
        else:
            if not isinstance(policy[policy_type], dict):
                policy_type = None  # second layer is not a dictionary
    else:
        policy_type = None

    return policy_type
# ======================================================================================================================
# Get The policy value - determine the policy type and return the value for the key
# ======================================================================================================================
def get_policy_value(policy, key):
    '''
    For the provided policy, pull the value using the second level key
    '''

    policy_type = get_policy_type(policy)
    if policy_type:
        if key in policy[policy_type]:
            return policy[policy_type][key]
    return None
# ======================================================================================================================
# Get a value from a policy using a key line [tag][name] [tag][id]
# ======================================================================================================================
def extract_policy_value(policy, key):
    '''
    Given a JSON policy and a key, retrieve the value
    The key structure is similar to the bring command: [key 1][key 2]

    If policy type is provided - test the type
    '''

    value = None
    if key[0] == '[' and key[-1] == ']':
        keys_list = key[1:].split('[')         # The list of keys to use to retrieve from the JSON
        value = policy
        for entry in keys_list:                # at least 2 keys (the first is the policy type)
            if isinstance(value,dict):
                key = entry[:-1]    # Remove closing brakets
                if key in value:
                    value = value[key]
                else:
                    value = None
                    break
            else:
                value = None
                break

    return value


##### Title: Clip by Raster Extent
##### Author: Colin Stief

import arcpy, os

## Grab user inputs
feature = arcpy.GetParameterAsText(0)
raster = arcpy.GetParameterAsText(1)
arcpy.env.workspace = arcpy.GetParameterAsText(2)
output_feature_name = arcpy.GetParameterAsText(3)

## Make new array to hold extent, then grab it from raster
pnt_array = arcpy.Array()
extent = arcpy.Raster(raster).extent
pnt_array.add(extent.lowerLeft)
pnt_array.add(extent.lowerRight)
pnt_array.add(extent.upperRight)
pnt_array.add(extent.upperLeft)

## Create new polygon from extent
poly = arcpy.Polygon(pnt_array)

## Perform Clip
arcpy.Clip_analysis(feature, poly, output_feature_name)


s = list(input())
array = []
sum = 0
for i in s:
    if i.isalpha():
        array.append(i)
    else:
        sum += int(i)
array.sort()
if sum != 0 :
    array.append(str(sum)) # 0인 경우 : 처음 문자열 s에 숫자가 없는경우
print("".join(array))


from collections import deque

with open('i19.txt') as f:
    scn = [[(*map(int, line.split(',')),) for line in sc.split()[4:]]
           for sc in f.read().strip().split('\n\n')]

N = len(scn)
MIN_OVERLAP = 12

def rot90z(coords):
    return [(-y, x, z) for x, y, z in coords]

def rot90x(coords):
    return [(x, -z, y) for x, y, z in coords]

def rot90y(coords):
    return [(z, y, -x) for x, y, z in coords]

def getAllOrient(coords):
    for _ in range(4):
        for _ in range(4):
            yield coords
            coords = rot90z(coords)
        coords = rot90x(coords)
    coords = rot90y(coords)
    for _ in range(4):
        yield coords
        coords = rot90z(coords)
    coords = rot90y(rot90y(coords))
    for _ in range(4):
        yield coords
        coords = rot90z(coords)

def mapToPairs(coords):
    for x1, y1, z1 in coords:
        for x2, y2, z2 in coords:
            if x1 == x2 and y1 == y2 and z1 == z2:
                continue
            yield x2-x1, y2-y1, z2-z1

def mapDelta(arr, dx, dy, dz):
    return [(x+dx, y+dy, z+dz) for x, y, z in arr]

def findMapedDeltas(a, b, ovl=None):
    if ovl is None:
        ovl = MIN_OVERLAP
    for ax, ay, az in a:
        for bx, by, bz in b:
            maped = mapDelta(b, ax-bx, ay-by, az-bz)
            if overlap(a, maped) >= ovl:
                return maped, ax-bx, ay-by, az-bz

def overlap(a, b):
    a = {*a}
    c = 0
    for e in b:
        if e in a:
            a.remove(e)
            c += 1
    return c

scnOr = [list(getAllOrient(sc)) for sc in scn]

scwor = [[list(mapToPairs(o)) for o in s] for s in scnOr]

prs = []
for i in range(N):
    print('Precheck:', i, '/', N, end='\r')
    for j in range(i + 1, N):
        for bo in scwor[j]:
            if overlap(scwor[i][0], bo) >= MIN_OVERLAP * (MIN_OVERLAP - 1):
                prs += [(i, j)]
                break
print(end='Precheck: Done     \r')

curr = {*scn[0]}
q = deque(x[1] for x in prs if x[0] == 0)
done = set([0]+[*q])
scnpos = [(0, 0, 0)]

while q:
    print('Done:', len(done)-len(q), '/', N, end='      \r')
    i = q.popleft()
    for o in getAllOrient(scn[i]):
        r = findMapedDeltas(curr, o)
        if r:
            maped, *dp = r
            curr.update(maped)
            scnpos += [dp]
            for a, b in prs:
                if b == i:
                    a, b = b, a
                if a == i and b not in done:
                    q.append(b)
                    done.add(b)
            break

print('Part 1:', len(curr), '   ')

mx = 0
for x1, y1, z1 in scnpos:
    for x2, y2, z2 in scnpos:
        mx = max(mx, abs(x1-x2)+abs(y1-y2)+abs(z1-z2))

print('Part 2:', mx)


"""Steps implementation for following scenarios: verifyStage.feature."""

from behave import given, when, then
from features.src.stage import Stage
from features.src import pipeline
from pyshould import should

@given(u'I have verified a booster\'s pipeline has completed')
def given_pipeline_completed(context):
    """Precondition that the pipeline has been complete and verified."""
    pipeline.pipelineVerified | should.be_true.desc("Pipeline is complete and verified.")
    print('Attempting to use query for Pipeline deployed to Stage...')
    context.stage = Stage()

@when(u'I query a pipeline\'s stage endpoint')
def when_query_pipeline(context):
    """Query a pipeline's stage endpoint."""
    result = context.stage.runTest('testing stage endpoint')
    print('Result = {}'.format(result))
    context.result = result

@then(u'I should see the deployed app running on stage')
def then_app_running_stage(context):
    """Check that the app is deployed and running on stage."""
    result = context.result
    result | should.equal('Success').desc("Application is reachable in the Stage stage.")


# -*- coding:utf-8 -*-

from functools import partial
import httplib

from libcloud.loadbalancer import providers

from libcloud_rest.api.handlers import ServiceHandler, invoke_method,\
    invoke_extension_method, list_providers, provider_info
from libcloud_rest.utils import json

invoke_method = partial(invoke_method, providers)

lb_handler = ServiceHandler('/loadbalancer/')

lb_handler.add_handlers([
    ('/providers', partial(list_providers, providers)),
    ('/providers/<string:provider_name>',
        partial(provider_info, providers)),
    ('/<string:provider>/<string:method_name>',
        partial(invoke_extension_method, providers), ['POST']),
    ('/<string:provider>/algorithms',
        partial(invoke_method, 'list_supported_algorithms')),
    ('/<string:provider>/balancers',
        partial(invoke_method, 'list_balancers')),
    ('/<string:provider>/protocols',
        partial(invoke_method, 'list_protocols')),
    ('/<string:provider>/locations', partial(invoke_method, 'list_locations'))
])

@lb_handler.handler('/<string:provider>/balancers', methods=['POST'])
def create_balancer(request):
    """
    Invoke create_balancer method and patch response.

    @return: Response object with newly created balancer ID in Location.
    """
    response = invoke_method('create_balancer', request)
    balancer_id = json.loads(response.data)['id']
    response.autocorrect_location_header = False
    response.headers.add_header('Location', balancer_id)
    response.status_code = httplib.CREATED
    return response

@lb_handler.handler('/<string:provider>/balancers/<string:balancer_id>')
def get_balancer(request):
    data = json.dumps({'balancer_id': request.args['balancer_id']})
    return invoke_method('get_balancer', request, data=data)

@lb_handler.handler('/<string:provider>/balancers/<string:loadbalancer_id>',
                    methods=['PUT'])
def update_balancer(request):
    json_data = json.loads(request.data)
    json_data['loadbalancer_id'] = request.args['loadbalancer_id']
    return invoke_method('update_balancer', request,
                         data=json.dumps(json_data))

@lb_handler.handler('/<string:provider>/balancers/<string:loadbalancer_id>',
                    methods=['DELETE'])
def destroy_balancer(request):
    """
    Get balancer id from params and invoke destroy_balancer driver method.
    @return: Empty response body
    """
    json_data = {'loadbalancer_id': request.args['loadbalancer_id']}
    return invoke_method('destroy_balancer', request,
                         data=json.dumps(json_data),
                         status_code=httplib.ACCEPTED)

@lb_handler.handler('/<string:provider>/balancers/<string:lb_id>/members',
                    methods=['POST'])
def create_member(request):
    json_data = json.loads(request.data)
    json_data['loadbalancer_id'] = request.args['lb_id']
    return invoke_method('balancer_attach_member', request,
                         data=json.dumps(json_data))

@lb_handler.handler('/<string:provider>/balancers/<string:lb_id>/members')
def list_members(request):
    json_data = json.loads(request.data)
    json_data['loadbalancer_id'] = request.args['lb_id']
    return invoke_method('balancer_list_members', request,
                         data=json.dumps(json_data))

@lb_handler.handler(
    '/<string:provider>/balancers/<string:lb_id>/members/<string:member_id>',
    methods=['DELETE'])
def delete_member(request):
    """
    @return:This operation does not return a response body.
    """
    json_data = {'loadbalancer_id': request.args['lb_id'],
                 'member_id': request.args['member_id']}
    return invoke_method('balancer_detach_member', request,
                         data=json.dumps(json_data),
                         status_code=httplib.ACCEPTED)


groups_count = int(input())  # Въвеждаме броя на групите

musala_count = 0
monblan_count = 0
kilimanjaro_count = 0
k2_count = 0
everest_count = 0

for _ in range(groups_count):
    group_size = int(input())  # Въвеждаме броя на хората в групата

    if group_size <= 5:
        musala_count += 1
    elif group_size <= 12:
        monblan_count += 1
    elif group_size <= 25:
        kilimanjaro_count += 1
    elif group_size <= 40:
        k2_count += 1
    else:
        everest_count += 1

total_count = musala_count + monblan_count + kilimanjaro_count + k2_count + everest_count

musala_percent = musala_count / total_count * 100
monblan_percent = monblan_count / total_count * 100
kilimanjaro_percent = kilimanjaro_count / total_count * 100
k2_percent = k2_count / total_count * 100
everest_percent = everest_count / total_count * 100

print(f"{musala_percent :.2f}%")
print(f"{monblan_percent :.2f}%")
print(f"{kilimanjaro_percent :.2f}%")
print(f"{k2_percent :.2f}%")
print(f"{everest_percent :.2f}%")

SoftUni Python Fourth lecture for-loop/trecking_mania.py


import numpy as np
import pickle
import sys
import os
import RBFN as RBFN
from sklearn.ensemble import RandomForestRegressor
from sklearn import linear_model
from sklearn.neighbors import KNeighborsRegressor
from sklearn import svm
# import logging
# logging.basicConfig(filename='/home/naamah/Documents/CatES/result_All/GECCO/svm_25/logger/logger.log', filemode='a',level=logging.INFO)
import smac_KNN, smac_svm, smac_RF
import time
#import pyKriging
#from pyKriging.krige import kriging

# from pyKriging_master import pyKriging
# from pyKriging_master.pyKriging.krige import kriging

def surrogateRF(Xarchive, Farchive, X,file_loc,file_loc_general,toUpdate, first_iter=False,problem='LABS',index=1):
    Xnew=Xarchive.T
    X_pred=X.T
    SMAC = False

    if SMAC:
        with open("/home/naamah/Documents/CatES/result_All/smac/RF/X1.p", "wb") as fp:
            pickle.dump(Xnew, fp)
        with open("/home/naamah/Documents/CatES/result_All/smac/RF/F1.p", "wb") as fp:
            pickle.dump(Farchive, fp)

        anf=smac_RF.main_loop(problem)

        print("SMAC {}".format(anf))
        sys.exit("Error message")

    clf = RandomForestRegressor(criterion="mse",n_estimators=49, min_samples_leaf=1, min_samples_split=2,
                                    min_weight_fraction_leaf=0.0001060554, max_leaf_nodes=1000,
                                    min_impurity_decrease=0.0,min_impurity_split=None, warm_start=False, max_depth=None,
                                    max_features="auto",random_state=7
                                    ) #RF_9111

    # if problem=="LABS":
    #
    #     clf = RandomForestRegressor(criterion="mse",n_estimators=49, min_samples_leaf=1, min_samples_split=2,
    #                                 min_weight_fraction_leaf=0.0001060554, max_leaf_nodes=1000,
    #                                 min_impurity_decrease=0.0,min_impurity_split=None, warm_start=False, max_depth=None,
    #                                 max_features="auto",random_state=7
    #                                 ) #RF_9111
    #
    #
    # elif problem=="NKL":
    #     clf = RandomForestRegressor(criterion="mse",n_estimators=43, min_samples_leaf=1, min_samples_split=4,
    #                                 min_weight_fraction_leaf=0.0005238657425634613, max_leaf_nodes=673, min_impurity_decrease=0.0,
    #                                 warm_start=True, max_depth=None, max_features="auto", random_state=8
    #                                 ) #RF_1_sig
    #
    #
    #
    # else: #problem=="QAP"
    #     clf = RandomForestRegressor(criterion="mse",n_estimators=38, min_samples_leaf=1, min_samples_split=2,
    #                                 min_weight_fraction_leaf=0.0002313685, max_leaf_nodes=551, min_impurity_decrease=2.86E-08,
    #                                 warm_start=False, max_depth=None, max_features="auto", random_state=None
    #                                 )#RF_9333

    if not os.path.exists(file_loc_general + "/surrogate_configuration"):
        with open(file_loc_general + "/surrogate_configuration", 'a') as file:
            file.write("clf:\n{}\n\nTuning Algorithem: {} ".format(clf.get_params(), "smac"))
        file.close()

    clf.fit(Xnew, Farchive)
    F_pred = clf.predict(X_pred)

    return F_pred

def surrogateKNN(Xarchive, Farchive, X,file_loc,file_loc_general,toUpdate, first_iter=False,problem='LABS'):
    Xnew=Xarchive.T
    X_pred=X.T
    SMAC = False

    if SMAC:
        with open("/home/naamah/Documents/CatES/result_All/X1.p", "wb") as fp:
            pickle.dump(Xnew, fp)
        with open("/home/naamah/Documents/CatES/result_All/F1.p", "wb") as fp:
            pickle.dump(Farchive, fp)

        anf=smac_KNN.main_loop(problem)

        print("SMAC {}".format(anf))
        sys.exit("Error message")

    neigh = KNeighborsRegressor(n_neighbors=9,  algorithm="ball_tree", p=1, weights="distance",leaf_size=60) # KNN_LABS_444

    # if problem=="LABS":
    #     neigh = KNeighborsRegressor(n_neighbors=9,  algorithm="ball_tree", p=1, weights="distance",leaf_size=60) # KNN_LABS_444
    #
    #
    #
    # elif problem=="NKL":
    #     neigh = KNeighborsRegressor(n_neighbors=10, algorithm="brute", p=1, weights="distance",leaf_size=76) # KNN_NKL_4442
    #
    #
    #
    # else: #problem=="QAP"
    #     neigh = KNeighborsRegressor(n_neighbors=8,  algorithm="auto", p=1, weights="distance",leaf_size=19) # KNN_QAP_4446

    if not os.path.exists(file_loc_general + "/surrogate_configuration"):
        with open(file_loc_general + "/surrogate_configuration", 'a') as file:
            file.write("clf:\n{}\n\nTuning Algorithem: {} ".format(neigh.get_params(), "smac"))
        file.close()

    neigh.fit(Xnew, Farchive)
    F_pred = neigh.predict(X_pred)

    return F_pred

def surrogateSVM(Xarchive, Farchive, X,file_loc,file_loc_general,toUpdate, first_iter=True,problem='LABS'):
    Xnew=Xarchive.T
    X_pred=X.T
    SMAC = False

    if SMAC:
        # smac - no conda
        with open("/home/naamah/Documents/CatES/result_All/smac/svm/X1.p", "wb") as fp:
            pickle.dump(Xnew, fp)
        with open("/home/naamah/Documents/CatES/result_All/smac/svm/F1.p", "wb") as fp:
            pickle.dump(Farchive, fp)

        ans=smac_svm.main_loop(problem)

        print("SMAC {}".format(ans))
        sys.exit("Error message")

        ans_clf=ans.get_dictionary()
        C=ans_clf['C']
        epsilon=ans_clf['epsilon']
        kernel=ans_clf['kernel']
        shrinking =True
        if ans_clf['shrinking']=='false':
            shrinking=False
        if ans_clf['gamma']=='value':
            gamma_value = ans_clf['gamma']
        else:
            gamma_value='auto'

    # time1=time.time()
    # clf = svm.SVR(kernel='rbf', C=307)
    if problem == "MIS":
        # clf = svm.SVR(kernel='rbf', C=307, epsilon=0.0023, gamma=0.1223 ,shrinking=False,degree=3) #IRACE_SURROGATE SVM_NKL_3331
        clf = svm.SVR(kernel='rbf', C=307, epsilon=0.5, gamma=0.1223 ,shrinking=False,degree=3) #IRACE_SURROGATE SVM_NKL_3331

    else:
        # clf = svm.SVR(kernel='rbf', C=237.689013261001, epsilon=0.00125697429061751, gamma=0.0445112387400382,shrinking=False)  # BYSMAC_9111
        clf = svm.SVR(kernel='rbf', C=237.689013261001, epsilon=0.5, gamma=0.0445112387400382,shrinking=False)  # BYSMAC_9111

    # if problem=="LABS":
    #     # clf = svm.SVR(kernel='rbf', C=307, epsilon=0.0023, gamma=0.1223 ,shrinking=False,degree=3) #R
    #     clf = svm.SVR(kernel='rbf', C=237.689013261001, epsilon=0.00125697429061751, gamma=0.0445112387400382 ,shrinking=False) #BYSMAC_9111
    #
    #
    # elif problem=="NKL":
    #     clf = svm.SVR(kernel='poly', C=999.7180904447123, epsilon=0.0014989615126237686, gamma=1,shrinking=True) #BYSMAC_9111
    #
    # else: #"QAP"
    #     clf = svm.SVR(kernel='rbf', C=307, epsilon=0.0023, gamma=0.1223 ,shrinking=False,degree=3) #IRACE_SURROGATE SVM_NKL_3331

    # time2=time.time()

    if not os.path.exists(file_loc_general + "/surrogate_configuration"):
        with open(file_loc_general + "/surrogate_configuration", 'a') as file:
            file.write("clf:\n{}\n\nTuning Algorithem: {} ".format(clf.get_params(), "smac"))
        file.close()
    clf.fit(Xnew, Farchive)
    # time3=time.time()
    F_pred = clf.predict(X_pred)
    # time4=time.time()
    # logging.warning("\nModel creation: {}  Training: {}  Prediction:  {} \n\n".format(time2-time1, time3-time2, time4-time3))
    return F_pred

def surrogateLM(Xarchive, Farchive, X, toUpdate, test=False, problem='LABS'):
    Fnew = np.asarray(Farchive).reshape((len(Farchive), 1))
    Xnew = Xarchive.T
    X_pred = X.T

    reg = linear_model.LinearRegression()
    reg.fit(Xnew, Fnew)

    F_pred = reg.predict(X_pred)
    F_pred = np.squeeze(F_pred, axis=1)

    return F_pred

def surrogateRBFN (Xarchive, Farchive, X,file_loc,file_loc_general,toUpdate, first_iter=False,problem='LABS',isKmeans=True):
    # http://www.rueckstiess.net/research/snippets/show/72d2363e
    Xnew=Xarchive.T
    X_pred=X.T
    Xnew_unique, idx_unique = np.unique(Xnew, axis=0, return_index=True)
    F_unique =Farchive[idx_unique]
    numCenter= int(len(F_unique)*0.75)

    if (toUpdate):
        Rbfn=RBFN.RBF(len(Xnew[0]),numCenter,len(Xnew[0]))
        Rbfn.train(Xnew_unique,F_unique,isKmeans)
        with open(file_loc+"/Rbfn.p", "wb") as fp:
            pickle.dump(Rbfn, fp)
    else:
        with open(file_loc+"/Rbfn.p", "rb") as fp:
            Rbfn = pickle.load(fp)

    F_pred=Rbfn.test(X_pred)
    return F_pred

def surrogateKriging (Xarchive, Farchive, X, file_loc,file_loc_general,toUpdate, first_iter=False,problem='LABS'):
    X_pred=X.T
    F_pred=[]

    # update or build the model
    if (toUpdate):
        Xnew = Xarchive.T
        Xnew_unique, idx_unique = np.unique(Xnew, axis=0, return_index=True)
        F_unique = Farchive[idx_unique]

        if first_iter: #build the model

            testfun = pyKriging.testfunctions().stybtang

            # Now that we have our initial data, we can create an instance of a Kriging model
            k = kriging(Xnew_unique, F_unique, testfunction=testfun, name='simple')
            k.train(optimizer='ga')

        else: #update the model
            with open(file_loc+"kriging.p", "rb") as fp:
                k = pickle.load(fp)
            for point,y_point in zip(Xnew_unique,F_unique):
                k.addPoint(point,y_point)

        #save the new/updates model
        with open(file_loc+"kriging.p", "wb") as fp:
            pickle.dump(k, fp)

    # no new points to update the model
    # only predicts new points.
    else:
        with open(file_loc+"kriging.p","rb") as fp:
            k = pickle.load(fp)

    for x in X_pred:
        F_pred.append(k.predict(x))

    F_pred=np.asarray(F_pred)
    return F_pred

#
# X= np.asarray([[1,0,1,0,1,0],[4,5,6],[7,8,9],[10,11,12],[13,14,15],[13,14,15]], dtype=float)
# y= np.asarray([6,15,24,36,42], dtype=float)
# x_test=np.asarray([[1,2,3],[13,14,16],[16,11,8],[16,12,8],[2,3,4],[13,14,15]],dtype=float)
# X= np.asarray([[1,0,1,0,1,0],[1,1,0,0,1,1],[0,0,1,1,1,1],[0,1,1,0,0,0],[0,0,1,0,0,0],[1,1,1,1,1,1],[1,1,0,0,1,1]
#                ,[1,1,1,1,0,1],[0,1,1,1,1,1],[0,0,0,1,0,0]], dtype=float)
# y= np.asarray([3,4,4,2,1,6,4,5,5,1], dtype=float)
# x_test=np.asarray([[1,1,1,0,0,0],[1,1,1,1,1,1],[0,0,0,0,0,0],[0,1,0,1,0,1],[1,0,1,0,1,0]],dtype=float)
# X=X.T
# x_test=x_test.T
# #
# X=np.loadtxt('/home/naamah/Documents/CatES/data/X')
# y=np.loadtxt('/home/naamah/Documents/CatES/data/F')
# x_test=np.loadtxt('/home/naamah/Documents/CatES/data/X_test')
# f_test=np.loadtxt('/home/naamah/Documents/CatES/data/F_test')
# X=X[0:12,:]
# x_test=x_test[0:12,:]
# # x_test=X
# # f_test=y
#
# ans=surrogateKriging(X,y,x_test,file_loc="/home/naamah/Documents/CatES/result_All/result_test/exp_num_1", toUpdate=True,first_iter=True)
# ans2=np.linalg.norm(f_test-ans)
#
# print("the ans for the surrogate is:\n {}\n".format(ans))
# print("the reall fittnes is: \n{}\n".format(f_test))
# print("the diff between the fittnes and the surrogate is:\n {}\n".format(f_test-ans))
# print("the euclidean diff between the fittnes and the surrogate is: {}\n".format(ans2))


import logging
from os.path import join, exists, splitext, basename, split
from os import makedirs, remove, listdir
from franklin.backbone.specifications import (BACKBONE_DIRECTORIES,
                                              BACKBONE_BASENAMES)
from franklin.utils.cmd_utils import call
from franklin.utils.misc_utils import get_num_threads, rel_symlink
from franklin.seq.readers import guess_seq_file_format
from franklin.utils.seqio_utils import seqio
from tempfile import NamedTemporaryFile
from franklin.backbone.analysis import scrape_info_from_fname

LOGGER_NAME = 'franklin'

def blast_runner_plus(seq_fpath, blast_db, blast_type, result_fpath,
                       threads=False):
    'It runs a blast giving a file and a database path'
    cmd = [blast_type, '-db', blast_db, '-num_alignments', '25',
           '-num_descriptions', '25', '-evalue', '0.0001', '-outfmt', '5',
           '-query', seq_fpath, '-out', result_fpath]
    if threads:
        cmd.extend(['-num_threads', str(threads)])
    call(cmd, raise_on_error=True, log=True)

def makeblastdb_plus(seq_fpath, dbtype, outputdb=None):
    'It creates the blast db database'
    cmd = ['makeblastdb', '-in', seq_fpath, '-dbtype', dbtype]
    if outputdb is not None:
        cmd.extend(['-out', outputdb])
    call(cmd, raise_on_error=True)

def _get_basename(fpath):
    'It returns the base name without path and extension'
    return splitext(basename(fpath))[0]

def _create_temp_fasta_file(fpath):
    'It creates a fasta file format temfile'
    fasta_fhand = NamedTemporaryFile(suffix='.fasta', mode='a')
    seqio(in_seq_fhand=open(fpath),
          out_seq_fhand=fasta_fhand,
          out_format='fasta')
    return fasta_fhand

def guess_blastdb_kind(blastdb):
    'it infers the kind of the blastdb'
    blastdir, basename_ = split(blastdb)
    for file_ in listdir(blastdir):
        if file_.startswith(basename_ + '.') and file_ != basename_ :
            if splitext(file_)[1][1] == 'n':
                return 'nucl'
            elif splitext(file_)[1][1] == 'p':
                return 'prot'

def guess_blast_program(seq_type, db_type, prefer_tblastx=False):
    'It guess the blast program to use for the given seq and db type'
    if seq_type == 'nucl' and db_type == 'nucl':
        if prefer_tblastx:
            blast_program = 'tblastx'
        else:
            blast_program = 'blastn'
    elif seq_type == 'nucl' and db_type == 'prot':
        blast_program = 'blastx'
    elif seq_type == 'prot' and db_type == 'nucl':
        blast_program = 'tblastn'
    elif seq_type == 'prot' and db_type == 'prot':
        blast_program = 'blastp'

    return blast_program

def backbone_blast_runner(query_fpath, project_dir, blast_program,
                          blast_db=None, blast_db_seq=None, dbtype='nucl',
                          threads=False):
    '''It returns the blast if the results doesn't exist'''
    if blast_db is None and blast_db_seq is None:
        raise RuntimeError('It needs a blast database or seqfile')

    #create a logger
    logger = logging.getLogger(LOGGER_NAME)
    query_basename = _get_basename(query_fpath)
    blast_dir = join(project_dir, BACKBONE_DIRECTORIES['blast_dir'])

    if blast_db:
        result_dir = join(blast_dir, query_basename, _get_basename(blast_db))
    else:
        result_dir = join(blast_dir, query_basename,
                          _get_basename(blast_db_seq))
    if not exists(result_dir):
        makedirs(result_dir)
    result_fpath = join(result_dir,
                        '%s.%s.xml' % (BACKBONE_BASENAMES['blast_basename'],
                                       blast_program))
    if exists(result_fpath):
        logger.info('Using the stored blast result %s' % result_fpath)
        return result_fpath

    #the input file should be fasta
    fasta_query_fhand = None
    fasta_db_fhand = None
    if guess_seq_file_format(open(query_fpath)) != 'fasta':
        fasta_query_fhand = _create_temp_fasta_file(query_fpath)
        query_fpath = fasta_query_fhand.name

    #we have to create a database in BACKBONE_DIRECTORIES['blast_databases']
    if blast_db_seq:
        blast_db = make_backbone_blast_db(project_dir, blast_db_seq, dbtype)

    logger.info('Running the blast %s' % result_fpath)
    try:
        blast_runner_plus(query_fpath, blast_db, blast_program,
                                 result_fpath, threads=threads)
    except RuntimeError as error:
        if exists(result_fpath):
            remove(result_fpath)
        msg = '%s \n database: %s\n database type: %s' % (str(error),
                                                             blast_db, dbtype)
        raise RuntimeError(msg)

    if fasta_query_fhand:
        fasta_query_fhand.close()
    if fasta_db_fhand:
        fasta_db_fhand.close()

    return result_fpath

def make_backbone_blast_db(project_dir, blast_db_seq, dbtype):
    'It formats a blastdb when need it'
    logger = logging.getLogger(LOGGER_NAME)
    #the name should be the basename of the blast_db_seq
    db_dir = join(project_dir, BACKBONE_DIRECTORIES['blast_databases'])
    if not exists(db_dir):
        makedirs(db_dir)
    db_seq_fpath = join(db_dir, _get_basename(blast_db_seq))
    if not exists(db_seq_fpath):
        #which is the name of the new databae?
        blast_db_seq_format = guess_seq_file_format(open(blast_db_seq))
        if blast_db_seq_format == 'fasta':
            rel_symlink(blast_db_seq, db_seq_fpath)
        else:
            seqio(in_seq_fhand=open(blast_db_seq),
                  out_seq_fhand=open(db_seq_fpath, 'w'),
                  out_format='fasta')
        logger.info('Formatting the database %s' % db_seq_fpath)
        try:
            makeblastdb_plus(db_seq_fpath, dbtype=dbtype)
        except RuntimeError:
            msg = 'Error making blastdb. db:%s\n dbtype:%s\n' % \
                                               (db_seq_fpath, dbtype)
            remove(db_seq_fpath)
            raise RuntimeError(msg)
    return db_seq_fpath


#!flask/bin/python
from app import app  #导入app文件中__init__中app=Flask(__name__)
#1）当文件是被调用时，__name__的值为模块名；
#2）当文件被执行时，__name__的值为 ‘__main__’。
#基于此特性，为测试驱动开发提供了很好的支持，我们可以在每个模块中写上测试代码
#这些测试代码仅当模块被Python直接执行时才会运行，代码和测试完美的结合在一起。
#

@app.route('/', methods=['GET'], strict_slashes=False)
def namespaces():
    response = make_response("hello")
    return response

app.debug = True  #设置debug模式
app.run(host='0.0.0.0', port=6688, debug=True, use_reloader=False)


import time

import gym
import gym_rover

from gym import spaces

import numpy as np

from gym_rover.learning.ccea import CCEA

RENDER = True
GENS = 10000
NUM_POIS = 1
NUM_AGENTS = 1
TIME_LIMIT = 10
LENGTH = 10

class FitnessEval(object):
    def __init__(self, env):
        self.env = env
        self.input_shape = (1, 8)

    def fitness(self, team, debug=False):
        agents = team

        states = self.env.reset()
        done = False

        while not done:
            if RENDER:
                self.env.render()

            actions = []
            for i in range(self.env.num_agents):
                state = states[i]
                agent = agents[i]
                state = np.reshape(state, self.input_shape)
                action = agent.predict(state)
                actions.append(action)

            next_states, reward, done, info = self.env.step(np.array(actions))

        return [reward]

def init_ccea(env):
    fitness = FitnessEval(env)
    ccea = CCEA(env.num_agents, 12, [8,12,2], ['relu', 'relu', 'relu'], 0.05, fitness)
    return ccea

def init_env():
    env = gym.make('rover-cont-feature-v0')
    env._max_epsidoes = GENS * NUM_AGENTS * 12

    env.world_height = LENGTH
    env.world_width = LENGTH
    env.num_agents = NUM_AGENTS
    env.num_pois = NUM_POIS
    env.time_limit = TIME_LIMIT

    env.observation_mode = 'feature'

    env.set_observation_space()
    env.set_action_space()
    env.reset()
    return env

def run_ccea():
    env = init_env()
    ccea = init_ccea(env)

    for _ in range(10000):
        ccea.generation()
        print(ccea.best_team()[0])

if __name__ == "__main__":
    run_ccea()


import string

s = input()
delta = 0
index = 0
for i in range(26):
    index = s.find(string.ascii_lowercase[i])
    if index == -1:
        delta += 1
    else:
        s = s[index+1:]

print(delta)


# 1. 교재 - stack 사용, FIFO
# 자료 구조 : snake(뱀정보-배열/큐), info(방향정보-큐), data(그래프정보-2차원 배열)
n = int(input())
k = int(input())
data = [[0] * (n+1) for _ in range(n+1)]
info = []

for _ in range(k):
  a,b = map(int, input().split())
  data[a][b] = 1

l = int(input())
for _ in range(l):
  x, c = input().split()
  info.append((int(x),c))

dx = [0,1,0,-1]
dy = [1,0,-1,0]

def turn(direction, c):
  if c == "L":
    direction = (direction - 1) % 4
  else:
    direction = (direction + 1) % 4
  return direction

def simulate():
  x,y = 1,1
  data[x][y] = 2
  direction = 0
  time = 0
  index = 0
  # 꼬리가 앞 쪽
  snake = [(x,y)]
  while True:
    nx = x + dx[direction]
    ny = y + dy[direction]
    # 접근할 수 있는 곳이면
    if 1 <= nx <= n and 1 <= ny <= n and data[nx][ny] != 2 :
      if data[nx][ny] == 0:
        data[nx][ny] = 2
        snake.append((nx,ny))
        px, py = snake.pop(0)
        data[px][py] = 0
      if data[nx][ny] == 1 :
        data[nx][ny] = 2
        snake.append((nx,ny))
    # 접근 불가
    else:
      time += 1
      break

    # 여기부터는 다음 시간 체크
    time += 1
    x,y = nx, ny
    if index < l and time == info[index][0]:
      direction = turn(direction, info[index][1])
      index += 1
  return time

print(simulate())


#Given an array A of integers, find the maximum of j - i subjected to the constraint of A[i] <= A[j].

#If there is no solution possible, return -1.

from sys import maxint
def maximumGap(arr):
    n = len(arr)
    start = 0
    end = n-1
    maximum = -maxint-1
    if n == 0 or n==1:
        return 0

    while (start < end):
        if arr[end] >= arr[start]:
            prev_max = end -start
            if maximum < prev_max:
                maximum = prev_max
            start +=1
        else:
            end -=1
    return maximum


from __future__ import annotations

from typing import Generator

from ansible_collections.arista.avd.plugins.filter.convert_dicts import convert_dicts
from ansible_collections.arista.avd.plugins.plugin_utils.errors import AvdConversionWarning, AvdDeprecationWarning
from ansible_collections.arista.avd.plugins.plugin_utils.utils import get_all

SCHEMA_TO_PY_TYPE_MAP = {
    "str": str,
    "int": int,
    "bool": bool,
    "float": float,
    "dict": dict,
    "list": list,
}
SIMPLE_CONVERTERS = {
    "str": str,
    "int": int,
    "bool": bool,
}

class AvdDataConverter:
    """
    AvdDataConverter is used to convert AVD Data Types based on schema options.

    avdschema argument is an instance of AvdSchema. Type hinting is not working because of circular import
    TODO: Refactor to take a fully resolved schema as dict
    """

    def __init__(self, avdschema):
        self._avdschema = avdschema

        # We run through all the regular keys first, to ensure that all data has been converted
        # in case some of it is referenced in "dynamic_keys" below
        self.converters = {
            "items": self.convert_items,
            "keys": self.convert_keys,
            "dynamic_keys": self.convert_dynamic_keys,
            "deprecation": self.deprecation,
        }

    def convert_data(self, data, schema: dict = None, path: list[str] = None) -> Generator:
        """
        Perform in-place conversion of data according to the provided schema.
        Main entry function which is recursively called from the child functions performing the actual conversion of keys/items.
        """
        if schema is None:
            # Get fully resolved schema (where all $ref has been expanded recursively)
            schema = self._avdschema.resolved_schema

        if path is None:
            path = []

        for key, converter in self.converters.items():
            if key not in schema:
                # Ignore keys not in schema
                continue

            # Converters will do inplace update of data. Any returns will be yielded conversion messages.
            yield from converter(schema[key], data, schema, path)

    def convert_keys(self, keys: dict, data: dict, schema: dict, path: list[str]):
        """
        This function performs conversion on each key with the relevant subschema
        """
        if not isinstance(data, dict):
            return

        for key, childschema in keys.items():
            if key not in data:
                # Skip key since there is nothing to convert if the key is not set in data
                continue

            # Perform type conversion of the data for the child key if required based on "convert_types"
            if "convert_types" in childschema:
                yield from self.convert_types(childschema["convert_types"], data, key, childschema, path + [key])

            # Convert to lower case if set in schema and value is a string
            if childschema.get("convert_to_lower_case") and isinstance(data[key], str):
                data[key] = data[key].lower()

            yield from self.convert_data(data[key], childschema, path + [key])

    def convert_dynamic_keys(self, dynamic_keys: dict, data: dict, schema: dict, path: list[str]):
        """
        This function resolves "dynamic_keys" by looking in the actual data.
        Then calls convert_keys to performs conversion on each resolved key with the relevant subschema
        """
        if not isinstance(data, dict):
            return

        # Resolve "keys" from schema "dynamic_keys" by looking for the dynamic key in data.
        keys = {}
        for dynamic_key, childschema in dynamic_keys.items():
            resolved_keys = get_all(data, dynamic_key)
            for resolved_key in resolved_keys:
                keys.setdefault(resolved_key, childschema)

        # Reuse convert_keys to perform the actual conversion on the resolved dynamic keys
        yield from self.convert_keys(keys, data, schema, path)

    def convert_items(self, items: dict, data: list, schema: dict, path: list[str]):
        """
        This function performs conversion on each item with the items subschema
        """
        if not isinstance(data, list):
            return

        for index, item in enumerate(data):
            # Perform type conversion of the items data if required based on "convert_types"
            if "convert_types" in items:
                yield from self.convert_types(items["convert_types"], data, index, items, path + [index])

            # Convert to lower case if set in schema and item is a string
            if items.get("convert_to_lower_case") and isinstance(item, str):
                data[index] = item.lower()

            # Dive in to child items/schema
            yield from self.convert_data(item, items, path + [index])

    def convert_types(self, convert_types: list, data: dict | list, index: str | int, schema: dict, path: list[str]):
        """
        This function performs type conversion if necessary on a single data instance.
        It is invoked for child keys during "keys" conversion and for child items during
        "items" conversion

        "data" is either the parent dict or the parent list.
        "index" is either the key of the parent dict or the index of the parent list.

        Conversion is performed in-place using the provided "data" and "index"

        Yields AvdConversionWarning and/or AvdDeprecationWarning except for simple str/int/bool conversions

        Any conversion errors are ignored and the original value is returned
        """
        schema_type = schema.get("type")

        # Get value from input data
        value = data[index]

        # For simple conversions, skip conversion if the value is of the correct type
        if schema_type in SIMPLE_CONVERTERS and isinstance(value, SCHEMA_TO_PY_TYPE_MAP.get(schema_type)):
            # Avoid corner case where we want to convert bool to int. Bool is a subclass of Int so it passes the check above.
            if not (schema_type == "int" and isinstance(value, bool)):
                return

        for convert_type in convert_types:
            if isinstance(value, SCHEMA_TO_PY_TYPE_MAP.get(convert_type)):
                if schema_type in SIMPLE_CONVERTERS:
                    try:
                        data[index] = SIMPLE_CONVERTERS[schema_type](value)
                    except Exception:
                        # Ignore errors
                        # TODO: Log message
                        return

                    # Here we do not yield an AvdConversionWarning, since these will be accepted going forward.

                elif convert_type in ["dict", "list"] and schema_type == "list" and "primary_key" in schema:
                    try:
                        data[index] = convert_dicts(value, schema["primary_key"], secondary_key=schema.get("secondary_key"))
                    except Exception:
                        # Ignore errors
                        # TODO: Log message
                        return

                    if data[index] == value:
                        # No change - when input is list and have the correct format in all items
                        return

                    yield AvdConversionWarning(key=path, oldtype=convert_type, newtype=schema_type)

                elif convert_type == "dict" and schema_type == "list":
                    try:
                        data[index] = list(value)
                    except Exception:
                        # Ignore errors
                        # TODO: Log message
                        return

                    yield AvdConversionWarning(key=path, oldtype=convert_type, newtype=schema_type)

                elif convert_type == "str" and schema_type == "list":
                    try:
                        data[index] = list(map(str.strip, value.split(",")))
                    except Exception:
                        # Ignore errors
                        # TODO: Log message
                        return

                    yield AvdConversionWarning(key=path, oldtype=convert_type, newtype=schema_type)

    def deprecation(self, deprecation: dict, data, schema: dict, path: list):
        """
        deprecation:
          warning: bool, default = True
          new_key: str
          removed: bool
          remove_in_version: str
          remove_after_date: str
          url: str
        """

        if not deprecation.get("warning", True):
            return

        yield AvdDeprecationWarning(
            key=path,
            new_key=deprecation.get("new_key"),
            remove_in_version=deprecation.get("remove_in_version"),
            remove_after_date=deprecation.get("remove_after_date"),
            url=deprecation.get("url"),
            removed=deprecation.get("removed", False),
        )


import os
import argparse
from pathlib import Path

from dotenv import load_dotenv
import pandas as pd
from tqdm import tqdm
from langchain.llms import Ollama

from loggers import log_message_with_traceback

load_dotenv()
DE_TOOLS_LOG = os.getenv("DE_TOOLS_LOG")
JOBS_PROCESSED = os.getenv("JOBS_PROCESSED")
DE_TOOLS_OUT = os.getenv("DE_TOOLS_OUT")

def extract_de_tools(job_description: str) -> str:
    prompt = f"""Below is a job description for the role of a data engineer:\n`{job_description}`\n
    List the Data engineering software tools mentioned in the job description.
    Give only the list, no explanations needed."""
    return llm(prompt)

def process_and_save(data: pd.DataFrame, start_idx: int) -> None:
    data = data.loc[~data["Job_description"].isnull()].reset_index(drop=True)
    for idx, row in tqdm(
        data.iloc[start_idx:].iterrows(), total=len(data.iloc[start_idx:])
    ):
        try:
            job_description = row["Job_description"].strip()
            with open(Path(DE_TOOLS_OUT) / f"{row['Job_id']}.txt", "w") as file:
                file.write(extract_de_tools(job_description))
        except Exception as _:
            log_message_with_traceback(DE_TOOLS_LOG, f"failed index: {idx}")

def get_args():
    parser = argparse.ArgumentParser(
        prog="extract_de_tools",
        description="Extract Data Engineering tools from job descriptions and save to plain text files.",
    )
    parser.add_argument(
        "--llm_type",
        type=str,
        help="LLM model to use for extraction.",
        default="llama2",
    )
    parser.add_argument(
        "--start_idx",
        type=int,
        help="Start index to continue processing from a certain point in the csv.",
        default=0,
    )
    return parser.parse_args()

if __name__ == "__main__":
    args = get_args()

    llm = Ollama(model=args.llm_type)
    jobs_df = pd.read_csv(JOBS_PROCESSED)

    process_and_save(jobs_df, start_idx=args.start_idx)
    print("Processing Completed!!!!!!!!")


import warnings

warnings.filterwarnings("ignore")
import argparse
import torch
import os
import numpy as np
import pdb

from torch import nn, optim
from torch.utils import data
from torch.nn import functional as F
from data_utils import *
from vis_tools import *

# from model_utils import *
from torchvision.utils import save_image
from torchvision import transforms
from time import time
from tqdm import tqdm

from torch.optim.lr_scheduler import StepLR
from utils.trajectory_loader import PushDataset
from models.image_autoencoder import Decoder, Encoder

# Configurations and Hyperparameters
port_num = 8082
gpu_id = 1
lr_rate = 2e-4
num_epochs = 50
num_sample = 6
noise_dim = 2
report_feq = 10

display = visualizer(port=port_num)

# Random Initialization
torch.manual_seed(1)
np.random.seed(1)

def denorm(tensor):
    return ((tensor + 1.0) / 2.0) * 255.0

def norm(image):
    return (image / 255.0 - 0.5) * 2.0

# Dataloader
dataset = PushDataset("128_128_data")
loader = data.DataLoader(dataset, batch_size=16, shuffle=True)

# Models
encoder = Encoder().to(gpu_id)
decoder = Decoder().to(gpu_id)
decoder.weight_init(mean=0.0, std=0.02)
encoder.weight_init(mean=0.0, std=0.02)

# Initialize Loss
l1, mse, bce = nn.L1Loss(), nn.MSELoss(), nn.BCELoss()

# Initialize Optimizer
optimizer = optim.Adam(
    [{"params": decoder.parameters()}, {"params": encoder.parameters()}],
    lr=lr_rate,
    betas=(0.5, 0.999),
)

step = 0
min_pred_error = np.inf
for epoch in range(num_epochs):
    for i, inputs in enumerate(loader):
        ########## Inputs ########
        images, _, _, _ = inputs
        images = images.to(gpu_id)

        # Flatten image trajectories to image batch
        state_cur = images.view(-1, *(images.size()[2:]))
        # state_cur = norm(state_cur)

        z = encoder(state_cur)
        state_cur_hat = decoder(z)

        recon_loss = mse(state_cur_hat, state_cur)

        optimizer.zero_grad()
        recon_loss.backward()
        optimizer.step()

        step += 1

        recon_loss_np = recon_loss.cpu().data.numpy()
        print(epoch, step, "recon_loss_np: ", recon_loss_np)

        if step % report_feq == 0:
            state_cur_vis = denorm(state_cur[0]).detach().cpu().numpy().astype(np.uint8)
            state_cur_hat_vis = (
                denorm(state_cur_hat[0]).detach().cpu().numpy().astype(np.uint8)
            )

            display.img_result(state_cur_vis, win=1, caption="state_cur_vis")
            display.img_result(state_cur_hat_vis, win=2, caption="state_cur_hat_vis")

    if epoch % 10 == 1:
        if not os.path.exists("models"):
            os.makedirs("models")

        torch.save(encoder, "models/encoder_" + str(epoch) + ".pt")
        torch.save(decoder, "models/decoder_" + str(epoch) + ".pt")