import torch
import numpy as np
import torchvision.transforms as transforms
import torchvision
import matplotlib.pyplot as plt
from PIL import Image
import pickle
import math
import cv2
from skimage import img_as_ubyte
import logging
import warnings
warnings.filterwarnings("ignore")

from match_utils import matching, stats, proggan, nethook, dataset, loading, plotting, layers

def viz_matches(gan, discr, dataset, ganlayers, discrlayers, ganstats, discrstats, gan_mode, discr_mode, global_matches):

    '''Visualize Rosetta Neurons across all 6 models.'''

    #one example image
    num_ex = 1

    gan.eval()

    for i,_ in enumerate(discr):
        discr[i].eval()

    z = dataset[0]
    c = dataset[1]

    #### hook layers for GAN
    gan = nethook.InstrumentedModel(gan)
    gan.retain_layers(ganlayers)

    #### hook layers for discriminator
    for i, _ in enumerate(discr):
        model = nethook.InstrumentedModel(discr[i])
        model.retain_layers(discrlayers[i])
        discr[i] = model

    with torch.no_grad():

        for rank,_ in enumerate(global_matches):
            viz_list = []
            info_dict = {}
            for iii in range(len(discr)):
                ganidx = layers.find_act(list(global_matches.keys())[rank], ganlayers)

                info_dict["ganidx"] = ganidx

                if gan_mode == "biggan":
                    img = gan(z,c,1)
                    img = (img+1)/2
                elif gan_mode == "stylegan3":
                    img = gan(z,c)
                    img = (img+1)/2
                elif gan_mode == "projgan":
                    img = gan(z,c, truncation_psi = 0.7)
                    img = (img+1)/2
                elif gan_mode == "styleganxl":
                    img = gan(z,c, truncation_psi = 0.5)
                    img = (img+1)/2
                elif "stylegan2" in gan_mode:
                    img, _  = gan([z], 0.7, c)
                    img = (img+1)/2

                gan_act = gan.retained_layer(list(ganlayers)[ganidx[0]], clear = True)
                gan_act = matching.normalize(gan_act, ganstats[iii][ganidx[0]])

                ### through discriminator

                discridx = layers.find_act(global_matches[list(global_matches.keys())[rank]][iii], discrlayers[iii] )
                info_dict["discridx"+str(iii)] = discridx

                if discr_mode[iii] == "clip":
                    img = torch.nn.functional.interpolate(img, size = (224,224), mode = "bicubic")
                    img = torchvision.transforms.Normalize((0.48145466, 0.4578275, 0.40821073), (0.26862954, 0.26130258, 0.27577711))(img)
                    _ = discr[iii].model.encode_image(img)
                else:
                    img = torch.nn.functional.interpolate(img, size = (224,224), mode = "bicubic")
                    img = torchvision.transforms.Normalize((0.485, 0.456, 0.406), (0.229, 0.224, 0.225))(img)
                    _ = discr[iii](img)

                discr_act = discr[iii].retained_layer(list(discrlayers[iii])[discridx[0]], clear = True)
                discr_act = matching.normalize(discr_act, discrstats[iii][discridx[0]])

                ##### resize
                map_size = map_size = max((gan_act.shape[2], discr_act.shape[2]))
                gan_act = torch.nn.Upsample(size=(map_size,map_size), mode='bilinear')(gan_act)
                discr_act = torch.nn.Upsample(size=(map_size,map_size), mode='bilinear')(discr_act)
                scores = torch.mul(gan_act[:, ganidx[1], :, :], discr_act[:, discridx[1], :, :])
                scores = scores.view(scores.shape[0], -1)
                scores = torch.mean(scores, dim=-1, dtype = torch.float32)
                scores_sorted, indices = torch.sort(scores, descending = True)

                ex_list = []
                for ex in range(num_ex):
                    discr_act_viz1 = discr_act[indices[ex], discridx[1]]
                    discr_act_viz = discr_act_viz1.unsqueeze(0).unsqueeze(0)
                    discr_act_viz = torch.nn.Upsample(size=(img.shape[2], img.shape[3]), mode='nearest')(discr_act_viz).cpu()

                    gan_act_viz1 = gan_act[indices[ex], ganidx[1]]
                    gan_act_viz = gan_act_viz1.unsqueeze(0).unsqueeze(0)
                    gan_act_viz = torch.nn.Upsample(size=(img.shape[2], img.shape[3]), mode='nearest')(gan_act_viz).cpu()

                    img_viz = torch.permute(img[indices[ex]].cpu(), (1,2,0))
                    img_viz = ((img_viz-torch.min(img_viz))/(torch.max(img_viz)-torch.min(img_viz))).numpy()

                    ### list of visualizations for this example and discr
                    ex_list.append([img_viz, gan_act_viz, discr_act_viz, gan_act[indices[ex], ganidx[1]].cpu(),discr_act[indices[ex], discridx[1]].cpu()  ])

                viz_list.append(ex_list)

            for jjjj in range(len(ex_list)):
                fig=plt.figure(figsize=(15, 5))
                plt.axis("off")
                plt.title("Universal Match #" + str(rank+1)+" , Ex. "+str(jjjj+1), y=0.85)

                logger = logging.getLogger()
                old_level = logger.level
                logger.setLevel(100)
                alpha = 0.003
                num_plots = 2+len(discr)

                for kkkk in range(num_plots):
                    minifig= fig.add_subplot(1,num_plots, kkkk+1)
                    minifig.axis('off')
                    if kkkk == 0:
                        ax = plt.gca()
                        ax.set_title('Original Image',size=10)
                        plt.imshow(viz_list[kkkk][jjjj][0])

                    elif (kkkk==1):
                        ax = plt.gca()
                        ax.set_title("GAN Layer "+str(info_dict["ganidx"][0])+", Unit "+str(info_dict["ganidx"][1]),size=8)
                        plt.imshow(viz_list[kkkk][jjjj][3])
                    else:
                        discrunit = info_dict["discridx"+str(kkkk-2)]
                        ax = plt.gca()
                        ax.set_title("Discr. Layer "+str(discrunit[0])+", Unit "+str(discrunit[1]), fontsize = 8)
                        plt.imshow(viz_list[kkkk-2][jjjj][2][0,0])

                    logger.setLevel(old_level)


import os
import time

ship_requirement = 10
damage_requirement = 1000

def get_ships(data):
    return int(data.split("producing ")[1].split(" ships")[0])

def get_damage(data):
    return int(data.split("dealing ")[1].split(" damage")[0])

def get_rank(data):
    return int(data.split("rank #")[1].split(" and")[0])

player_1_wins = 0
player_2_wins = 0

for num in range(5000):
    try:
        print("Currently on: {}".format(num))
        if player_1_wins > 0 or player_2_wins > 0:
            p1_pct = round(player_1_wins/(player_1_wins+player_2_wins)*100.0, 2)
            p2_pct = round(player_2_wins/(player_1_wins+player_2_wins)*100.0, 2)
            print("Player 1 win: {}%; Player 2 win: {}%.".format(p1_pct, p2_pct))

        os.system('halite.exe -d "360 240" "python MyBot-Python.py" "python MyBot-Python.py" >> data.gameout')

        with open('data.gameout', 'r') as f:
            contents = f.readlines()
            MLBot1 = contents[-4]
            MLBot2 = contents[-3]
            print(MLBot1)
            print(MLBot2)

            MLBot1_ships = get_ships(MLBot1)
            MLBot1_dmg = get_damage(MLBot1)
            MLBot1_rank = get_rank(MLBot1)

            MLBot2_ships = get_ships(MLBot2)
            MLBot2_dmg = get_damage(MLBot2)
            MLBot2_rank = get_rank(MLBot2)

            print("Charles1 rank: {} ships: {} dmg: {}".format(MLBot1_rank,MLBot1_ships,MLBot1_dmg))
            print("Charles2 rank: {} ships: {} dmg: {}".format(MLBot2_rank,MLBot2_ships,MLBot2_dmg))

        if MLBot1_rank == 1:
            print("c1 won")
            player_1_wins += 1
            if MLBot1_ships >= ship_requirement and MLBot1_dmg >= damage_requirement:
                with open("c1_input.vec","r") as f:
                    input_lines = f.readlines()
                with open("train.in","a") as f:
                    for l in input_lines:
                        f.write(l)

                with open("c1_out.vec","r") as f:
                    output_lines = f.readlines()
                with open("train.out","a") as f:
                    for l in output_lines:
                        f.write(l)

        elif MLBot2_rank == 1:
            print("c2 won")
            player_2_wins += 1
            if MLBot2_ships >= ship_requirement and MLBot2_dmg >= damage_requirement:
                with open("c2_input.vec","r") as f:
                    input_lines = f.readlines()
                with open("train.in","a") as f:
                    for l in input_lines:
                        f.write(l)

                with open("c2_out.vec","r") as f:
                    output_lines = f.readlines()
                with open("train.out","a") as f:
                    for l in output_lines:
                        f.write(l)

        time.sleep(2)
    except Exception as e:
        print(str(e))
        time.sleep(2)


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

import sys
import os
import logging
from ruamel.yaml import YAML, YAMLError

class Config(object):
    """ Config loader class """

    ## Class constructor
    def __init__(self, logger: logging, path: str) -> None:

        ## get class name
        self.module_name = type(self).__name__

        self.logger = logger
        self.rootPath = path
        self.configDir = 'config'
        self.configFile = 'app.yaml'

        ## for caching configuration
        self.modulesConfigCache = None
        self.sensorsConfigCache = None

    def load_config(self, entity: str):
        try:
            stream = "{}{}{}{}{}".format(self.rootPath, os.sep, self.configDir, os.sep, self.configFile)
            yaml = YAML(typ='safe')
            content = yaml.load(open(stream))
            return content[entity]
        except (FileNotFoundError, AttributeError, YAMLError, KeyError, IndexError, ValueError, TypeError) as e:
            self.logger.critical('[{}] Cannot load configuration file. Details {}.'.format(self.module_name, e))
            sys.exit(1)

    def modules(self):
        if self.modulesConfigCache is None:
            self.logger.debug('[Config] Loading configuration of modules from config file.')
            self.modulesConfigCache = self.load_config('modules')

        return self.modulesConfigCache

    def sensors(self):
        if self.sensorsConfigCache is None:
            self.logger.debug('[Config] Loading configuration of sensors from config file.')
            self.sensorsConfigCache = self.load_config('sensors')

        return self.sensorsConfigCache


import uuid

import attrs
import cacholote.extra_encoders
import cads_broker.database
import cads_catalogue.config
import cads_catalogue.database
import fastapi
import ogc_api_processes_fastapi
import ogc_api_processes_fastapi.clients
import ogc_api_processes_fastapi.exceptions
import ogc_api_processes_fastapi.models
import sqlalchemy
import sqlalchemy.orm
import sqlalchemy.orm.attributes
import sqlalchemy.orm.decl_api
import sqlalchemy.orm.exc
import sqlalchemy.sql.selectable
import structlog

from . import adaptors, auth, config, db_utils, models, serializers, translators, utils
from .metrics import handle_download_metrics

logger: structlog.stdlib.BoundLogger = structlog.get_logger(__name__)

@attrs.define
class DatabaseClient(ogc_api_processes_fastapi.clients.BaseClient):
    """Database implementation of the OGC API - Processes endpoints.

    Attributes
    ----------
    process_table: type[cads_catalogue.database.Resource]
        Process record/table.
    job_table: type[cads_broker.database.SystemRequest]
        Job record/table.
    """

    process_table = cads_catalogue.database.Resource
    process_data_table = cads_catalogue.database.ResourceData
    job_table = cads_broker.database.SystemRequest

    def get_processes(
        self,
        limit: int | None = fastapi.Query(10, ge=1, le=10000),
        sortby: utils.ProcessSortCriterion | None = fastapi.Query(
            utils.ProcessSortCriterion.resource_uid_asc
        ),
        cursor: str | None = fastapi.Query(None, include_in_schema=False),
        back: bool | None = fastapi.Query(None, include_in_schema=False),
    ) -> ogc_api_processes_fastapi.models.ProcessList:
        """Implement OGC API - Processes `GET /processes` endpoint.

        Get the list of available processes' summaries.

        Parameters
        ----------
        limit : int | None, optional
            Specifies the number of process summaries to be included in the response.
        sortby : utils.ProcessSortCriterion | None, optional
            Specifies the sorting criterion for results. By default
            results are sorted by resource (process) uid in ascending alphabetical order.
        cursor : str | None, optional
            Hash string representing the reference to a particular process, used for pagination.
        back : bool | None, optional
            Specifies in which sense the list of processes should be traversed, used for pagination.
        """
        statement = sqlalchemy.select(self.process_table)
        sort_key, sort_dir = utils.parse_sortby(sortby.name)
        if cursor:
            statement = utils.apply_bookmark(
                statement, self.process_table, cursor, back, sort_key, sort_dir
            )
        statement = utils.apply_sorting(
            statement, self.process_table, back, sort_key, sort_dir
        )
        statement = utils.apply_limit(statement, limit)
        catalogue_sessionmaker = db_utils.get_catalogue_sessionmaker(
            db_utils.ConnectionMode.read
        )
        with catalogue_sessionmaker() as catalogue_session:
            processes_entries = catalogue_session.scalars(statement).all()
        processes = [
            serializers.serialize_process_summary(process)
            for process in processes_entries
        ]
        if back:
            processes = list(reversed(processes))
        process_list = ogc_api_processes_fastapi.models.ProcessList(
            processes=processes, links=[ogc_api_processes_fastapi.models.Link(href="")]
        )
        pagination_query_params = utils.make_pagination_query_params(
            processes, sort_key=sortby.lstrip("-")
        )
        process_list._pagination_query_params = pagination_query_params
        return process_list

    def get_process(
        self,
        response: fastapi.Response,
        process_id: str = fastapi.Path(...),
    ) -> ogc_api_processes_fastapi.models.ProcessDescription:
        """Implement OGC API - Processes `GET /processes/{process_id}` endpoint.

        Get the description of the process identified by `process_id`.

        Parameters
        ----------
        response : fastapi.Response
            fastapi.Response object.
        process_id : str
            Process identifier.

        Returns
        -------
        ogc_api_processes_fastapi.models.ProcessDescription
            Process description.
        """
        catalogue_sessionmaker = db_utils.get_catalogue_sessionmaker(
            db_utils.ConnectionMode.read
        )
        with catalogue_sessionmaker() as catalogue_session:
            resource = utils.lookup_resource_by_id(
                resource_id=process_id,
                table=self.process_table,
                session=catalogue_session,
            )
        process_description = serializers.serialize_process_description(resource)
        process_description.outputs = {
            "asset": ogc_api_processes_fastapi.models.OutputDescription(
                title="Asset",
                description="Downloadable asset description",
                schema_=ogc_api_processes_fastapi.models.SchemaItem(
                    type="object",
                    properties={
                        "value": cacholote.extra_encoders.FileInfoModel.schema()
                    },
                ),
            ),
        }

        response.headers[
            "cache-control"
        ] = config.ensure_settings().public_cache_control

        return process_description

    def post_process_execution(
        self,
        process_id: str = fastapi.Path(...),
        execution_content: ogc_api_processes_fastapi.models.Execute = fastapi.Body(...),
        auth_header: tuple[str, str] = fastapi.Depends(auth.get_auth_header),
        portal_header: str | None = fastapi.Header(
            None, alias=config.PORTAL_HEADER_NAME
        ),
    ) -> models.StatusInfo:
        """Implement OGC API - Processes `POST /processes/{process_id}/execution` endpoint.

        Request execution of a process.

        Parameters
        ----------
        process_id : str
            Process identifier.
        execution_content : models.Execute
            Details needed for the process execution.
        auth_header : tuple[str, str], optional
            Authorization header.

        Returns
        -------
        models.StatusInfo
            Submitted job's status information.
        """
        user_uid = auth.authenticate_user(auth_header, portal_header)
        structlog.contextvars.bind_contextvars(user_uid=user_uid)
        accepted_licences = auth.get_accepted_licences(auth_header)
        execution_content = execution_content.model_dump()
        catalogue_sessionmaker = db_utils.get_catalogue_sessionmaker(
            db_utils.ConnectionMode.read
        )
        with catalogue_sessionmaker() as catalogue_session:
            resource: cads_catalogue.database.Resource = utils.lookup_resource_by_id(
                resource_id=process_id,
                table=self.process_table,
                session=catalogue_session,
                load_messages=True,
            )
        adaptor = adaptors.instantiate_adaptor(resource)
        licences = adaptor.get_licences(execution_content)
        auth.validate_licences(accepted_licences, licences)
        job_id = str(uuid.uuid4())
        structlog.contextvars.bind_contextvars(job_id=job_id)
        job_kwargs = adaptors.make_system_job_kwargs(
            resource, execution_content, adaptor.resources
        )
        compute_sessionmaker = db_utils.get_compute_sessionmaker(
            mode=db_utils.ConnectionMode.write
        )
        with compute_sessionmaker() as compute_session:
            job = cads_broker.database.create_request(
                session=compute_session,
                request_uid=job_id,
                origin=auth.REQUEST_ORIGIN[auth_header[0]],
                user_uid=user_uid,
                process_id=process_id,
                portal=resource.portal,
                qos_tags=resource.qos_tags,
                **job_kwargs,
            )
        dataset_messages = [
            models.DatasetMessage(
                date=message.date,
                severity=message.severity,
                content=message.content,
            )
            for message in resource.messages
        ]
        status_info = utils.make_status_info(
            job, dataset_metadata={"messages": dataset_messages}
        )
        return status_info

    def get_jobs(
        self,
        processID: list[str] | None = fastapi.Query(None),
        status: list[ogc_api_processes_fastapi.models.StatusCode]
        | None = fastapi.Query(None),
        limit: int | None = fastapi.Query(10, ge=1, le=10000),
        sortby: utils.JobSortCriterion | None = fastapi.Query(
            utils.JobSortCriterion.created_at_desc
        ),
        cursor: str | None = fastapi.Query(None, include_in_schema=False),
        back: bool | None = fastapi.Query(None, include_in_schema=False),
        auth_header: tuple[str, str] = fastapi.Depends(auth.get_auth_header),
        portal_header: str | None = fastapi.Header(
            None, alias=config.PORTAL_HEADER_NAME
        ),
    ) -> models.JobList:
        """Implement OGC API - Processes `GET /jobs` endpoint.

        Get the list of submitted jobs, alongside information on their status.

        Parameters
        ----------
        processID : list[str] | None, optional
            If specified, only jobs that have a value for the processID property
            matching one of the specified values shall be included in the response.
        status : list[ogc_api_processes_fastapi.models.StatusCode] | None, optional
            If specified, only jobs that have a value for the status property matching
            one of the specified values of shall be included in the response.
        limit : int | None, optional
            Specifies the number of jobs to be included in the response.
        sortby : utils.JobSortCriterion | None, optional
            Specifies the sorting criterion for results. By default results are sorted
            by the job's creation date in descending order.
        cursor : str | None, optional
            Hash string representing the reference to a particular job, used for pagination.
        back : bool | None, optional
            Specifies in which sense the list of processes should be traversed, used for pagination.
        auth_header : tuple[str, str], optional
            Authorization header

        Returns
        -------
        models.JobList
            List of jobs status information.
        """
        user_uid = auth.authenticate_user(auth_header, portal_header)
        portals = [p.strip() for p in portal_header.split(",")]
        job_filters = {
            "process_id": processID,
            "status": status,
            "user_uid": [user_uid],
            "portal": portals,
        }
        sort_key, sort_dir = utils.parse_sortby(sortby.name)
        statement = sqlalchemy.select(self.job_table)
        statement = utils.apply_job_filters(statement, self.job_table, job_filters)
        if cursor:
            statement = utils.apply_bookmark(
                statement,
                self.job_table,
                cursor,
                back,
                sort_key,
                sort_dir,
            )
        statement = utils.apply_sorting(
            statement, self.job_table, back, sort_key, sort_dir
        )
        statement = utils.apply_limit(statement, limit)
        compute_sessionmaker = db_utils.get_compute_sessionmaker(
            mode=db_utils.ConnectionMode.read
        )
        with compute_sessionmaker() as compute_session:
            jobs_count = cads_broker.database.count_requests(
                session=compute_session,
                **job_filters,
            )
            job_entries = compute_session.scalars(statement).all()
        if back:
            job_entries = reversed(job_entries)
        jobs = []
        catalogue_sessionmaker = db_utils.get_catalogue_sessionmaker(
            db_utils.ConnectionMode.read
        )
        for job in job_entries:
            with catalogue_sessionmaker() as catalogue_session:
                try:
                    (dataset_title,) = utils.get_resource_properties(
                        resource_id=job.process_id,
                        properties="title",
                        table=self.process_table,
                        session=catalogue_session,
                    )
                except ogc_api_processes_fastapi.exceptions.NoSuchProcess:
                    dataset_title = config.ensure_settings().missing_dataset_title
            results = utils.parse_results_from_broker_db(job)
            jobs.append(
                utils.make_status_info(
                    job=job,
                    results=results,
                    dataset_metadata={"title": dataset_title},
                    qos={
                        "status": cads_broker.database.get_qos_status_from_request(job)
                    },
                )
            )
        job_list = models.JobList(
            jobs=jobs,
            links=[ogc_api_processes_fastapi.models.Link(href="")],
            metadata=models.JobListMetadata(totalCount=jobs_count),
        )
        pagination_query_params = utils.make_pagination_query_params(
            jobs, sort_key=sortby.lstrip("-")
        )
        job_list._pagination_query_params = pagination_query_params

        return job_list

    def get_job(
        self,
        job_id: str = fastapi.Path(...),
        auth_header: tuple[str, str] = fastapi.Depends(auth.get_auth_header),
        portal_header: str | None = fastapi.Header(
            None, alias=config.PORTAL_HEADER_NAME
        ),
        qos: bool = fastapi.Query(False),
        request: bool = fastapi.Query(False),
        log: bool = fastapi.Query(False),
    ) -> models.StatusInfo:
        """Implement OGC API - Processes `GET /jobs/{job_id}` endpoint.

        Get status information for the job identifed by `job_id`.

        Parameters
        ----------
        job_id : str
            Job identifer.
        auth_header : tuple[str, str], optional
            Authorization header
        portal_header : str | None, optional
            Portal header
        qos : bool, optional
            Whether to include job qos info in the response
        request : bool, optional
            Whether to include the request in the response
        log : bool, optional
            Whether to include the job's log in the response

        Returns
        -------
        models.StatusInfo
            Job status information.
        """
        user_uid = auth.authenticate_user(auth_header, portal_header)
        portals = [p.strip() for p in portal_header.split(",")]
        try:
            compute_sessionmaker = db_utils.get_compute_sessionmaker(
                mode=db_utils.ConnectionMode.read
            )
            with compute_sessionmaker() as compute_session:
                job = utils.get_job_from_broker_db(
                    job_id=job_id, session=compute_session
                )
                if qos:
                    job_qos_info = utils.collect_job_qos_info(job, compute_session)
        except ogc_api_processes_fastapi.exceptions.NoSuchJob:
            compute_sessionmaker = db_utils.get_compute_sessionmaker(
                mode=db_utils.ConnectionMode.write
            )
            with compute_sessionmaker() as compute_session:
                job = utils.get_job_from_broker_db(
                    job_id=job_id, session=compute_session
                )
                if qos:
                    job_qos_info = utils.collect_job_qos_info(job, compute_session)
        if job.portal not in portals:
            raise ogc_api_processes_fastapi.exceptions.NoSuchJob()
        auth.verify_permission(user_uid, job)
        kwargs = {}
        if request:
            request_ids = job.request_body["request"]
            catalogue_sessionmaker = db_utils.get_catalogue_sessionmaker(
                db_utils.ConnectionMode.read
            )
            with catalogue_sessionmaker() as catalogue_session:
                (form_data,) = utils.get_resource_properties(
                    resource_id=job.process_id,
                    properties="form_data",
                    table=self.process_data_table,
                    session=catalogue_session,
                )
            kwargs["request"] = {
                "ids": request_ids,
                "labels": translators.translate_request_ids_into_labels(
                    request_ids, form_data
                ),
            }
        if qos:
            kwargs["qos"] = {
                **job_qos_info,
                "status": cads_broker.database.get_qos_status_from_request(job),
            }
        if log:
            kwargs["log"] = utils.extract_job_log(job)
        status_info = utils.make_status_info(job=job, **kwargs)
        return status_info

    def get_job_results(
        self,
        job_id: str = fastapi.Path(...),
        auth_header: tuple[str, str] = fastapi.Depends(auth.get_auth_header),
        portal_header: str | None = fastapi.Header(
            None, alias=config.PORTAL_HEADER_NAME
        ),
    ) -> ogc_api_processes_fastapi.models.Results:
        """Implement OGC API - Processes `GET /jobs/{job_id}/results` endpoint.

        Get results for the job identifed by `job_id`.

        Parameters
        ----------
        job_id : str
            Identifier of the job.
        auth_header : tuple[str, str], optional
            Authorization header

        Returns
        -------
        ogc_api_processes_fastapi.models.Results
            Job results.
        """
        structlog.contextvars.bind_contextvars(job_id=job_id)
        user_uid = auth.authenticate_user(auth_header, portal_header)
        structlog.contextvars.bind_contextvars(user_id=user_uid)
        try:
            compute_sessionmaker = db_utils.get_compute_sessionmaker(
                mode=db_utils.ConnectionMode.read
            )
            with compute_sessionmaker() as compute_session:
                job = utils.get_job_from_broker_db(
                    job_id=job_id, session=compute_session
                )
            auth.verify_permission(user_uid, job)
            results = utils.get_results_from_job(job=job)
        except (
            ogc_api_processes_fastapi.exceptions.NoSuchJob,
            ogc_api_processes_fastapi.exceptions.ResultsNotReady,
        ):
            compute_sessionmaker = db_utils.get_compute_sessionmaker(
                mode=db_utils.ConnectionMode.write
            )
            with compute_sessionmaker() as compute_session:
                job = utils.get_job_from_broker_db(
                    job_id=job_id, session=compute_session
                )
            auth.verify_permission(user_uid, job)
            results = utils.get_results_from_job(job=job)
        handle_download_metrics(job.process_id, results)
        return results

    def delete_job(
        self,
        job_id: str = fastapi.Path(...),
        auth_header: tuple[str, str] = fastapi.Depends(auth.get_auth_header),
        portal_header: str | None = fastapi.Header(
            None, alias=config.PORTAL_HEADER_NAME
        ),
    ) -> ogc_api_processes_fastapi.models.StatusInfo:
        """Implement OGC API - Processes `DELETE /jobs/{job_id}` endpoint.

        Dismiss the job identifed by `job_id`.

        Parameters
        ----------
        job_id : str
            Identifier of the job.
        auth_header : tuple[str, str], optional
            Authorization header.

        Returns
        -------
        ogc_api_processes_fastapi.models.StatusInfo
            Job status information
        """
        structlog.contextvars.bind_contextvars(job_id=job_id)
        user_uid = auth.authenticate_user(auth_header, portal_header)
        structlog.contextvars.bind_contextvars(user_id=user_uid)
        compute_sessionmaker = db_utils.get_compute_sessionmaker(
            mode=db_utils.ConnectionMode.write
        )
        with compute_sessionmaker() as compute_session:
            job = utils.get_job_from_broker_db(job_id=job_id, session=compute_session)
            auth.verify_permission(user_uid, job)
            job = cads_broker.database.set_request_status(
                request_uid=job_id, status="dismissed", session=compute_session
            )
            job = utils.dictify_job(job)
        status_info = utils.make_status_info(job)
        return status_info


import helpers

def compute_allen_relations(scene):
    # Takes as input a scene object from the Scene class and computes Allen relations between every pairwise object
    # within that scene. RETURNS: a dictionary of object pair as key and corresponding allen relation in x direction
    # and y direction. CURRENTLY ONLY COMPUTING IN 2D plane.

    x =  [obj.get_name() for obj in scene.get_objects()]
    obj_pairs = []
    objs = scene.get_objects()
    for i in range(len(objs)):
        for j in range(i+1 , len(objs)):
            obj_pairs.append((objs[i],objs[j]))

    relations = {}
    for obj1, obj2 in obj_pairs:
        # Call the 3d version of the get info method to return x y z when needed
        obj1_info = obj1.get_2D_info()
        obj2_info = obj2.get_2D_info()

        is1x, ie1x, is2x, ie2x, is1y, ie1y, is2y, ie2y = helpers.rec2intervals(obj1_info,obj2_info)

        relX = _allen_relation(is1x, ie1x, is2x, ie2x, type = 'numeric')
        relY = _allen_relation(is1y, ie1y, is2y, ie2y, type = 'numeric')

        rel_key = obj1.get_name()+'/'+obj2.get_name()
        relations[rel_key] = [relX,relY]
        # returned as a tuple with first element as numeric and the second as categorical string representation

    return relations

def _allen_relation(is1, ie1, is2, ie2, type):
    # types (int, int, int, int) -> int, string
    # Takes in two intervals defined by the start and end point is and ie. Return the corresponding allen's relation
    # between the intervals

    if is2 - 1 == ie1:
        rel = 2 # 'meets'
        relS = 'm'

    elif is1 - 1 == ie2:
        rel = 11 # 'metby'
        relS = 'mi'

    elif is1 == is2 and ie1 == ie2:
        rel = 13 # 'equal'
        relS = 'e'

    elif is2 > ie1:
        rel = 1 # 'before'
        relS = 'b'

    elif is1 > ie2:
        rel = 12 # 'after'
        relS = 'a'

    elif ie1 >= is2 and ie1 < ie2 and is1 < is2:
        rel = 3 # 'overlaps'
        relS = 'o'

    elif ie2 >= is1 and ie2 < ie1 and is2 < is1:
        rel = 10 # 'overlapped_by'
        relS = 'oi'

    elif is1 > is2 and ie1 < ie2:
        rel = 5 # 'during'
        relS = 'd'

    elif is1 < is2 and ie1 > ie2:
        rel = 8 # 'contains'
        relS = 'c'

    elif is1 == is2 and ie1 < ie2:
        rel = 4 # 'starts'
        relS = 's'

    elif is1 == is2 and ie1 > ie2:
        rel = 9 # 'started_by'
        relS = 'si'

    elif ie1 == ie2 and is2 < is1:
        rel = 6 # 'finishes'
        relS = 'f'

    elif ie1 == ie2 and is2 > is1:
        rel = 7 # 'finished_by'
        relS = 'fi'

    if type == 'numeric':
        return rel
    elif type == 'categorical':
        return relS


#
# @Author: Akash Raj
# @Date: 2020-01-08 11:49:51
# @Last Modified by:   Akash Raj
# @Last Modified time: 2020-01-08 11:49:51
#

# joining method naive solution
# actually was needed to be done using binary search

# logic
# a=[n..elems]
# b=[m..elems]
# divide a and b such that total elems in right partition= total elems i left partition
# a=[a1,a2,a3,..,a left] [a right,..,an-1,an]
# b=[b1,b2,b3,..,b left] [b right,..,bn-1,bn]
#
# up or down the point of partition until you get a left<b right and b left<a right
# once point of partition is found which satisfies ^
# median= max(a left,b left) //if total elems=odd
# median= avg(max(a left,b left),min(a right,b right) //if total elems=even
#

def findMedianSortedArrays(A, B):
    a=A
    b=B

    if(len(a)==0 and len(b)==1):
        return b[0]
    if(len(b)==0 and len(a)==1):
        return a[0]
    size=len(a)+len(b);
    mid=(int)(size/2)
    ai=0;
    bi=0;
    prev=None
    curr=None
    r=None
    if(size%2==0):
        r=mid+1
    else:
        r=mid+1
    print(size,r)

    for i in range(r):
        # print(i)
        # print(ai,bi)
        # print(a[ai],b[bi])
        prev=curr
        if(ai==len(a)):
            curr=b[bi]
            bi+=1
        elif(bi==len(b)):
            curr=a[ai]
            ai+=1
        elif(a[ai]<b[bi]):
            curr=a[ai]
            ai+=1;
        elif(b[bi]<a[ai]):
            curr=b[bi]
            bi+=1
        elif(b[bi]==a[ai]):
            curr=b[bi]
            bi+=1
        print(curr)

    print("-------")
    if(size%2==0):
       print((float)(prev+curr)/2)
    else:
       print(curr)

# A =[1,4 ,5]
# B =[2 ,3]

# A =[ -50, -41, -40, -19, 5, 21, 28 ]
# B =[ -50, -21, -10 ]
# A=[]
# B=[0,23]

A =[ -37, -9, 10, 19 ]
B =[ -29, 18, 46 ]
findMedianSortedArrays(A,B)


import json
import os.path
from typing import Any, Dict

import tensorflow as tf

def display_hyperparams(
    dir: str,
) -> Dict[str, Any]:
    """
    Parse best found hyperparameters.

    Consumes `Tuner` output.
    """
    file_path = os.path.join(dir, "best_hyperparameters.txt")
    with tf.io.gfile.GFile(file_path, "r") as f:
        data = json.load(f)
    hparam_values: Dict[str, Any] = data[
        "values"
    ]  # skip the hparams search space dump
    return hparam_values


import torch
from module.metric import MetricBase

class EvaluatePack(object):
    def __init__(self,
                 metrics,
                 loss=None,
                 use_gpu=True
                 ):
        """

        Args:
            metrics: a dict of name to metric object
            loss:
        """
        self.metrics = metrics
        for name, m in metrics.items():
            if not isinstance(m, MetricBase):
                raise ValueError('The metirc must be subclass of MetricBase, but it is {}'.format(m))
        self.loss = loss

        self.device = torch.device('cuda' if torch.cuda.is_available() and use_gpu else 'cpu')

    def compute_metric(self, data_loader):
        result = {}
        # compute metrics per batch
        for idx, (inputs, targets) in enumerate(data_loader):
            result = self.compute_metric_step(inputs, targets)
        # return the final result
        for name, metirc in self.metrics.items():
            result[name] = metirc.streaming_value()

        return result

    def compute_metric_step(self, inputs, targets):
        inputs = inputs.to(self.device)
        targets = targets.to(self.device)
        ret = {}
        for name, metric in self.metrics.items():
            ret[name] = metric(inputs, targets)
        return ret


from scrapy.spiders import SitemapSpider
import re

class MySpider(SitemapSpider):
    name = "scrap_sitemap"
    #Use of the sitemap module
    sitemap_urls = ['http://www.marmiton.org/wsitemap_1.xml']
    sitemap_rules = [
        ('/recettes/', 'parse_recettes'),
    ]

    def parse_recettes(self, response):
        #Image parsing
        image_urls = []

        #Time parsing
        time = {}
        total = ('total', response.css(".title-2.recipe-infos__total-time__value::text").extract_first())
        preparation = ('preparation', response.css(".recipe-infos__timmings__preparation .recipe-infos__timmings__value::text").extract_first())
        cooking = ('cooking', response.css(".recipe-infos__timmings__cooking .recipe-infos__timmings__value::text").extract_first())
        safe_insert(total, time)
        safe_insert(preparation, time)
        safe_insert(cooking, time)

        #Ingredients parsing
        ingredients = []
        ingredients_selector = response.css(".recipe-ingredients__list__item")
        for ingredient in ingredients_selector:
            dict_ingredient = {}
            full_name = ingredient.css(".name_plural::attr(data-name-plural)").extract_first()
            prefix = ('prefix', re.split("  |' ", full_name)[0])
            name = ('name', re.split("  |' ", full_name)[1])
            complement = ('complement', ingredient.css(".recipe-ingredient__complement::text").extract_first())
            quantity = ('quantity', ingredient.css(".recipe-ingredient-qt::text").extract_first())
            image_url = ingredient.css(".ingredients-list__item__icon::attr(src)").extract_first()
            id = ('id', image_url.split('/')[-1].split('_')[0].replace('ingredient', 'unique'))
            image_urls.append(image_url)
            safe_insert(id, dict_ingredient)
            safe_insert(prefix, dict_ingredient)
            safe_insert(name, dict_ingredient)
            safe_insert(complement, dict_ingredient)
            safe_insert(quantity, dict_ingredient)

            ingredients.append(dict_ingredient)

        #Utensils parsing
        utensils = []
        utensils_selector = response.css(".recipe-utensil__name::text").extract()
        for utensil in utensils_selector:
            ustensil = utensil.strip("\r\n\t")
            if ustensil != "":
                utensils.append(ustensil)

        #Etapes parsing
        etapes = []
        etapes_selector = response.css(".recipe-preparation__list__item")
        for i, etape in enumerate(etapes_selector):
            description = ""
            for string in etape.css("::text").extract():
                description += string.strip("\r\n\t")

            dict = {
                'Etape' : i + 1,
                'Description' : description.replace("Etape " + str(i+1), '', 1)
            }
            etapes.append(dict)

        #Main parsing
        scraped_recipe = {'url': response.url, 'image_urls': image_urls}

        title = ('title', response.css("h1.main-title::text").extract_first())
        number_of_person = ('number_of_person', response.css(".title-2.recipe-infos__quantity__value::text").extract_first())
        rating = ('rating', response.css(".recipe-reviews-list__review__head__infos__rating__value::text").extract_first())
        level = ('level', response.css(".recipe-infos__level").xpath("div/@class").re_first(".$"))
        budget = ('budget', response.css(".recipe-infos__budget").xpath("div/@class").re_first(".$"))
        categories = ('categories', response.css(".mrtn-tag--grey::text").extract())

        safe_insert(title, scraped_recipe)
        safe_insert(number_of_person, scraped_recipe)
        safe_insert(rating, scraped_recipe)
        safe_insert(level, scraped_recipe)
        safe_insert(budget, scraped_recipe)
        safe_insert(categories, scraped_recipe)
        safe_insert(('time', time), scraped_recipe)
        safe_insert(('ingredients', ingredients), scraped_recipe)
        safe_insert(('utensils', utensils), scraped_recipe)
        safe_insert(('etapes', etapes), scraped_recipe)

        yield scraped_recipe

#Insert in the dict valid data
def safe_insert(data, dictio):
    (name, value) = data

    if isinstance(value, str) and value is not None and not value.isspace() and value != "":
        dictio[name] = value.strip("\r\n\t")

    elif isinstance(value, list) and value:
        dictio[name] = value

    elif isinstance(value, dict) and value:
        dictio[name] = value


"""Integration test for INSERT and SELECT."""
from ..context import py3odb

def test_read_sample(sample_odb):
    """Read a sample database."""
    conn = py3odb.connect(sample_odb)
    cur = conn.cursor()
    cur.execute(f"SELECT DISTINCT varno@body FROM '{sample_odb}'")
    varnos = cur.fetchall()
    assert len(varnos) == 3
    assert varnos[0][0] == 162
    assert varnos[1][0] == 241
    assert varnos[2][0] == 7
    conn.close()

def test_fetchmany(sample_odb):
    """Read a database using fetchmany."""
    conn = py3odb.connect(sample_odb)
    cur = conn.cursor()
    cur.execute(f"SELECT DISTINCT varno@body FROM <odb>;")
    rows = cur.fetchmany(4)
    conn.close()
    assert len(rows) == 3
    assert rows[0]["varno@body"] == 162
    assert rows[1]["varno@body"] == 241
    assert rows[2]["varno@body"] == 7


from collections import defaultdict
from bisect import bisect_left, bisect_right
import copy
"""TLE"""
# class RangeFreqQuery(object):
#     def __init__(self, arr):
#         """
#         :type arr: List[int]
#         """
#         self.arr = arr
#         self.arr_dict = defaultdict(list)
#         for i in range(len(self.arr)):
#             self.arr_dict[self.arr[i]].append(i)

#     def query(self, left, right, value):
#         """
#         :type left: int
#         :type right: int
#         :type value: int
#         :rtype: int
#         """
#         if not self.arr_dict[value]: return 0
#         res = 0
#         flag = 0
#         indexs =copy.deepcopy(self.arr_dict[value])
#         if not left in indexs:
#             flag = flag - 1
#             indexs.append(left)
#         if not right in indexs:
#             flag = flag - 1
#             indexs.append(right)
#         indexs.sort()
#         i_left = indexs.index(left)
#         i_right = indexs.index(right)
#         return len(indexs[i_left:i_right+1])+flag
class RangeFreqQuery:
    def __init__(self, arr):
        self.O = O = defaultdict(list)
        for i, a in enumerate(arr):
            O[a].append(i)

        print(self.O)

    def query(self, left: int, right: int, v: int) -> int:
        """
        https://docs.python.org/3/library/bisect.html
        bisect_left/right if x exists return index, else return the insertion index
        bisect.bisect_left(a, x, lo=0, hi=len(a), *, key=None)
        all(val < x for val in a[lo : i]) for the left side and all(val >= x for val in a[i : hi]) for the right side.

        bisect.bisect(a, x, lo=0, hi=len(a))
        all(val <= x for val in a[lo : i]) for the left side and all(val > x for val in a[i : hi]) for the right side.
        """
        _all = self.O[v]
        l = bisect_left(_all, left)
        r = bisect_right(_all, right)

        return r-l

# Your RangeFreqQuery object will be instantiated and called as such:
arr = []
obj = RangeFreqQuery([2,2,1,2,2])
param_1 = obj.query(2, 4, 1)
param_2 = obj.query(1, 3, 1)
param_3 = obj.query(0, 2, 1)

Daily attendance/5186. Range Frequency Queries.py


import types
from typing import Tuple, Union, Dict, Callable

import tensorflow as tf
import numpy as np

def _check_evaluation_args(
        sess: tf.Session,
        input_node: Union[tf.Tensor, str],
        reference_nodes: dict,
        calibration_data: Callable[[], types.GeneratorType]):

    if not isinstance(sess, tf.Session):
        raise TypeError("Specified session must be a valid tf.Session object")

    # if not isinstance(calibration_data, DataGenerator):
    #     raise TypeError("Specified calibration data must be an instance of DataGenerator class")

    if not isinstance(input_node, (tf.Tensor, str)):
        raise TypeError("Input node must be whether a tensor or a node name")

    if not isinstance(reference_nodes, dict):
        raise TypeError("Reference nodes must be presented via a dictionary")

    if not all([isinstance(node_name, str) for node_name in reference_nodes.keys()]):
        raise TypeError("One of the specified reference nodes has a non-string name")

    if not all([isinstance(node, tf.Tensor) for node in reference_nodes.values()]):
        raise TypeError("One of the specified reference nodes is not a tensor")

def _eval_threshold_for_one_node(
        output_node: tf.Tensor,
        input_node: Union[tf.Tensor, str],
        sess: tf.Session,
        feed_data_generator: types.GeneratorType) -> Tuple[float, float]:

    res_min = np.Inf
    res_max = -np.Inf

    for data_feed in feed_data_generator:
        res = sess.run(output_node, feed_dict={input_node: data_feed})
        res_min = np.minimum(res_min, np.min(res))
        res_max = np.maximum(res_max, np.max(res))

    return res_min, res_max

def eval_thresholds(sess, input_node, reference_nodes, calibration_data) -> Dict[str, Dict[str, float]]:
    """

    Parameters
    ----------
    sess: tf.Session
    input_node: Union[tf.Tensor, str]
    reference_nodes: Dict[str, tf.Tensor]
    calibration_data: Callable[[], types.GeneratorType]

    Returns
    -------
    dict:
        A dictionary containing min and max thresholds for the reference nodes
    """
    _check_evaluation_args(sess, input_node, reference_nodes, calibration_data)

    thresholds = dict()

    output_nodes = [node_name for node_name in reference_nodes if "weights" not in node_name.split('/')[-1]]
    weights_nodes = [node_name for node_name in reference_nodes if "weights" in node_name.split('/')[-1]]

    for w_node in weights_nodes:
        res = sess.run(reference_nodes[w_node])

        thresholds[w_node] = {"min": np.min(res),
                              "max": np.max(res)}

    for o_node in output_nodes:
        res_min, res_max = _eval_threshold_for_one_node(reference_nodes[o_node],
                                                        input_node,
                                                        sess,
                                                        calibration_data())

        thresholds[o_node] = {"min": res_min,
                              "max": res_max}

    return thresholds


#!/usr/bin/env python3
# pylint: disable=too-many-locals, too-many-branches, too-many-statements, line-too-long, unnecessary-lambda-assignment
# noqa: E501
"""
Peering Buddy - Helping you dig data from internet for better decisions!
"""

import sys
import argparse
import json

from pbuddy.pbuddy import PBuddy

def main():
    """Peering Buddy main"""
    formatter = lambda prog: argparse.HelpFormatter(prog, max_help_position=88)
    parser = argparse.ArgumentParser(
        description="Peering Buddy - Helping you dig data from internet for better decisions!",
        formatter_class=formatter,
    )
    parser.add_argument(
        "-av",
        "--asn-visibility",
        action="store",
        dest="asn_visibility",
        metavar="ASN",
        help="[RIPE] Check ASN visibility RIPE RIS sensors.",
    )
    parser.add_argument(
        "-ap",
        "--asn-announced-pfxs",
        action="store",
        dest="asn_announcedpfxs",
        metavar="ASN",
        help="[RIPE] Check ASN announced prefixes to internet.",
    )
    parser.add_argument(
        "-ar",
        "--asn-roa-validation",
        action="store",
        dest="asn_roavalidation",
        metavar="ASN",
        help="[RIPE] Check ASN RPKI/ROA validation for announced prefixes.",
    )
    parser.add_argument(
        "-lg",
        "--looking-glass",
        action="store",
        dest="pfx_rislg",
        metavar="PREFIX",
        help="[RIPE] Get prefix using RIPE RIS as Looking Glass.",
    )
    parser.add_argument(
        "-al",
        "--aspath-length-overview",
        action="store",
        dest="asn_aspathoverview",
        metavar="ASN",
        help="[RIPE] Check AS-Path length overview.",
    )
    parser.add_argument(
        "-as",
        "--aspath-lenghth-stripped",
        action="store",
        dest="asn_aspathstripped",
        metavar="ASN",
        help="[RIPE] Check AS-Path length stripped [no as-prepend].",
    )
    parser.add_argument(
        "-au",
        "--aspath-lenghth-unstripped",
        action="store",
        dest="asn_aspathunstripped",
        metavar="ASN",
        help="[RIPE] Check AS-Path length unstripped [with as-prepend].",
    )
    parser.add_argument(
        "-tm",
        "--threshold-max",
        action="store",
        dest="asn_aspaththresholdmax",
        metavar="INTEGER",
        help="[RIPE][as|au] Threshold [>=] to be used with -as and -au for max.",
    )
    parser.add_argument(
        "-ti",
        "--threshold-min",
        action="store",
        dest="asn_aspaththresholdmin",
        metavar="INTEGER",
        help="[RIPE][as|au] Threshold [>=] to be used with -as and -au for min.",
    )
    parser.add_argument(
        "-ta",
        "--threshold-avg",
        action="store",
        dest="asn_aspaththresholdavg",
        metavar="INTEGER",
        help="[RIPE][as|au] Threshold [>=] to be used with -as and -au for avg.",
    )
    parser.add_argument(
        "-ao",
        "--asn-overview",
        action="store",
        dest="asn_overview",
        metavar="ASN",
        help="[RIPE] Check ASN public resources overview.",
    )
    parser.add_argument(
        "-ac",
        "--asn-announce-consistency",
        action="store",
        dest="asn_announcesconsistency",
        metavar="ASN",
        help="[RIPE][BGPView][IPInfo] Check ASN announces consistency.",
    )
    parser.add_argument(
        "-pa",
        "--asn-pfxs-aspath-length",
        action="store",
        dest="asn_asnpfxaspathlength",
        metavar=("ASN", "THRESHOLD", "PREPEND[y|n]"),
        help="[RIPE][BGPView] Check ASN prefixes where as-path length >= threshold.",
        nargs=3,
    )
    parser.add_argument(
        "-tu",
        "--asn-upstreams-transient",
        action="store",
        dest="asn_upstreamtransient",
        metavar="ASN",
        help="[RIPE][BGPView] Check ASN upstreams on transient paths.",
    )
    parser.add_argument(
        "-gu",
        "--asn-upstreams",
        action="store",
        dest="upstreams",
        metavar="ASN",
        help="[BGPView] Get ASN upstreams.",
    )
    parser.add_argument(
        "-gd",
        "--asn-downstreams",
        action="store",
        dest="downstreams",
        metavar="ASN",
        help="[BGPView] Get ASN downstreams.",
    )
    parser.add_argument(
        "-gw",
        "--whois",
        action="store",
        dest="whois",
        metavar="[ASN|PREFIX]",
        help="[BGPView] Get ASN/Prefix whois information.",
    )
    parser.add_argument(
        "-wi",
        "--whois-ip",
        action="store",
        dest="ipwhois",
        metavar="IP",
        help="[IPInfo] Get IP whois information.",
    )
    parser.add_argument(
        "-ip",
        "--pdb-ixp-pfxs",
        action="store_true",
        dest="pdb_ip",
        help="[PeeringDB] Get IXPs prefixes.",
    )
    parser.add_argument(
        "-ai",
        "--pdb-asn-info",
        action="store",
        dest="asninfo",
        metavar="ASN",
        help="[PeeringDB] Get ASN information on PeeringDB.",
    )
    parser.add_argument(
        "-ii",
        "--pdb-asn-ips",
        action="store",
        dest="ixpips",
        metavar="ASN",
        help="[PeeringDB] Get ASN IPS allocated on IXPs.",
    )
    parser.add_argument(
        "-gc",
        "--pdb-asn-contact",
        action="store",
        dest="asncontact",
        metavar="ASN",
        help="[PeeringDB] Get ASN contact.",
    )
    parser.add_argument(
        "-cc",
        "--pdb-ixp-bycc",
        action="store",
        dest="ixpcc",
        metavar="ASN",
        help="[PeeringDB] Get IXPs by Country Code [iso-3166-1 alpha-2].",
    )
    parser.add_argument(
        "-gl",
        "--lgs",
        action="store_true",
        dest="lgs",
        help="[Team Cymrus] Check a list of public LookingGlass.",
    )
    parser.add_argument(
        "-bo",
        "--bogons",
        action="store_true",
        dest="bogonspfx4",
        help="[Team Cymrus] Get ip4 bogons list.",
    )
    parser.add_argument(
        "-b4",
        "--bogons-v4",
        action="store_true",
        dest="fbogonspfx4",
        help="[Team Cymrus] Get ip4 full (+unallocated) bogons list.",
    )
    parser.add_argument(
        "-b6",
        "--bogons-v6",
        action="store_true",
        dest="fbogonspfx6",
        help="[Team Cymrus] Get ip6 full (+unallocated) bogons list.",
    )
    parser.add_argument(
        "-ba",
        "--bogons-asn",
        action="store_true",
        dest="bogonsasn",
        help="[NTT] Get ASN bogons list/examples.",
    )
    parser.add_argument(
        "-aa",
        "--asset",
        action="store",
        dest="asset",
        metavar="ASN",
        help="[NLNOG] Check ASN AS-SET and expand it.",
    )
    parser.add_argument(
        "-rh",
        "--resource-health-check",
        action="store",
        dest="resourcehealthcheck",
        metavar="ASN|PREFIX",
        help="[NLNOG] ASN or Prefix health check.",
    )
    parser.add_argument(
        "-nv",
        "--non-verbose",
        action="store_true",
        dest="nonverbose",
        help="Remove human-like text to the output.",
    )

    args = parser.parse_args()
    options = all(value is True for value in vars(args).values())
    pbuddy = PBuddy()

    re_asn = "^[0-9]{0,9}$"
    re_cc = "^[a-zA-Z]{0,2}$"
    re_int = "^[0-9]{0,2}$"
    re_yn = "^[yYnN]$"
    asn_invalid = "Invalid ASN, please type the ASN without the suffix AS."
    pfx_invalid = "Invalid prefix (v4/v6), please type prefix/mask."
    separator = "=" * 80

    if args.asn_visibility is not None:
        reasn = pbuddy.regex_validation(re_asn, args.asn_visibility)
        if reasn is False:
            print(asn_invalid)
            sys.exit(1)
        result = pbuddy.ripe_asn_visibility(args.asn_visibility)
        if args.nonverbose is False:
            print(separator)
            print(
                "=> Visibilit percentage (RIS point of view)",
                args.asn_visibility,
                ":",
            )
            print(separator)
        for afi, perc in result.items():
            print(f"Visibility for {afi}: {perc}%")
        if args.nonverbose is False:
            print(separator)
    if args.asn_announcedpfxs is not None:
        regexp_asn = pbuddy.regex_validation(re_asn, args.asn_announcedpfxs)
        if regexp_asn is False:
            print(asn_invalid)
            sys.exit(1)
        pfxs = pbuddy.ripe_asn_announced_pfx(args.asn_announcedpfxs)
        if args.nonverbose is False:
            print(separator)
            print(
                "=> We are seeing the prefixes being announced to the internet for the ASN",
                args.asn_announcedpfxs,
                ":",
            )
            print(separator)
        print(json.dumps(pfxs, indent=4))
        if args.nonverbose is False:
            print(separator)
    if args.asn_roavalidation is not None:
        regexp_asn = pbuddy.regex_validation(re_asn, args.asn_roavalidation)
        if regexp_asn is False:
            print(asn_invalid)
            sys.exit(1)
        if args.nonverbose is False:
            print(separator)
            print(
                "=> We are validating the prefixes announced by the ASN",
                args.asn_roavalidation,
                ":",
            )
            print(separator)
        prefixes = pbuddy.ripe_asn_announced_pfx(args.asn_roavalidation)
        for prefix in prefixes:
            result = pbuddy.ripe_vrp_check(args.asn_roavalidation, prefix)
            print("Prefix", prefix, "is", result)
        if args.nonverbose is False:
            print(separator)
    if args.pfx_rislg is not None:
        repfx = pbuddy.pfx_validation(args.pfx_rislg)
        if repfx is False:
            print(pfx_invalid)
            sys.exit(1)
        field = None
        result = pbuddy.ripe_ris_lg(args.pfx_rislg, field)
        if args.nonverbose is False:
            print(separator)
            print("=> Looking glass results for the prefix", args.pfx_rislg, ":")
            print(separator)
        print(json.dumps(result, indent=4))
        if args.nonverbose is False:
            print(separator)
    if args.asn_aspathoverview is not None:
        reasn = pbuddy.regex_validation(re_asn, args.asn_aspathoverview)
        if reasn is False:
            print(asn_invalid)
            sys.exit(1)
        result = pbuddy.ripe_aspth_length_overview(args.asn_aspathoverview)
        aspath_s_max = result[0]
        aspath_s_min = result[1]
        aspath_s_avg = result[2]
        aspath_u_max = result[3]
        aspath_u_min = result[4]
        aspath_u_avg = result[5]
        print(separator)
        print("=> AS-Path length overview for the ASN", args.asn_aspathoverview, ":")
        print(separator)
        print("Maximum AS-PATH Stripped [ignore as-prepend] => ", aspath_s_max)
        print("Minimum AS-PATH Stripped [ignore as-prepend] => ", aspath_s_min)
        print("Average AS-PATH Stripped [ignore as-prepend] => ", aspath_s_avg)
        print("Maximum AS-PATH Unstripped [considering as-prepend] => ", aspath_u_max)
        print("Minimum AS-PATH Unstripped [considering as-prepend] => ", aspath_u_min)
        print("Average AS-PATH Unstripped [considering as-prepend] => ", aspath_u_avg)
        print(separator)
    if args.asn_aspathstripped is not None:
        reasn = pbuddy.regex_validation(re_asn, args.asn_aspathstripped)
        if reasn is False:
            print(asn_invalid)
            sys.exit(1)
        if (
            args.asn_aspaththresholdmax is not None
            or args.asn_aspaththresholdmin is not None
            or args.asn_aspaththresholdavg is not None
        ):
            func = ["max", "min", "avg"]
            values = [
                args.asn_aspaththresholdmax,
                args.asn_aspaththresholdmin,
                args.asn_aspaththresholdavg,
            ]
            for value in values:
                if value:
                    regex_int = pbuddy.regex_validation(re_int, str(value))
                    if regex_int is False:
                        print(
                            "That's not a valid integer, please type an integer from 1 to 2 digits."
                        )
                        sys.exit(1)
            threshold = dict(zip(func, values))
            result = pbuddy.ripe_aspath_length(
                args.asn_aspathstripped, "stripped", func, threshold
            )
        else:
            result = pbuddy.ripe_aspath_length(
                args.asn_aspathstripped, "stripped", None, None
            )
        if args.nonverbose is False:
            print(separator)
            print(
                "=> AS-Path length (min, max and avg - stripping as-prepends) for the ASN",
                args.asn_aspathstripped,
                ":",
            )
            print(separator)
        print(json.dumps(result, indent=4))
        if args.nonverbose is False:
            print(separator)
    if args.asn_aspathunstripped is not None:
        reasn = pbuddy.regex_validation(re_asn, args.asn_aspathunstripped)
        if reasn is False:
            print(asn_invalid)
            sys.exit(1)
        if (
            args.asn_aspaththresholdmax is not None
            or args.asn_aspaththresholdmin is not None
            or args.asn_aspaththresholdavg is not None
        ):
            func = ["max", "min", "avg"]
            values = [
                args.asn_aspaththresholdmax,
                args.asn_aspaththresholdmin,
                args.asn_aspaththresholdavg,
            ]
            for value in values:
                if value:
                    regex_int = pbuddy.regex_validation(re_int, str(value))
                    if regex_int is False:
                        print(
                            "That's not a valid integer, please type an integer from 1 to 2 digits."
                        )
                        sys.exit(1)
            threshold = dict(zip(func, values))
            result = pbuddy.ripe_aspath_length(
                args.asn_aspathunstripped, "unstripped", func, threshold
            )
        else:
            result = pbuddy.ripe_aspath_length(
                args.asn_aspathunstripped, "unstripped", None, None
            )
        if args.nonverbose is False:
            print(separator)
            print(
                "=> AS-Path length (min, max and avg - unstripping as-prepends) for the ASN",
                args.asn_aspathunstripped,
                ":",
            )
            print(separator)
        print(json.dumps(result, indent=4))
        if args.nonverbose is False:
            print(separator)
    if args.asn_overview is not None:
        reasn = pbuddy.regex_validation(re_asn, args.asn_overview)
        if reasn is False:
            print(asn_invalid)
            sys.exit(1)
        result = pbuddy.ripe_asn_resources_overview(args.asn_overview)
        if args.nonverbose is False:
            print(separator)
            print(
                "=> Public Internet resources overview for the ASN",
                args.asn_overview,
                ":",
            )
            print(separator)
        print(json.dumps(result, indent=4))
        if args.nonverbose is False:
            print(separator)
    if args.asn_announcesconsistency is not None:
        reasn = pbuddy.regex_validation(re_asn, args.asn_announcesconsistency)
        if reasn is False:
            print(asn_invalid)
            sys.exit(1)
        if args.nonverbose is False:
            print(separator)
            print(
                "=> ASN announces consistency for the ASN",
                args.asn_announcesconsistency,
                ":",
            )
            print(separator)
        result = pbuddy.ripe_asn_announces_consistency(args.asn_announcesconsistency)
        for item in result:
            print("".join(map(str, item)))
        if args.nonverbose is False:
            print(separator)
    if args.lgs is True:
        result = pbuddy.tc_public_lg()
        if args.nonverbose is False:
            print(separator)
            print("=> List of public looking glass.")
            print(separator)
        for key, value in result.items():
            print(key, "=>", value[0])
        if args.nonverbose is False:
            print(separator)
    if args.asset is not None:
        reasn = pbuddy.regex_validation(re_asn, args.asset)
        if reasn is False:
            print(asn_invalid)
            sys.exit(1)
        result = pbuddy.pdb_asn_asset(args.asset)
        asset = result[0]
        expanded = pbuddy.nlnog_expand_asset(asset[args.asset])
        if args.nonverbose is False:
            print(separator)
        print(json.dumps(expanded, indent=4))
        if args.nonverbose is False:
            print(separator)

    if args.resourcehealthcheck is not None:
        reasn = pbuddy.regex_validation(re_asn, args.resourcehealthcheck)
        repfx = pbuddy.pfx_validation(args.resourcehealthcheck)
        if reasn is False and repfx is False:
            print(
                "That's not a valid ASN or prefix, please type the ASN without the suffix AS."
            )
            sys.exit(1)
        if reasn is True:
            resource_type = "asn"
        elif repfx is True:
            resource_type = "prefix"
        rhc = pbuddy.nlnog_resource_health_check(
            args.resourcehealthcheck, resource_type
        )
        if args.nonverbose is False:
            print(separator)
        print(json.dumps(rhc, indent=4))
        if args.nonverbose is False:
            print(separator)

    if args.pdb_ip is True:
        if args.nonverbose is False:
            print(separator)
            print("=> IXPs prefixes:")
            print(separator)
        result = pbuddy.pdb_ixps_pfxs()
        for item in result:
            print("".join(map(str, item)))
        if args.nonverbose is False:
            print(separator)
    if args.asninfo is not None:
        reasn = pbuddy.regex_validation(re_asn, args.asninfo)
        if reasn is False:
            print(asn_invalid)
            sys.exit(1)
        if args.nonverbose is False:
            print(separator)
            print("=> ASN ", args.asninfo, " info/summary:")
            print(separator)
        result = pbuddy.pdb_asn_info(args.asninfo)
        print(json.dumps(result, indent=4))
        if args.nonverbose is False:
            print(separator)
    if args.ixpips is not None:
        reasn = pbuddy.regex_validation(re_asn, args.ixpips)
        if reasn is False:
            print(asn_invalid)
            sys.exit(1)
        if args.nonverbose is False:
            print(separator)
            print("=> Allocated IXPs IPs for the ASN ", args.ixpips, ":")
            print(separator)
        result = pbuddy.pdb_asn_ixps_ips(args.ixpips)
        for item in result:
            print("".join(map(str, item)))
        if args.nonverbose is False:
            print(separator)
    if args.asncontact is not None:
        reasn = pbuddy.regex_validation(re_asn, args.asncontact)
        if reasn is False:
            print(asn_invalid)
            sys.exit(1)
        if args.nonverbose is False:
            print(separator)
            print("=> ASN ", args.asncontact, " contacts:")
            print(separator)
        result = pbuddy.pdb_asn_contacts(args.asncontact)
        print(json.dumps(result, indent=4))
        if args.nonverbose is False:
            print(separator)
    if args.ixpcc is not None:
        reasn = pbuddy.regex_validation(re_cc, args.ixpcc)
        if reasn is False:
            print(
                "That's not a valid Country Code, please type the CC with two letters (IBAN Alpha-2)."
            )
            sys.exit(1)
        if args.nonverbose is False:
            print(separator)
            print("=> IXPs available on ", args.ixpcc, ":")
            print(separator)
        result = pbuddy.pdb_ixps_by_cc(args.ixpcc)
        print(json.dumps(result, indent=4))
        if args.nonverbose is False:
            print(separator)
    if args.bogonspfx4 is True:
        if args.nonverbose is False:
            print(separator)
            print("=> IPv4 bogons list:")
            print(separator)
        result = pbuddy.tc_bogons_pfxs(
            "https://www.team-cymru.org/Services/Bogons/bogon-bn-nonagg.txt"
        )
        for item in result:
            print("".join(map(str, item)))
        if args.nonverbose is False:
            print(separator)
    if args.fbogonspfx4 is True:
        if args.nonverbose is False:
            print(separator)
            print("=> IPv4 full (+unallocated) bogons list:")
            print(separator)
        result = pbuddy.tc_bogons_pfxs(
            "https://www.team-cymru.org/Services/Bogons/fullbogons-ipv4.txt"
        )
        for item in result:
            print("".join(map(str, item)))
        if args.nonverbose is False:
            print(separator)
    if args.fbogonspfx6 is True:
        if args.nonverbose is False:
            print(separator)
            print("=> IPv6 full (+unallocated) bogons list:")
            print(separator)
        result = pbuddy.tc_bogons_pfxs(
            "https://www.team-cymru.org/Services/Bogons/fullbogons-ipv6.txt"
        )
        for item in result:
            print("".join(map(str, item)))
        if args.nonverbose is False:
            print(separator)
    if args.upstreams is not None:
        reasn = pbuddy.regex_validation(re_asn, args.upstreams)
        if reasn is False:
            print(asn_invalid)
            sys.exit(1)
        if args.nonverbose is False:
            print(separator)
            print("=> ASN ", args.upstreams, " upstreams are:")
            print(separator)
        result = pbuddy.bv_asn_upstreams(args.upstreams)
        print(json.dumps(result, indent=4))
        if args.nonverbose is False:
            print(separator)
    if args.downstreams is not None:
        reasn = pbuddy.regex_validation(re_asn, args.downstreams)
        if reasn is False:
            print(asn_invalid)
            sys.exit(1)
        if args.nonverbose is False:
            print(separator)
            print("=> ASN ", args.downstreams, " downstreams are:")
            print(separator)
        result = pbuddy.bv_asn_downstreams(args.downstreams)
        print(json.dumps(result, indent=4))
        if args.nonverbose is False:
            print(separator)
    if args.whois is not None:
        reasn = pbuddy.regex_validation(re_asn, args.whois)
        repfx = pbuddy.pfx_validation(args.whois)
        if reasn is False and repfx is False:
            print(
                "That's not a valid ASN or prefix, please type the ASN without the suffix AS."
            )
            sys.exit(1)
        if reasn is True:
            if args.nonverbose is False:
                print(separator)
                print("=> ASN ", args.whois, " information:")
                print(separator)
            result = pbuddy.bv_asn_whois(args.whois)
            print(json.dumps(result, indent=4))
            if args.nonverbose is False:
                print(separator)
        elif repfx is True:
            if args.nonverbose is False:
                print(separator)
                print("=> Prefix ", args.whois, " information:")
                print(separator)
            result = pbuddy.bv_pfx_whois(args.whois)
            print(json.dumps(result, indent=4))
            if args.nonverbose is False:
                print(separator)
    if args.ipwhois is not None:
        reip = pbuddy.ip_validation(args.ipwhois)
        if reip is False:
            print("That's not a valid IP, please type the IP without the network mask.")
            sys.exit(1)
        if args.nonverbose is False:
            print(separator)
            print("=> Prefix ", args.ipwhois, " information:")
            print(separator)
        result = pbuddy.ii_ip_whois(args.ipwhois)
        print(json.dumps(result, indent=4))
        if args.nonverbose is False:
            print(separator)
    if args.bogonsasn is True:
        if args.nonverbose is False:
            print(separator)
            print("=> Bogons ASN list:")
            print(separator)
        result = pbuddy.ntt_bogons_asn()
        print(result)
        if args.nonverbose is False:
            print(separator)
    if args.asn_asnpfxaspathlength is not None:
        asn = args.asn_asnpfxaspathlength[0]
        threshold = args.asn_asnpfxaspathlength[1]
        asprepend = args.asn_asnpfxaspathlength[2]
        reasn = pbuddy.regex_validation(re_asn, args.asn_asnpfxaspathlength[0])
        repfx = pbuddy.regex_validation(re_int, args.asn_asnpfxaspathlength[1])
        reprep = pbuddy.regex_validation(re_yn, args.asn_asnpfxaspathlength[2])
        if reasn is False:
            print(asn_invalid)
            sys.exit(1)
        if repfx is False:
            print(
                "That's not a valid integer, please type an integer from 1 to 2 digits."
            )
            sys.exit(1)
        if reprep is False:
            print("That's not a valid option, please type an y [yes] or n [no].")
            sys.exit(1)
        if args.nonverbose is False:
            answer = None
            if asprepend == "y":
                answer = "considering as-prepend"
            elif asprepend == "n":
                answer = "not considering as-prepend"
            print(separator)
            print(
                "=> Getting prefixes for the ASN",
                asn,
                "where the AS-Path is greater than",
                threshold,
                "and",
                answer,
                ":",
            )
            print(separator)
        result = pbuddy.ripe_bv_pfxs_aspath_length(asn, threshold, asprepend)
        tuple_lpa = result[0]
        first_asns = result[1]
        second_asns = result[2]
        third_asns = result[3]
        nontransit = result[4]
        transit = result[5]
        direct = result[6]
        summary = pbuddy.ripe_bv_pfxs_aspath_length_summary(
            tuple_lpa, first_asns, second_asns, third_asns, nontransit, transit, direct
        )
        locations_d = summary[0]
        first_asn_d = summary[1]
        second_asn_d = summary[2]
        third_asn_d = summary[3]
        nontransit_d = summary[4]
        transit_d = summary[5]
        if args.nonverbose is False:
            print(separator)
        if args.nonverbose is False:
            print(separator)
            print("Summary => format [ ASN:COUNTER ]: ")
            print(separator)
        if int(threshold) <= 2:
            print(
                "First ASN (the other end ASN): ",
                [(":".join(map(str, item))) for item in first_asn_d],
            )
            print("")
            print(
                "Non transit peers directly attached to ASN",
                asn,
                ":",
                [(":".join(map(str, item))) for item in nontransit_d],
            )
            print("")
            print(
                "Transit upstreams for the ASN",
                asn,
                ":",
                [(":".join(map(str, item))) for item in transit_d],
            )
            print("")
            print("By locations:")
            for place in locations_d:
                print((":".join(map(str, place))))
        elif int(threshold) == 3:
            print(
                "First ASN (the other end ASN): ",
                [(":".join(map(str, item))) for item in first_asn_d],
            )
            print("")
            print(
                "Second ASN (the other end upstream): ",
                [(":".join(map(str, item))) for item in second_asn_d],
            )
            print("")
            print(
                "Non transit peers directly attached to ASN",
                asn,
                ":",
                [(":".join(map(str, item))) for item in nontransit_d],
            )
            print("")
            print(
                "Transit upstreams for the ASN",
                asn,
                ":",
                [(":".join(map(str, item))) for item in transit_d],
            )
            print("")
            print("By locations:")
            for place in locations_d:
                print((":".join(map(str, place))))
        elif int(threshold) >= 4:
            print(
                "First ASN (the other end ASN): ",
                [(":".join(map(str, item))) for item in first_asn_d],
            )
            print("")
            print(
                "Second ASN (the other end upstream): ",
                [(":".join(map(str, item))) for item in second_asn_d],
            )
            print("")
            print(
                "Third ASN (trying to find a common ASN on the path): ",
                [(":".join(map(str, item))) for item in third_asn_d],
            )
            print("")
            print(
                "Non transit peers directly attached to ASN",
                asn,
                ":",
                [(":".join(map(str, item))) for item in nontransit_d],
            )
            print("")
            print(
                "Transit upstreams for the ASN",
                asn,
                ":",
                [(":".join(map(str, item))) for item in transit_d],
            )
            print("")
            print("By locations:")
            for place in locations_d:
                print((": ".join(map(str, place))))
        if args.nonverbose is False:
            print(separator)
    if args.asn_upstreamtransient is not None:
        reasn = pbuddy.regex_validation(re_asn, args.asn_upstreamtransient)
        if reasn is False:
            print(asn_invalid)
            sys.exit(1)
        if args.nonverbose is False:
            print(separator)
            print(
                "=> Checking for upstreams on transient paths for the ASN",
                args.asn_upstreamtransient,
                ":",
            )
            print(separator)
        result = pbuddy.ripe_bv_upstreams_transient_path(args.asn_upstreamtransient)
        transient_paths = result[0]
        transient_ups = result[1]
        aspaths = result[2]
        full_aspaths = result[3]
        all_locations = result[4]
        locations = []
        transient_upstreams = {}
        for item in transient_paths:
            print("".join(map(str, item)))
            locations.append(item[0])
        locations_u = pbuddy.list_unique(locations)
        locations_dict = {}
        for location in locations_u:
            loc = locations.count(location)
            locations_dict[location] = loc
        asns_u = pbuddy.list_unique(transient_ups)
        for each in asns_u:
            rcount = aspaths.count(each[0])
            transient_upstreams[each[0]] = rcount
        transient_upstreams_d = sorted(
            transient_upstreams.items(), reverse=True, key=lambda x: x[1]
        )
        locations_d = sorted(locations_dict.items(), reverse=True, key=lambda x: x[1])
        if args.nonverbose is False:
            print(separator)
        print(
            "Transient upstreams for the ASN",
            args.asn_upstreamtransient,
            "[ Upstream transient ASN => Number of times this ASN was matched on the AS-Path => Total AS-Paths number seeing this ASN => Percentage ]:",
        )
        for item in transient_upstreams_d:
            upstreams_asn = item[0]
            upstreams_count = item[1]
            total_upstreams_count = full_aspaths.count(upstreams_asn)
            upstreams_percentage = round(
                100 * upstreams_count / total_upstreams_count, 2
            )
            print(
                "AS",
                upstreams_asn,
                "=>",
                upstreams_count,
                "=>",
                total_upstreams_count,
                "=>",
                upstreams_percentage,
                "%",
            )
        print("")
        print(
            "By locations [ Location => Number of transient upstreams ASNs on this location  => Total NLRI number seeing this location => Percentage ]:"
        )
        for place in locations_d:
            location = place[0]
            location_count = place[1]
            total_location_count = all_locations.count(location)
            location_percentage = round(100 * location_count / total_location_count, 2)
            print(
                location,
                "=>",
                location_count,
                "=>",
                total_location_count,
                "=>",
                location_percentage,
                "%",
            )
        if args.nonverbose is False:
            print(separator)

    if options is False:
        if len(sys.argv) == 1:
            parser.print_help(sys.stderr)
            sys.exit(0)

if __name__ == "__main__":
    try:
        main()
    except KeyboardInterrupt:
        print("Interrupted")


from collections import deque

def solve1(N, relationships):
    # relationships.append([-1]) # 0번 인덱스 처리하기 위함
    building_times = [-1]
    for i in range(1, N + 1):
        input_data = input().split()

        building_time = int(input_data[0])
        building_times.append(building_time)

        dependencies = input_data[1:-1]
        for dependency in dependencies:
            relationships[int(dependency)].append(i)
    print(relationships)
    print(building_times)

def solve2(N, relationships):
    result = []
    building_times = [0] * (N+1)
    indegree_infos = [[] for _ in range(N+1)]
    max_times = [[] for _ in range(N+1)]

    for i in range(1, N + 1):
        input_data = input().split()

        parent_building_time = int(input_data[0])
        building_times[i] = parent_building_time

        dependencies = list(map(int, input_data[1:-1]))
        indegree_infos[i] = dependencies

        # convert
        for dependency in dependencies:
            relationships[int(dependency)].append(i)

    # print(relationships)
    indegree = []
    for v_list in indegree_infos:
        indegree.append(len(v_list))

    dq = deque()

    for i in range(1, N+1):
        if indegree[i] == 0:
            dq.append((i,building_times[i]))

    for i in range(1, N+1):
        if not dq:
            # 큐가 비면 사이클이 생겼따는것임
            print('사이클 발생')
        vertex_idx, parent_building_time = dq.popleft()
        result.append(vertex_idx)
        building_times[vertex_idx] = parent_building_time
        for k in relationships[vertex_idx]:
            indegree[k] -= 1
            max_times[k].append(parent_building_time)
            if indegree[k] == 0:
                dq.append((k, max(max_times[k]) + building_times[k]))
    # print(result)
    # print(building_times)
    return building_times

if __name__ == '__main__':
    N = int(input()) # 건물의 번호는 1부터 N까지
    relationships = [[] for _ in range(N+1)]

    # solve1(N, relationships)
    answers = solve2(N, relationships)
    for i in range(1, len(answers)):
        print(answers[i])


import os
from part2 import get_distance_and_time
import urllib, json
from haversine import haversine_func

"""
Class to represent a Node in the graph
"""
class Node:

    """ Constructor """
    def __init__(self, latitude, longitude, name, id):
        self.latitude = latitude
        self.longitude = longitude
        self.name = name
        self.id = id

    """ Prints according to competitions specification """
    def mPrint(self):
        mString = str(self.latitude) + " " + str(self.longitude) + " " + str(self.name) + " " + str(self.id)
        print (mString)

    """
    Function that takes a dictionary of points as input and returns the list of points that are within 480km
    Arguments:
    list_of_nodes -- the graph of nodes represented by a dictionary
    Return:
    closePointsList -- a list of points that are within 480km
    """
    def close_points(self, list_of_nodes):
        # return list of nodes that are within 480km
        closePointsList = []
        for key in list_of_nodes:
            node = list_of_nodes[key]

            # Skip over self
            if self.id == node.id:
                continue

            dist = haversine_func(self.latitude, self.longitude, node.latitude, node.longitude)
            if dist <= 480:
                closePointsList.append(node)

        return closePointsList

""" Class that represents the graph """
class Graph:

    """ Constructor that parses through JSON file to create the graph """
    def __init__(self):

        # JSON parsing to get list of stations
        data = json.load(open("charging_stations.json"))
        list_of_stations = data["fuel_stations"]

        # the actual graph
        self.list_of_nodes = {}

        for station_dict in list_of_stations:
            latitude = station_dict["latitude"]
            longitude = station_dict["longitude"]
            name = station_dict["city"]
            id = station_dict["id"]

            # Put node into the dictionary
            self.list_of_nodes[id] = Node(latitude, longitude, name, id)

        # Debugging purposes
        # for key in self.list_of_nodes:
        #      self.list_of_nodes[key].mPrint()

    """
    Function that takes a start and end point as input and returns the optimal path, time and distance
    """
    def findPath(self, start, end):

        # Create nodes for start and end
        currNode = Node(start[0], start[1], "Start", 0)
        endNode = Node(end[0], end[1], "End", 1)

        # Initialize with starting node in path
        path = [currNode]
        dist = 0
        time = 0

        while currNode.latitude != endNode.latitude and currNode.longitude != endNode.longitude:

            # Get the list of valid points from the current node
            candidates = currNode.close_points(self.list_of_nodes)
            hdist=[]

            # Check if can reach destination from current node
            if haversine_func(currNode.latitude, currNode.longitude, endNode.latitude, endNode.longitude) <= 480:
                currDist, currTime = get_distance_and_time((currNode.latitude, currNode.longitude),
                                                           (endNode.latitude, endNode.longitude))
                dist += currDist
                time += currTime
                # Don't need to refuel at end so discount the refuelling time
                #time += currDist / 480 * 20
                break

            # Greedy algorithm. Find distance from each candidate to the end then choose the node that minimizes this
            for node in candidates:
                hdist.append(haversine_func(node.latitude, node.longitude, endNode.latitude, endNode.longitude))

            shortest = min(hdist)
            ind = hdist.index(shortest)
            chosen = candidates[ind]
            path.append(chosen)

            currDist, currTime = get_distance_and_time((currNode.latitude, currNode.longitude),
                                                       (chosen.latitude, chosen.longitude))

            # Add onto running sums. Distance in kilometers, time in hours
            dist += currDist
            time += currTime

            # The time to refuel at the station
            # Car can travel 480km then must refuel for 20min to get to full charge again
            time += currDist / 480 * 20 / 60.0

            currNode = chosen

        # At the end, append the end node
        path.append(endNode)
        return (path, time, dist)

"""
Part 4 of the competition

Arguments:
startstr -- the coordinates of the starting point as a string
endstr -- the coordinates of the end point as a string

Output:
outputs the list of nodes along the path, the time, and the distance

Returns:
the path, the time, the distance

"""
def part4(startstr, endstr):
    start_lat, start_lon = map(float, startstr.split(' '))
    end_lat, end_lon = map(float, endstr.split(' '))

    startPoint = (start_lat, start_lon)
    endPoint = (end_lat, end_lon)

    # Check the distance and time from start to end
    dist, time = get_distance_and_time(startPoint, endPoint)

    path = []
    if dist <= 480:
        path.append(Node(startPoint[0], startPoint[1], "Start", 0))
        path.append(Node(endPoint[0], endPoint[1], "End", 1))
        for station in path:
            station.mPrint()
        print (str(time) + " " + str(dist))
        return (path, time, dist)

    # Create the graph and find the path
    g = Graph()
    output = g.findPath(startPoint, endPoint)

    path = output[0]
    for station in path:
        station.mPrint()

    # time then distance
    print(str(output[1]) + " " + str(output[2]))

    return output

"""
Function called from part5.py (the UI application)
Same as part4 but with an additional step to parse the data to a string
"""
def part4Tuple(startTuple, endTuple):
    start_str = startTuple[0] + " " + startTuple[1]
    end_str = endTuple[0] + " " + endTuple[1]

    return part4(start_str,end_str)

# Run from command line
if __name__ == "__main__":
    str1 = input("Enter start coordinate: ")
    str2 = input("Enter end coordinate: ")
    part4(str1, str2)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Wed Oct 21 14:22:07 2020

@author: quert
"""

import numpy as np
from matplotlib import pyplot as plt

np.random.seed(7)

x = np.random.rand(100, 1)
y = 2 + 5 * x + .2 * np.random.randn(100, 1)

idx = np.arange(100)
np.random.shuffle(idx)

train_idx = idx[:80]
val_idx = idx[80:]

x_train, y_train = x[train_idx], y[train_idx]
x_val, y_val = x[val_idx], y[val_idx]

plt.scatter(x_train, y_train)
plt.show()

np.random.seed(7)
a = np.random.randn(1)

lr = 1e-1
num_epochs = 500

for epoch in range(num_epochs):
    yhat = a + b * x_train
    error = (y_train - yhat)
    loss = (error ** 2).mean()

    a_grad = -2 * error.mean()
    b_grad = -2 * (x_train * error).mean()

    a = a - lr * a_grad
    b = b - lr * b_grad
print(a, b)


from itertools import product
def solution(word):
    answer = 0
    a_list = 'AEIOU'

    result = []

    for i in range(1,6):
        tmp = list(map(list,product(a_list,repeat=i)))

        for each in tmp:
            aa = ''.join(each)
            result.append(aa)

    result.sort()
    return result.index(word)+1

프로그래머스/lv2/84512. 모음 사전/모음 사전.py


# -*- coding: utf-8 -*-
"""
Created on Thu Nov 30 13:39:15 2017

@author: dsun2
"""
# this script clean customers reviews and save into files

import csv
import nltk, string
stop_words = ['a', 'an', 'the', 'and', 'or']

def get_review_tokens(review):
    # unigram tokenization pattern
    pattern = r'\w+[\-]*\w+'
    # get unigrams
    tokens=[token.strip() \
            for token in nltk.regexp_tokenize(review.lower(), pattern) \
            if token.strip() not in string.punctuation and \
            token.strip() not in stop_words and \
            token.strip() if not token.isdigit() and \
            token.strip() if not token.startswith('\'')
            ]
    return tokens

def clean_review(tokens):
    review = " ".join(get_review_tokens(tokens))
    return review

def save(reviews):
    with open("clean_iphone8_review.csv", "wb") as f:
        writer = csv.writer(f, dialect = 'excel')
        writer.writerows(reviews)
    f.close()

if __name__ == "__main__":
    f = open("raw_iphone8_review.csv", "rb")
    reader = csv.reader(f)
    reviews = []
    for utf8_row in reader:
        unicode_row = [row.decode('utf8') for row in utf8_row]
        review = [unicode_row[0], clean_review(unicode_row[1])]
        reviews.append(review)
    f.close()
    save(reviews)


# Почему нет ограничения на кол-во параметров для `print` ?
print("asd", "asdasd", "asdas", "asdjih1209y1029312", 123, 123, 123)

# аргументы должны быть или `int`, или `float`.
# вернется или `int`, или `float` тоже.
def summ(*numbers: int | float) -> int | float:
    """
    Суммирует все переданные числа и возвращает сумму.
    """
    # `args` это кортеж всех аргументов, которые были переданы в функцию.
    total = 0
    for number in numbers:
        total += number
    return total

print(type(summ(1, 8, 0, 1)))
print(type(summ(1, 8.1, 0, 1)))


import unittest
from src.similarity.homogeneous.PageRankStrategy import PageRankStrategy
from src.util.SampleGraphUtility import SampleGraphUtility

__author__ = 'jontedesco'

class PageRankStrategyTest(unittest.TestCase):
    """
      Tests a basic PageRank strategy
    """

    def testFindSingleSimilarityPathSimExampleThree(self):
        """
          Tests pairwise similarity for nodes, using example 3 from PathSim paper (compute similarity scores from Mike)
        """

        graph, authorMap, conferenceMap  = SampleGraphUtility.constructPathSimExampleThree()
        strategy = PageRankStrategy(graph)

        mike = authorMap['Mike']
        jimScore = strategy.findSimilarityScore(mike, authorMap['Jim'])
        maryScore = strategy.findSimilarityScore(mike, authorMap['Mary'])
        bobScore = strategy.findSimilarityScore(mike, authorMap['Bob'])
        annScore = strategy.findSimilarityScore(mike, authorMap['Ann'])

        self.assertTrue(annScore >= maryScore)
        self.assertTrue(annScore >= jimScore)
        self.assertTrue(annScore >= bobScore)

    def testFindAllSimilarityFromNodeOnPathSimExampleThree(self):
        """
          Tests similarity for all other nodes given a signle node, using example 3 from PathSim paper
        """

        graph, authorMap, conferenceMap  = SampleGraphUtility.constructPathSimExampleThree()
        strategy = PageRankStrategy(graph)

        mike = authorMap['Mike']
        mostSimilarNodes = strategy.findMostSimilarNodes(mike, 1)

        self.assertEquals([authorMap['Ann']], mostSimilarNodes)