from __future__ import print_function
from numpy import array as Vector
from collections import namedtuple

from .vector_ops import *
from .kpclasses import Bead,chainDeepCopy
from .writer import *
from .reader import *
from .config import EPSILON,VERBOSE
from knot_pull.finder import find_frame

def too_far(p1 ,p2 ,p3 ,i0 ,i1):
    """Checks if crossing is possible - 9 A from all triangle points is impossible due to single connection
    length restrictions"""
    return all([point_distance(p1 ,i0 )>=9. ,point_distance(p2 ,i0 ) >9. ,point_distance(p3 ,i0 ) >9.]) \
            or all([point_distance(p1 ,i1 )>=9. ,point_distance(p2 ,i1 ) >9. ,point_distance(p3 ,i1 ) >9.])

def inspectingOtherLines(p1, p2, p3, i0, i1, greedy=0, log=0,but_not=[]):
    """Looks for connections going through the triangle. Starts with second connection from each triangle end"""

    #but_not = [x.vec for x in but_not]
    potentials = []
    potids = []

    p123normal = get_normal(p1, p2, p3)

    inspected = i0
    if inspected and not inspected.Nhand:
        if found_crossing(p1,p2,p3, inspected.vec, l1=None, p123normal=None) is not False:
            potentials.append(inspected.vec)

    while inspected and inspected.Nhand:
        if inspected.Nhand.end or (inspected in but_not and inspected.Nhand in but_not):#Skip "Virtual" connection - between chain ends
            inspected = inspected.Nhand
            continue
        l0, l1 = inspected.vec, inspected.Nhand.vec
        #greedy can have distances larger than allowed in too_far()
        i = False if (greedy == 0 and too_far(p1, p2, p3, l0, l1)) else found_crossing(p1, p2, p3, l0, l1, p123normal)

        if i is not False:
            potentials.append(i)
        inspected = inspected.Nhand

    inspected = i1
    if inspected and not inspected.Chand:
        if found_crossing(p1,p2,p3, inspected.vec, l1=None, p123normal=None) is not False:
            potentials.append(inspected.vec)
    while inspected and inspected.Chand:
        if inspected.end or (inspected in but_not and inspected.Chand in but_not):
            inspected = inspected.Chand
            continue
        l0, l1 = inspected.vec, inspected.Chand.vec
        #greedy can have distances larger than allowed in too_far()
        i = False if (greedy == 0 and too_far(p1, p2, p3, l0, l1)) else found_crossing(p1, p2, p3, l0, l1, p123normal)
        if i is not False:
            potentials.append(i)
        inspected = inspected.Chand
    return potentials

def filter_greedy(atoms, outfile='', len_frames=0):
    """Removes all superfluous atoms(kept for PyMOL purposes, to better detect topology"""
    current = atoms[0]
    latom = 0 #num of removed atoms
    changed = False
    while current.Chand and current.Chand.Chand:
        if current.Chand.end: #Skips "virtual" connections at chain ends
            current = current.Chand.Chand
            continue
        if current.end:
            current = current.Chand
            continue

        i0 = current.Nhand
        i1 = current.Chand.Chand.Chand if current.Chand and current.Chand.Chand else False

        potentials = inspectingOtherLines(current.vec, current.Chand.vec, current.Chand.Chand.vec, i0, i1, greedy=True)

        if potentials:
            current = current.Chand
            continue
        else:
            changed = changed or (not current.Chand.recent)
            current.setChand(current.Chand.Chand)
            current.Chand.setNhand(current)

            latom += 1
            continue
            ## TODO specjalnie nie zamieniam current - watpliwe, ale a noz widelec jeszcze jeden?

    while current.Chand: #renumbering needs to start from the C terminus
        current = current.Chand

    atoms = []
    while current:
        current.recent = max(0, current.recent - 1)
        atoms.append(current)
        current = current.Nhand
    atoms.reverse()

    for i, at in enumerate(atoms):
        at.setId(i)

    return atoms, changed

def prefilter_with_adding(atoms):
    """Removes atoms to reduce the backbone where possible. Adding new joints to long connections
    allows for reducing bumps"""

    first_bead_in_structure = atoms[0]

    next_chain_handle = first_bead_in_structure
    changed = False
    cnt=0
    while next_chain_handle is not None:
        cnt+=1
        currentN = next_chain_handle
        currentC = currentN.Chand
        if currentC is None: #to bypass that currentN can be an end
            break
        while currentC.Chand and not currentC.end:
            currentC = currentC.Chand
        next_chain_handle = currentC.Chand
        assert currentC.end or next_chain_handle is None
        #print(cnt,(currentN.Nhand,(currentN.id,currentN.end),currentN.Chand),(currentC.Nhand,(currentC.id,currentC.end),currentC.Chand))
        verbose = 0

        Ntriangle = [currentN,currentN.Chand,currentN.Chand.Chand if currentN.Chand else None]
        Ctriangle = [currentC,currentC.Nhand,currentC.Nhand.Nhand if currentC.Nhand else None]
        #if 1 or verbose:
            #print("starting with",len(atoms))
        #    print([(a.id,a.end) for a in atoms])
         #   print("handle",next_chain_handle,next_chain_handle.id if next_chain_handle is not None else None)

        while None not in Ntriangle and None not in Ctriangle:# and not any(x.end for x in Ntriangle+Ctriangle): #maybe just one of them?
            if verbose: print(currentN.id,currentN,currentC.id,currentC)
            if verbose:  print(Ntriangle,Ctriangle)
            if Ntriangle[0] == Ctriangle[0]: #just passed the overlap (for odd) or lack of it (even)
                break
            # TODO: multichain
            """
                    if current.Chand.end: #skip "Virtual" connections at chain ends
                current = current.Chand.Chand
                continue
            if current.end:
                current = current.Chand
                continue"""
            overlap = sum(nt in Ctriangle for nt in Ntriangle)
            #if overlap: print("OVERLAP",overlap)

            #TODO dodac overalp 2 gdy a' w a,(b,c'),(c,b')

            if overlap == 3:
                if verbose: print("overlap=3")
                potentials = inspectingOtherLines(Ntriangle[0].vec, Ntriangle[1].vec, Ntriangle[2].vec,
                                                  Ntriangle[0].Nhand,#.vec,
                                                  Ntriangle[2].Chand)#.vec)
                if potentials:
                    if verbose: print("have potetnails")
                    if point_distance(Ntriangle[0].vec, Ntriangle[1].vec) > 3.: #new join on long connection
                        #breaks join Ntraingle[0],Ntriangle[1] (same as Ctirange[1], Ctriangle[2])
                        new_N = get_middlepoint(Ntriangle[0].vec, Ntriangle[1].vec)
                        if verbose: print("adding nowy at", new_N)
                        nowy_id = (Ntriangle[0].original_id + Ntriangle[1].original_id) / 2.
                        if int(nowy_id) != nowy_id:
                            if int(nowy_id) != Ntriangle[0].original_id:
                                nowy_id = int(nowy_id)
                            else:
                                nowy_id = int(nowy_id) + 1
                        nowy = Bead(Vector(new_N), "CA", nowy_id)
                        nowy.recent = 2
                        nowy.setId((Ntriangle[0].id + Ntriangle[1].id) / 2.)
                        nowy.setNhand(Ntriangle[0])
                        nowy.setChand(Ntriangle[1])
                        Ntriangle[1].setNhand(nowy)
                        Ntriangle[0].setChand(nowy)
                    if point_distance(Ntriangle[1].vec, Ntriangle[2].vec) > 3.:  # new join on long connection
                        # breaks join Ntraingle[1],Ntriangle[2] (same as Ctriangle[0], Ctriangle[1])
                        new_N = get_middlepoint(Ntriangle[1].vec, Ntriangle[2].vec)
                        if verbose: print("adding nowy at", new_N)
                        nowy_id = (Ntriangle[1].original_id + Ntriangle[2].original_id) / 2.
                        if int(nowy_id) != nowy_id:
                            if int(nowy_id) != Ntriangle[1].original_id:
                                nowy_id = int(nowy_id)
                            else:
                                nowy_id = int(nowy_id) + 1
                        nowy = Bead(Vector(new_N), "CA", nowy_id)
                        nowy.recent = 2
                        nowy.setId((Ntriangle[1].id + Ntriangle[2].id) / 2.)
                        nowy.setNhand(Ntriangle[1])
                        nowy.setChand(Ntriangle[2])
                        Ntriangle[2].setNhand(nowy)
                        Ntriangle[1].setChand(nowy)
                    currentN = currentN.Chand
                    Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                    currentC = currentC.Nhand
                    Ctriangle = [currentC, currentC.Nhand, currentC.Nhand.Nhand if currentC.Nhand else None]
                    continue
                else:
                    if verbose: print("dont have potetnails")
                    if point_distance(Ntriangle[0].vec, Ntriangle[2].vec) < 4.:  # TODO may be too far?
                        # if can be remove, and the distance is not so great - remove the atom
                        changed = changed or (not Ntriangle[1].recent)
                        Ntriangle[0].setChand(Ntriangle[2])
                        Ntriangle[2].setNhand(Ntriangle[0])
                        ## specjalnie nie zamieniam current - watpliwe, ale a noz widelec jeszcze jeden?
                    else:
                        position = get_middlepoint(Ntriangle[0].vec, Ntriangle[2].vec)
                        if verbose: print("adding nowy at", position)
                        # if we can reduce but the distance is too great - remove the atom, put a new one on the connection
                        # reduces traingles to straight line
                        changed = changed or point_distance(Ntriangle[1].vec, position) > EPSILON
                        nowy_id = (Ntriangle[0].original_id + Ntriangle[2].original_id) / 2.

                        nowy = Bead(Vector(position), "CA", nowy_id)
                        nowy.recent = 2
                        nowy.setId(Ntriangle[1].id)  # replaces current atom
                        nowy.setNhand(Ntriangle[0])
                        nowy.setChand(Ntriangle[2])
                        Ntriangle[2].setNhand(nowy)
                        Ntriangle[0].setChand(nowy)
                        currentN = nowy
                        Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                    break #removed middle from overlappig triangle, nothing more to do
            else:
                Npotentials = inspectingOtherLines(Ntriangle[0].vec, Ntriangle[1].vec, Ntriangle[2].vec,
                                                   Ntriangle[0].Nhand,#.vec if Ntriangle[0].Nhand else None,
                                                   Ntriangle[2].Chand,#.vec if Ntriangle[2].Chand else None,
                                                   but_not=Ctriangle)
                Cpotentials = inspectingOtherLines(Ctriangle[0].vec, Ctriangle[1].vec, Ctriangle[2].vec,
                                                   Ctriangle[2].Nhand,#.vec if Ctriangle[2].Nhand else None,
                                                   Ctriangle[0].Chand,#.vec if Ctriangle[0].Chand else None,
                                                   but_not=Ntriangle)
                if verbose: print("overlap < 3")
                if Npotentials:
                    if verbose: print("have Nportenials")
                    if Cpotentials:
                        if verbose: print("have Cportenials")
                        #nothing can be done
                        currentC=currentC.Nhand
                        Ctriangle = [currentC, currentC.Nhand, currentC.Nhand.Nhand if currentC.Nhand else None]
                        currentN = currentN.Chand
                        Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                        continue # it should break at the beginning of next loop pass if overlap was 2
                    else:
                        C123normal = get_normal(Ctriangle[0].vec, Ctriangle[1].vec, Ctriangle[2].vec)
                        # check if they ARE crossing each othe
                        c0v, c1v, c2v = [c.vec for c in Ctriangle]
                        n0v, n1v, n2v = [n.vec for n in Ntriangle]
                        if any(map(lambda x: x is not False, [found_crossing(c0v, c1v, c2v, n0v, n1v, C123normal),
                                                              found_crossing(c0v, c1v, c2v, n1v, n2v, C123normal)])):
                            if verbose: print("N jest w C")
                            currentC = currentC.Nhand
                            Ctriangle = [currentC, currentC.Nhand, currentC.Nhand.Nhand if currentC.Nhand else None]
                            currentN = currentN.Chand
                            Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                            continue
                        if verbose: print("dont have other Cportenials")
                        if point_distance(Ctriangle[0].vec, Ctriangle[2].vec) < 4.:  # TODO may be too far?
                            # if can be remove, and the distance is not so great - remove the atom
                            changed = changed or (not Ctriangle[1].recent)
                            Ctriangle[0].setNhand(Ctriangle[2])
                            Ctriangle[2].setChand(Ctriangle[0])
                            Ctriangle = [currentC, currentC.Nhand, currentC.Nhand.Nhand if currentC.Nhand else None]
                            currentN = currentN.Chand
                            Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                            continue
                             ## specjalnie nie zamieniam current - watpliwe, ale a noz widelec jeszcze jeden?
                        else:
                            position = get_middlepoint(Ctriangle[0].vec, Ctriangle[2].vec)
                            if verbose: print("adding nowy at", position)
                            # if we can reduce but the distance is too great - remove the atom, put a new one on the connection
                            # reduces traingles to straight line
                            changed = changed or point_distance(Ctriangle[1].vec, position) > EPSILON
                            nowy_id = (Ctriangle[0].original_id + Ctriangle[2].original_id) / 2.
                            nowy = Bead(Vector(position), "CA", nowy_id)
                            nowy.recent = 2
                            nowy.setId(Ctriangle[1].id)  # replaces current atom
                            nowy.setChand(Ctriangle[0])
                            nowy.setNhand(Ctriangle[2])
                            Ctriangle[2].setChand(nowy)
                            Ctriangle[0].setNhand(nowy)
                            currentC = nowy
                            Ctriangle = [currentC, currentC.Nhand, currentC.Nhand.Nhand if currentC.Nhand else None]
                            currentN = currentN.Chand
                            Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                            continue
                else:
                    if verbose: print("dont have other Nportenials")
                    if Cpotentials:
                        if verbose: print("have Cportenials")
                        N123normal = get_normal(Ntriangle[0].vec, Ntriangle[1].vec, Ntriangle[2].vec)
                        # check if they ARE crossing each othe
                        c0v, c1v, c2v = [c.vec for c in Ctriangle]
                        n0v, n1v, n2v = [n.vec for n in Ntriangle]
                        if any(map(lambda x: x is not False, [found_crossing(n0v, n1v, n2v, c0v, c1v, N123normal),
                                                              found_crossing(n0v, n1v, n2v, c1v, c2v, N123normal)])):
                            if verbose: print("C jest w N")
                            currentN = currentN.Chand
                            Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                            currentC = currentC.Nhand
                            Ctriangle = [currentC, currentC.Nhand, currentC.Nhand.Nhand if currentC.Nhand else None]
                            continue
                        if point_distance(Ntriangle[0].vec, Ntriangle[2].vec) < 4.:  # TODO may be too far?
                            # if can be remove, and the distance is not so great - remove the atom
                            changed = changed or (not Ntriangle[1].recent)
                            Ntriangle[0].setChand(Ntriangle[2])
                            Ntriangle[2].setNhand(Ntriangle[0])
                            Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                            currentC = currentC.Nhand
                            Ctriangle = [currentC, currentC.Nhand, currentC.Nhand.Nhand if currentC.Nhand else None]
                            continue
                             ## specjalnie nie zamieniam current - watpliwe, ale a noz widelec jeszcze jeden?
                        else:
                            position = get_middlepoint(Ntriangle[0].vec, Ntriangle[2].vec)
                            if verbose: print("adding nowy at", position)
                            # if we can reduce but the distance is too great - remove the atom, put a new one on the connection
                            # reduces traingles to straight line
                            changed = changed or point_distance(Ntriangle[1].vec, position) > EPSILON
                            nowy_id = (Ntriangle[0].original_id + Ntriangle[2].original_id) / 2.

                            nowy = Bead(Vector(position), "CA", nowy_id)
                            nowy.recent = 2
                            nowy.setId(Ntriangle[1].id)  # replaces current atom
                            nowy.setNhand(Ntriangle[0])
                            nowy.setChand(Ntriangle[2])
                            Ntriangle[2].setNhand(nowy)
                            Ntriangle[0].setChand(nowy)
                            currentN = nowy
                            Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                            currentC = currentC.Nhand
                            Ctriangle = [currentC, currentC.Nhand, currentC.Nhand.Nhand if currentC.Nhand else None]
                            continue
                    else:
                        if verbose: print("dont have any portenials")
                        if overlap == 2:
                            if verbose: print("overlap==2")
                            break

                            new_BC = get_middlepoint(Ntriangle[1].vec, Ctriangle[1].vec)
                            if verbose: print("adding nowy at", new_BC)
                            changed = True
                            nowy_id = (Ntriangle[1].original_id +Ctriangle[1].original_id)/2.
                            nowy = Bead(Vector(new_BC), "CA", nowy_id)
                            nowy.recent = 2
                            nowy.setId(Ntriangle[1].id)  # replaces current atom

                            Ntriangle[0].setChand(nowy)
                            Ctriangle[0].setNhand(nowy)
                            nowy.setNhand(Ntriangle[0])
                            nowy.setChand(Ctriangle[0])
                            Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                            Ctriangle = [currentC, currentC.Nhand, currentC.Nhand.Nhand if currentC.Nhand else None]
                            continue #tera bedzie overlap N.A,nowy,C.A
                        else: #separate triangles
                            if verbose: print("overlap<2")
                            N123normal = get_normal(Ntriangle[0].vec, Ntriangle[1].vec, Ntriangle[2].vec)
                            C123normal = get_normal(Ctriangle[0].vec, Ctriangle[1].vec, Ctriangle[2].vec)
                            #check if they ARE crossing each othe
                            c0v,c1v,c2v = [c.vec for c in Ctriangle]
                            n0v,n1v,n2v = [n.vec for n in Ntriangle]
                            if verbose: print("checking",[found_crossing(n0v,n1v,n2v,c0v,c1v,N123normal),
                                    found_crossing(n0v,n1v,n2v,c1v,c2v,N123normal),
                                    found_crossing(c0v, c1v, c2v, n0v, n1v, C123normal),
                                    found_crossing(c0v, c1v, c2v, n1v, n2v, C123normal)])
                            if any(map(lambda x: x is not False,[found_crossing(n0v,n1v,n2v,c0v,c1v,N123normal),
                                    found_crossing(n0v,n1v,n2v,c1v,c2v,N123normal),
                                    found_crossing(c0v, c1v, c2v, n0v, n1v, C123normal),
                                    found_crossing(c0v, c1v, c2v, n1v, n2v, C123normal)])):
                                if verbose: print("traingles cross each other")
                                currentN = currentN.Chand
                                currentC = currentC.Nhand
                                Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                                Ctriangle = [currentC, currentC.Nhand, currentC.Nhand.Nhand if currentC.Nhand else None]
                                #to be determined if move them
                                continue

                            # check if they would cross each other
                            xt1 = found_crossing(Ntriangle[0].vec, Ntriangle[1].vec, Ntriangle[2].vec,Ctriangle[0].vec,Ctriangle[2].vec,N123normal)
                            xt2 = found_crossing(Ctriangle[0].vec, Ctriangle[1].vec, Ctriangle[2].vec,Ntriangle[0].vec,Ntriangle[2].vec,C123normal)
                            #print("xts:",xt1,xt2)
                            #changed to or below, bo mzoe czegos nei widze
                            if xt1 is not False or xt2 is not False: #should always be bool(xt1)==bool(xt2)
                                currentN = currentN.Chand
                                currentC = currentC.Nhand
                                Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                                Ctriangle = [currentC, currentC.Nhand, currentC.Nhand.Nhand if currentC.Nhand else None]
                                # to be on the safe side
                                continue

                                X = get_middlepoint(xt1,xt2) #moving lines should meet here, last safe point
                                changed = True
                                new_N_B = get_middlepoint(xt1,X)
                                if verbose: print("adding nowy at", new_N_B)
                                nowy_N = Bead(Vector(new_N_B), "CA", Ntriangle[1].original_id)
                                nowy_N.recent = 2
                                nowy_N.setId(Ntriangle[1].id)
                                Ntriangle[0].setChand(nowy_N)
                                Ntriangle[2].setNhand(nowy_N)
                                nowy_N.setNhand(Ntriangle[0])
                                nowy_N.setChand(Ntriangle[2])
                                new_C_B = get_middlepoint(xt2,X)
                                if verbose: print("adding nowy at", new_C_B)
                                nowy_C = Bead(Vector(new_C_B), "CA", Ctriangle[1].original_id)
                                nowy_C.recent = 2
                                nowy_C.setId(Ctriangle[1].id)
                                Ctriangle[0].setNhand(nowy_C)
                                Ctriangle[2].setChand(nowy_C)
                                nowy_C.setNhand(Ctriangle[2])
                                nowy_C.setChand(Ctriangle[0])
                                #move on, wont move further here
                                currentN = currentN.Chand
                                Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                                currentC = currentC.Nhand
                                Ctriangle = [currentC, currentC.Nhand, currentC.Nhand.Nhand if currentC.Nhand else None]

                            else: #safe to do both triangles
                                if verbose: print("no xts,distances are",point_distance(Ntriangle[0].vec, Ntriangle[2].vec),point_distance(Ctriangle[0].vec, Ctriangle[2].vec))
                                if point_distance(Ntriangle[0].vec, Ntriangle[2].vec) < 4.:  # TODO may be too far?
                                    # if can be remove, and the distance is not so great - remove the atom
                                    changed = changed or (not Ntriangle[1].recent)
                                    Ntriangle[0].setChand(Ntriangle[2])
                                    Ntriangle[2].setNhand(Ntriangle[0])
                                    Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                                    ## specjalnie nie zamieniam current - watpliwe, ale a noz widelec jeszcze jeden?
                                else:
                                    position = get_middlepoint(Ntriangle[0].vec, Ntriangle[2].vec)
                                    if verbose: print("adding nowy at",position)
                                    # if we can reduce but the distance is too great - remove the atom, put a new one on the connection
                                    # reduces traingles to straight line
                                    changed = changed or point_distance(Ntriangle[1].vec, position) > EPSILON
                                    nowy_id = (Ntriangle[0].original_id + Ntriangle[2].original_id) / 2.

                                    nowy = Bead(Vector(position), "CA", nowy_id)
                                    nowy.recent = 2
                                    nowy.setId(Ntriangle[1].id)  # replaces current atom
                                    nowy.setNhand(Ntriangle[0])
                                    nowy.setChand(Ntriangle[2])
                                    Ntriangle[2].setNhand(nowy)
                                    Ntriangle[0].setChand(nowy)
                                    currentN = nowy
                                    Ntriangle = [currentN, currentN.Chand, currentN.Chand.Chand if currentN.Chand else None]
                                if point_distance(Ctriangle[0].vec, Ctriangle[2].vec) < 4.:  # TODO may be too far?
                                    # if can be remove, and the distance is not so great - remove the atom
                                    changed = changed or (not Ctriangle[1].recent)
                                    Ctriangle[0].setNhand(Ctriangle[2])
                                    Ctriangle[2].setChand(Ctriangle[0])
                                    Ctriangle = [currentC, currentC.Nhand, currentC.Nhand.Nhand if currentC.Nhand else None]
                                    continue
                                    ## specjalnie nie zamieniam current - watpliwe, ale a noz widelec jeszcze jeden?
                                else:
                                    position = get_middlepoint(Ctriangle[0].vec, Ctriangle[2].vec)
                                    if verbose: print("adding nowy at", position)
                                    # if we can reduce but the distance is too great - remove the atom, put a new one on the connection
                                    # reduces traingles to straight line
                                    changed = changed or point_distance(Ctriangle[1].vec, position) > EPSILON
                                    nowy_id = (Ctriangle[0].original_id + Ctriangle[2].original_id) / 2.
                                    nowy = Bead(Vector(position), "CA", nowy_id)
                                    nowy.recent = 2
                                    nowy.setId(Ctriangle[1].id)  # replaces current atom
                                    nowy.setChand(Ctriangle[0])
                                    nowy.setNhand(Ctriangle[2])
                                    Ctriangle[2].setChand(nowy)
                                    Ctriangle[0].setNhand(nowy)
                                    currentC = nowy
                                    Ctriangle = [currentC, currentC.Nhand, currentC.Nhand.Nhand if currentC.Nhand else None]
                                    continue
        if verbose: print("changed is",changed)

    #print(list((x.id,x.original_id) for x in atoms))

    #while currentN.Chand:
    #    currentN = currentN.Chand

    currentN = first_bead_in_structure
    atoms = []
    while currentN:
        currentN.recent = max(0, currentN.recent - 1)
        atoms.append(currentN)
        currentN = currentN.Chand
    #atoms.reverse()

    #print("after filtering atoms count:",len(atoms),atoms[0],atoms[0].Chand)

    for i, at in enumerate(atoms):
        at.setId(i)
    #exit()
    #exit()

    return atoms, changed

def run_through_filtering(atoms, config, greedy=0):
    """Governs reduction process and when it should end (when there is no improvement)"""

    frames = []
    frames.append([(x.original_id, x.vec, x.end) for x in atoms])
    o_and_t = config.get('outfile',0) and config.get('trajectory',0)

    if o_and_t:
        #print_out_last_pdb(config, frames, atoms)
        print_out_last_frame(config, atoms, len(frames))

    if not config or not config['no_pulling']:
        atoms, changed = prefilter_with_adding(atoms)

        frames_without_shortening = 0
        atoms_num = len(set(_.tuple() for _ in atoms))

        while changed:  # TODO should check RMSD up to 2 steps back
            frames.append([(x.original_id, list(x.vec), x.end) for x in atoms])
            if len(frames) >= 3 and len(frames[-1]) == len(frames[-3]):
                if all([all(i == j for i, j in zip(x[1], y[1])) for x, y in zip(frames[-1], frames[-3])]):
                    # if two frames back we had the exact same positions
                    break
                if len(set(_.tuple() for _ in atoms)) == atoms_num:
                    frames_without_shortening += 1
                else:
                    atoms_num = len(set(_.tuple() for _ in atoms))
                    frames_without_shortening = 0
                if frames_without_shortening > 2*len(atoms):
                    if VERBOSE: print ("Breaking filtering due to to not enough change")
                    break

            if o_and_t:
                #print_out_last_pdb(config, frames, atoms)
                print_out_last_frame(config, atoms, len(frames))

            atoms, changed = prefilter_with_adding(atoms)

        #    frames.append([(x.original_id, x.vec) for x in atoms])

    if VERBOSE:
        print ("Finished filtering, have {} atoms".format(len(atoms)))

    if greedy: #reduce number of atoms (improves topology detection)
        atoms, _ = filter_greedy(atoms, config, len(frames))
        frames.append([(x.original_id, x.vec, x.end) for x in atoms])
        if VERBOSE:
            print ("Finished greedy filtering, have {} atoms".format(len(atoms)))

    if o_and_t:
        #print_out_last_pdb(config, frames, atoms)
        print_out_last_frame(config, atoms, len(frames))

    return frames,atoms

def run_through_division(atoms):
    """Finds connections which can be safely cut (connected segments can't be simplified even separately) """
    if VERBOSE: print ("Starting with {} atoms".format(len(atoms)))
    cuts = []
    for i in range(1, len(atoms) - 2):  # No sense in checking last edges
        j = i + 1
        if VERBOSE: print("Cutting edge {}".format(j))
        _middle = get_middlepoint(atoms[i].vec, atoms[j].vec)
        _tmp1 = chainDeepCopy(atoms[:j] + [Bead(_middle, "CA")])
        _, _tmp1a = run_through_filtering(_tmp1, {}, greedy=1)
        if VERBOSE: print("Left from {} to {}".format(len(_tmp1),len(_tmp1a)))
        _tmp2 = chainDeepCopy([Bead(_middle, "CA")] + atoms[j:])  #
        _, _tmp2a = run_through_filtering(_tmp2, {}, greedy=1)
        if VERBOSE: print("Right from {} to {}".format(len(_tmp2),len(_tmp2a)))
        if _tmp1 == _tmp1a and _tmp2 == _tmp2a:  # no reduction
            # print i,
            cuts.append(i)

    cuts = [0] + cuts + [len(atoms) - 1]  # fix to get proper segment indices
    atom_lists = []
    if VERBOSE: print("Cuts: {}".format(cuts))

    for i in range(0, len(cuts) - 1):
        cutl = cuts[i]
        cutr = cuts[i + 1]
        lista = []
        if cutl:  # add middlepoints of our breakable edges
            _mid_l = get_middlepoint(atoms[cutl].vec, atoms[cutl + 1].vec)
            lista.append(Bead(_mid_l, "CA"))
        lista += atoms[cutl + bool(cutl):cutr + 1]
        if cutr < len(atoms) - 2:
            _mid_r = get_middlepoint(atoms[cutr].vec, atoms[cutr + 1].vec)
            lista.append(Bead(_mid_r, "CA"))
        lista = chainDeepCopy(lista)
        atom_lists.append(lista)

    return atom_lists  # returns all separateable segments

def pull(atoms, config, chain_names, get_representative=0,greedy=0):#, greedy_file="",trajectory=True,quiet=False, chain_names=(),rna=False):
    outfile = config['outfile']

    frames, atoms = run_through_filtering(atoms, config, greedy=greedy)
    quiet = config['quiet']
    repr = []
    if get_representative:
        Atom = namedtuple("Atom","original_id x y z end")
        repr = find_frame(frames)
        repr = [Atom(x[0],x[1][0],x[1][1],x[1][2],x[2]) for x in repr]

    chains = []
    model_num = len(frames)+1
    separate_chains = divide_into_bead_chains(atoms)
    for c, chain in enumerate(separate_chains):
        ch = Chain(c,chain)
        if chain_names: ch.setChainName(chain_names[c])
        if outfile:
            if not quiet: model_num = ch.print2file(config,model_num)
        chains.append(ch)

    for _,c1 in enumerate(chains):
        for c2 in chains[_+1:]:
            if are_chains_linked(c1,c2):
                c1.neighbours.append(c2)
                c2.neighbours.append(c1)

    return chains,repr

def same_vecs(l1,l2):
    return all(np.array_equal(x.vec,y.vec) for x,y in zip(l1,l2))

def are_chains_linked(ch1,ch2):
    _tmp_both = chainDeepCopy(ch1.atoms+ch2.atoms)
    _tmp_both[len(ch1.atoms)-1].end = True
    _tmp_ch1 = chainDeepCopy(ch1.atoms)
    _tmp_ch2 = chainDeepCopy(ch2.atoms)

    _,_both = run_through_filtering(_tmp_both, {}, greedy=1)
    _,_ch1 = run_through_filtering(_tmp_ch1, {}, greedy=1)
    _,_ch2 = run_through_filtering(_tmp_ch2, {}, greedy=1)
    return not same_vecs(_both,_ch1+_ch2)

class Chain:
    def __init__(self,chain,atoms):
        self.chain = chain
        self.atoms = atoms
        self.atom_lists = run_through_division(atoms)
        self.knots = []
        self.neighbours = []
        self.closing_path = closeTheCurve(atoms)
        self.closing_paths = [closeTheCurve(a) for a in self.atom_lists]
        self.wanda = None
        self.dowker = None
        self.dowker_code = None
        self.chain_name = ""

    def setChainName(self,c):
        self.chain_name = "({})".format(c)

    def print2file(self,config,model_num):
        #print_out_one_frame(outfile, self.atoms, model_num,self.chain)
        model_num+=1
        for alist in self.atom_lists:
            #print_out_one_frame(outfile, alist, model_num,self.chain,self.rna)
            print_out_last_frame(config, alist, model_num, cur_chain=self.chain_name[1:-1], final=True)
            model_num+=1
        return model_num

if __name__ == "__main__":
    import sys
    with open(sys.argv[1]) as input:
        atoms = input.readlines()
    if len(sys.argv) > 2:
        atoms = atoms[int(sys.argv[2]):int(sys.argv[3]) + 1]
    print ("Result is", run_through_filtering(atoms, sys.argv[1] + (
        "{}_{}".format(sys.argv[2], sys.argv[3]) if len(sys.argv) > 2 else "") + ".outall.pdb"))


import os
import socket
import zlib

from threading import Thread, Condition
from random import choices
from typing import Tuple

from protocol import apply_protocol, handle_switch, handle_fin, finish_con, req_switch
from protocol import calculate_checksum

def handle_syn(client_addr: Tuple[str, int], sock: socket) -> bool:
    # handling Syn signal from the client

    pad = "".join(choices("0", k=15))
    sock.settimeout(10)
    print("SYN signal has been received")
    while True:
        print("Sending SYN, ACK")
        sock.sendto(apply_protocol(pad, ["SYN", "ACK"], 'T', False), client_addr)
        try:
            reply, addr = sock.recvfrom(1500)
            # if int.from_bytes(list(reply[0])[0], "big") == 1:
            if reply[0] == 1:
                # we received ACK - connection is established
                print("Connection established")

                return True
        except socket.timeout:
            # else we send SYN, ACK again
            continue

pr_wait = False
break_threads = False
is_switched = False

# ser_RP stands for server receive packets
def ser_RP(s: socket, client_addr, c: Condition, path):
    global pr_wait, break_threads, is_switched

    payload, addr = s.recvfrom(1500)

    s.settimeout(8)
    is_file = False
    filename = ""
    c.acquire()
    res = b""
    fragments_cnt = 1
    errors_cnt = 0

    if path == 'l':
        path = ""

    pad = "".join(choices("0", k=15))
    while True:
        try:
            while pr_wait is True:
                c.wait()

            if break_threads is True:
                c.release()
                # print("RP thread has been stopped, connection closing process has been started")
                return

            # if received packet with PSH flag
            if payload[0] == 2:
                if chr(payload[5]) == "F":
                    checksum = zlib.crc32(payload[6:]).to_bytes(4, "big")
                else:
                    checksum = calculate_checksum(payload[6:].decode("utf-8"))

                # print(f"calculated: {checksum}\n saved:{payload[1:5]}")

                if checksum == payload[1:5]:
                    if fragments_cnt == 1:
                        # writing down the file name
                        if chr(payload[5]) == 'F':
                            is_file = True
                            filename = payload[6:].decode('utf-8')
                        else:
                            res += payload[6:]
                    else:
                        res += payload[6:]

                    print(f"Fragment number {fragments_cnt} has been received without any errors, replying with ACK")

                    while True:
                        s.sendto(apply_protocol(pad, ["ACK"], "T", False), client_addr)

                        try:
                            reply, addr = s.recvfrom(1500)
                            payload = reply
                            fragments_cnt += 1
                            break
                        # ARQ algorithm
                        except socket.timeout:
                            if break_threads is True:
                                c.release()
                                return
                            while pr_wait is True:
                                c.wait()
                            print("Didn't receive any response, resending ACK signal")
                            continue
                    continue
                else:
                    print(f"Fragment {fragments_cnt} number is damaged, sending Error signal")
                    errors_cnt += 1
                    while True:
                        s.sendto(apply_protocol(pad, ["ERR"], 'T', False), client_addr)

                        try:
                            reply, addr = s.recvfrom(1500)
                            payload = reply
                            # calculating different check sums for files and text messages
                            if chr(payload[5]) == "F":
                                checksum = zlib.crc32(payload[6:]).to_bytes(4, "big")
                            else:
                                checksum = calculate_checksum(payload[6:].decode("utf-8"))
                            if checksum == payload[1:5]:
                                break

                        except socket.timeout:
                            if break_threads is True:
                                c.release()
                                return
                            while pr_wait is True:
                                c.wait()
                            print("Didn't receive any response, resending ERR signal")
                            continue
                    continue

            elif payload[0] == 32:
                # =========================================================================================================
                # Received KA signal but last signal received was PSH - saving message
                if fragments_cnt != 1:
                    print(f"Number of fragments received: {fragments_cnt-1}\n"
                          f"Number of damaged fragments received and resend requests sent: {errors_cnt}")

                    if is_file is True:
                        f = open(path+filename, 'wb')
                        f.write(res)
                        f.close()
                        print(f"File has been received and saved as {path+filename}\n"
                              f"Length of file in Bytes is {os.stat(path+filename).st_size}")
                        filename = ""
                        is_file = False
                    else:
                        print(f"Length of message received in Bytes is {len(res)}\n"
                              f"Next message has been received: {res.decode('utf-8')}")

                    res = b""

                # =========================================================================================================
                # KA algorithm
                else:
                    print("KA received, sending ACK")

                while True:
                    s.sendto(apply_protocol(pad, ["ACK"], 'T', False), client_addr)
                    try:
                        payload, addr = s.recvfrom(1500)
                        # print("In KA condition reply received")
                        break
                    except socket.timeout:

                        if break_threads is True:
                            c.release()
                            # print("Thread is awaken and in the next line it should finish KA func")
                            # print("RP thread has been stopped, connection closing process has been started")
                            return

                        while pr_wait is True:
                            c.wait()

                        print("Didn't receive any response, resending ACK signal")
                        continue

                fragments_cnt = 1
                continue

            # =========================================================================================================
            elif payload[0] == 128:
                if handle_switch(client_addr, s) is True:
                    print("Press enter to switch role")
                    is_switched = True
                    break_threads = True
                    c.release()
                    return
                else:
                    while True:
                        try:
                            reply, addr = s.recvfrom(1500)
                            payload = reply
                            break
                        except socket.timeout:
                            if break_threads is True:
                                c.release()
                                return
                            while pr_wait is True:
                                c.wait()
                            print("Didn't receive any response, resending ERR signal")
                            s.sendto(apply_protocol(pad, ["ERR"], 'T', False), client_addr)
                            continue
                    continue

            elif payload[0] == 129:
                print("Req, Ack received in KA")
                while pr_wait is True:
                    c.wait()

                if break_threads is True:
                    c.release()
                    print("Thread is awaken and in the next line it should finish KA func")
                    # print("RP thread has been stopped, connection closing process has been started")
                    return
                continue

            # if we receive some kind of closing connection signal
            elif payload[0] == 8:
                handle_fin(client_addr, s)
                print("Connection was correctly closed\nPress enter to finish")
                break_threads = True
                c.release()
                return

            # handling FIN, ACK response,
            # it shouldn't be received here, so we respond with ERR flag and switching
            # to the right function
            elif payload[0] == 9:
                print("Sending ERR signal")
                s.sendto(apply_protocol(pad, ["ERR"], "T", False), client_addr)
                c.release()
                return

            elif payload[0] == 16:
                print("Connection was interrupted after receiving RST signal")
                break_threads = True
                c.release()
                return
        except ConnectionResetError:
            s.settimeout(30)
            print("Client has been disconnected, waiting 30 seconds for his return")
            try:
                reply, addr = s.recvfrom(1500)
                payload = reply
                s.settimeout(8)
                print("Client has returned")
                continue
            except socket.timeout:
                print("Client never returned, closing program\n"
                      "press Enter to finish")
                break_threads = True
                c.release()
                return

# function that  is being called when user chooses to be a server
def be_server(server_addr, s: socket):
    global break_threads, pr_wait, is_switched
    is_switched = False

    # Input path where files will be saved
    while True:
        path = input("Enter path where you want to save incoming files\n"
                     "(input 'l' if you want to save to project directory): ")
        if os.path.isdir(path) is True or path == 'l':
            break
        else:
            print("Path is incorrect, try again")
            continue

    # waiting for the client to open the communication
    while True:
        data, addr = s.recvfrom(1500)

        # if int.from_bytes(list(data)[0], "big") == 4:
        if data[0] == 4:
            handle_syn(addr, s)
            break

    # writing down client's addr to the variable
    client_addr = addr
    # when communication has been opened - we receive in cycle packets

    # KA thread
    c = Condition()

    t_rp = Thread(target=ser_RP, args=(s, client_addr, c, path))
    # KA thread blocks once it received a message with PSH signal
    t_rp.start()

    while True:
        ty = input("Choose your next action:\n"
                   "\t1) Switch role to the client: type \'s\'\n"
                   "\t2) Finish communication: type \'x\'\n")
        if break_threads is True:
            # s.close()
            t_rp.join()
            break_threads = False
            # print("Thread is closed")
            return is_switched, client_addr

        if ty == 'x':
            pr_wait = True
            # print("Closing connection")
            # locking up on current thread, KA thread is asleep
            c.acquire()
            if finish_con(client_addr, s) is True:
                print("Connection was correctly closed")
                # setting up break_threads marker and in some time KA thread will terminate
                break_threads = True
            else:
                print("Connection was interrupted")
            # s.close()
            pr_wait = False
            # notifying KA thread that in some time it can continue its work
            c.notify()
            # releasing lock, making KA thread work possible
            c.release()
            # joining KA thread, that means that current function will not run further until thread is finished
            t_rp.join()
            break_threads = False
            # print("Thread is closed")
            return is_switched, client_addr
        elif ty == 's':
            pr_wait = True
            c.acquire()
            if req_switch(client_addr, s) is True:
                break_threads = True
                is_switched = True
                pr_wait = False
                c.notify()
                c.release()
                t_rp.join()
                break_threads = False
                return is_switched, client_addr
            else:
                pr_wait = False
                continue

        else:
            print("Input is incorrect")
            continue


from sqlalchemy import create_engine
from sqlalchemy.ext.declarative import declarative_base
from sqlalchemy.orm import sessionmaker
import json
import os

CONFIG_PATH = "config.json" # is defined a second time in main.py

if os.environ.get("DATABASE_URL") == None:
    with open(CONFIG_PATH) as fp:
        config = json.load(fp)
    DATABASE_URL = config["DATABASE_URL"]
else:
    DATABASE_URL = os.environ.get("DATABASE_URL")
    DATABASE_URL = DATABASE_URL.replace("postgres:", "postgresql:")

engine = create_engine(
    DATABASE_URL,
)
SessionLocal = sessionmaker(autocommit=False, autoflush=False, bind=engine)

Base = declarative_base()


from setuptools import setup

exec(open("perceiver/version.py").read())

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

setup(
    name="perceiver",
    version="0.1.2",
    description="Implement of Perceiver, General Perception with Iterative Attention in TensorFlow",
    packages=["perceiver"],
    long_description=long_description,
    long_description_content_type="text/markdown",
    classifiers=[
        "Development Status :: 4 - Beta",
        "Programming Language :: Python :: 3",
        "Programming Language :: Python :: 3 :: Only",
        "Programming Language :: Python :: 3.7",
        "Programming Language :: Python :: 3.8",
        "Programming Language :: Python :: 3.9",
        "License :: OSI Approved :: MIT License",
        "Intended Audience :: Developers",
        "Intended Audience :: Education",
        "Intended Audience :: Science/Research",
        "Topic :: Scientific/Engineering",
        "Topic :: Scientific/Engineering :: Artificial Intelligence",
        "Topic :: Software Development",
        "Topic :: Software Development :: Libraries",
        "Topic :: Software Development :: Libraries :: Python Modules",
        "Topic :: Scientific/Engineering :: Mathematics",
    ],
    keywords=[
        "perceiver",
        "artificial intelligence",
        "deep learning",
        "transformer",
        "attention mechanism",
    ],
    url="https://github.com/Rishit-dagli/Perceiver",
    author="Rishit Dagli",
    author_email="rishit.dagli@gmail.com",
    install_requires=[
        "tensorflow~=2.4.0",
        "einops>=0.3",
    ],
    extras_require={
        "dev": ["check-manifest", "twine", "numpy"],
    },
)


# -*- coding: utf-8 -*-
"""
Created on Tue Mar 14 09:00:09 2023

@author: Urmi
"""

# -*- coding: utf-8 -*-
"""
Created on Mon May 16 14:45:49 2022

@author: Urmi
"""
#Input files:
#dataset: Data_0 to Data_7 in folder "Dataset", based on the output of Kmeans.py
#stratified random sampling is d one on the datasets individually, followed by merging them into train and test data.
#prediction dataset: loaded in "to predict_dataset"in the same folder as SCSS_predict.py
# choose "Regress_Mode" to decide the algorithm to be used:  #0-linear 1-extratree 2-Random forest 3-XGBoost
#Output files:
#test data is saved as file1; train data: file2; prediction for test data: file4 ; prediction for train data: file3.
# The image outputs are stored in "Image" folder
# The prediction output are stored in "predict" folder

#load libraries
import numpy as np
import sklearn.metrics as sm
import matplotlib.pyplot as plt
import random
np.random.seed(20)

from sklearn.ensemble import RandomForestRegressor
from sklearn.ensemble import ExtraTreesRegressor
import xgboost
import shap

from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import PolynomialFeatures

#Train the Model
def model_train(Data_Train_X,Data_Train_Y,Data_Test_X,Data_Test_Y,Regress_Mode, data_apply_1, data_apply_2, data_apply_3, data_apply_4, data_apply_5, data_apply_6, data_apply_7, data_apply_8, data_apply_9, data_apply_10, data_apply_11, data_apply_12, data_apply_13, data_apply_14, data_apply_15, data_apply_16, data_apply_17):
    #Polynomial_Regression
    if Regress_Mode == 0:
        polynomial_features= PolynomialFeatures(degree = 2)
        Data_Train_X = polynomial_features.fit_transform(Data_Train_X)

        polynomial_features= PolynomialFeatures(degree=2)
        Data_Test_X = polynomial_features.fit_transform(Data_Test_X)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_1 = polynomial_features.fit_transform(data_apply_1)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_2 = polynomial_features.fit_transform(data_apply_2)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_3 = polynomial_features.fit_transform(data_apply_3)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_4 = polynomial_features.fit_transform(data_apply_4)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_5 = polynomial_features.fit_transform(data_apply_5)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_6 = polynomial_features.fit_transform(data_apply_6)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_7 = polynomial_features.fit_transform(data_apply_7)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_8 = polynomial_features.fit_transform(data_apply_8)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_9 = polynomial_features.fit_transform(data_apply_9)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_10 = polynomial_features.fit_transform(data_apply_10)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_11 = polynomial_features.fit_transform(data_apply_11)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_12 = polynomial_features.fit_transform(data_apply_12)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_13 = polynomial_features.fit_transform(data_apply_13)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_14 = polynomial_features.fit_transform(data_apply_14)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_15 = polynomial_features.fit_transform(data_apply_15)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_16 = polynomial_features.fit_transform(data_apply_16)

        polynomial_features= PolynomialFeatures(degree=2)
        data_apply_17 = polynomial_features.fit_transform(data_apply_17)

        model = LinearRegression()

    #Extra Tree
    elif Regress_Mode == 1 :
        model = ExtraTreesRegressor(bootstrap=True, ccp_alpha=0.0, criterion='mse',
                            max_depth=200, max_features='auto', max_leaf_nodes=None,
                            max_samples=None, min_impurity_decrease=0.0,
                            min_samples_leaf=1,
                            min_samples_split=2, min_weight_fraction_leaf=0.0,
                            n_estimators=15, n_jobs=None, oob_score=False,
                            random_state=42, verbose=0, warm_start=False)
    elif Regress_Mode == 2 :
    #Random Forest
        model = RandomForestRegressor(bootstrap=True, ccp_alpha=0.0, criterion='mse',
                                max_depth=500, max_features=None, max_leaf_nodes=80,
                                max_samples=None, min_impurity_decrease=0.0,
                                min_samples_leaf=1,
                                min_samples_split=2, min_weight_fraction_leaf=0.0,
                                n_estimators=300, n_jobs=-1, oob_score=False,
                                random_state=20, verbose=0, warm_start=False) #min_impurity_split=None,
    elif Regress_Mode == 3 :
            #XGBoost
        model = xgboost.XGBRegressor(bootstrap=True, max_depth=300, max_features=None)

    model.fit(Data_Train_X,Data_Train_Y)
    pred_y = model.predict(Data_Train_X) #Train_Predict
    pred_yy = model.predict(Data_Test_X) #Test_Predict

    #_Predict_Data:
    pred_1 = model.predict(data_apply_1)
    pred_2 = model.predict(data_apply_2)
    pred_3 = model.predict(data_apply_3)
    pred_4 = model.predict(data_apply_4)
    pred_5 = model.predict(data_apply_5)
    pred_6 = model.predict(data_apply_6)
    pred_7 = model.predict(data_apply_7)
    pred_8 = model.predict(data_apply_8)
    pred_9 = model.predict(data_apply_9)
    pred_10 = model.predict(data_apply_10)
    pred_11 = model.predict(data_apply_11)
    pred_12 = model.predict(data_apply_12)
    pred_13 = model.predict(data_apply_13)
    pred_14 = model.predict(data_apply_14)
    pred_15 = model.predict(data_apply_15)
    pred_16 = model.predict(data_apply_16)
    pred_17 = model.predict(data_apply_17)

    np.savetxt('./predict/pred_1.txt',pred_1)
    np.savetxt('./predict/pred_2.txt',pred_2)
    np.savetxt('./predict/pred_3.txt',pred_3)
    np.savetxt('./predict/pred_4.txt',pred_4)
    np.savetxt('./predict/pred_5.txt',pred_5)
    np.savetxt('./predict/pred_6.txt',pred_6)
    np.savetxt('./predict/pred_7.txt',pred_7)
    np.savetxt('./predict/pred_8.txt',pred_8)
    np.savetxt('./predict/pred_9.txt',pred_9)
    np.savetxt('./predict/pred_10.txt',pred_10)
    np.savetxt('./predict/pred_11.txt',pred_11)
    np.savetxt('./predict/pred_12.txt',pred_12)
    np.savetxt('./predict/pred_13.txt',pred_13)
    np.savetxt('./predict/pred_14.txt',pred_14)
    np.savetxt('./predict/pred_15.txt',pred_15)
    np.savetxt('./predict/pred_16.txt',pred_16)
    np.savetxt('./predict/pred_17.txt',pred_17)

    if Regress_Mode == 0:
        print('Slope:' , model.coef_)
        print('Intercept:', model.intercept_)
    else:

        FI = model.feature_importances_
        Features = ['Pressure', 'T', 'SiO2', 'TiO2', 'Al2O3', 'FeO', 'MgO', 'CaO', 'NiO', 'Na2O', 'K2O', 'H2O', 'Fe', 'Ni+Cu+Co', 'S', 'O']

        print(Features)

        feature_importance = ({'Features': ['Pressure', 'T', 'SiO2', 'TiO2', 'Al2O3', 'FeO', 'MgO', 'CaO', 'NiO', 'Na2O', 'K2O', 'H2O', 'Fe', 'Ni+Cu+Co', 'S', 'O'], 'Feature imp' : [model.feature_importances_]})

        print (FI)

        import matplotlib.pyplot as plt
        fig = plt.figure()
        ax = fig.add_axes([0,0,1,1])
        ax.bar(Features,FI, color ='maroon')
        plt.xlabel("Features")
        plt.ylabel("Feature Importance")
        plt.title("XGB")
        plt.savefig('./Image/feature_importance.png')
        plt.show()

        np.savetxt('./FI-Dataset.txt',FI)

    pd.DataFrame(pred_y).to_csv("file3.csv")
    pd.DataFrame(pred_yy).to_csv("file4.csv")
    #impute the error parameter
    #R2
    r2_model = sm.r2_score(Data_Train_Y, pred_y) #R2 impute TrainData's R2
    r2_test = sm.r2_score(Data_Test_Y, pred_yy)  #impute TestData's R2

    print(r2_model)

#RMSE
    rmse_model = np.sqrt(sm.mean_squared_error(Data_Train_Y, pred_y)) #RMSE impute TrainData's RMESE
    rmse_test = np.sqrt(sm.mean_squared_error(Data_Test_Y, pred_yy)) #RMSE impute TestData's RMSE

     #Keep three decimals
    r2_model = round(r2_model,3)
    r2_test = round(r2_test,3)
    rmse_model = round(rmse_model,3)
    rmse_test = round(rmse_test,3)

    #tempr = Error Parameter Set
    temp_r =[]
    temp_r.append(r2_model)
    temp_r.append(r2_test)
    temp_r.append(rmse_model)
    temp_r.append(rmse_test)

    # plot
    binary_plot(y_train = Data_Train_Y,
                y_train_label = pred_y,
                y_test = Data_Test_Y,
                y_test_label = pred_yy,
                train_rmse = rmse_model,
                test_rmse = rmse_test,
                train_r2 = r2_model,
                test_r2 = r2_test)
    save_fig("Result_plot")

    #save the result

# make plot by sany He
def binary_plot(y_train,  y_train_label, y_test, y_test_label,
                train_rmse, test_rmse, train_r2, test_r2,
                text_position=[1000.5, 2000.075]):
    """plot the binary diagram

    :param y_train: the label of the training data set
    :param y_train_label: the prediction of the training the data set
    :param y_test: the label of the testing data set
    :param y_test_label: the prediction of the testing data set
    :param train_rmse: the RMSE score of the training data set
    :param test_rmse: the RMSE score of the testing data set
    :param train_r2: the R2 score of the training data set
    :param test_r2: the R2 score of the testing data set
    :param test_position: the coordinates of R2 text for
    """

    plt.figure(figsize=(6,6))
    plt.scatter(y_train, y_train_label, marker="s",
                label="Training set-RMSE={}".format(train_rmse))
    plt.scatter(y_test, y_test_label, marker="o",
                label="Test set-RMSE={}".format(test_rmse))
    plt.legend(loc="upper left", fontsize=14)
    plt.xlabel("Reference value", fontsize=20)
    plt.ylabel("Predicted value", fontsize=20)
    a=[0,10000]; b=[0,10000]
    plt.plot(a, b)
    plt.text(text_position[0]+100.5, text_position[0]+6000.0,
             r'$R^2(train)=${}'.format(train_r2),
             fontdict={'size': 16, 'color': '#000000'})
    plt.text(text_position[0]+100.5, text_position[0]+5000.5,
             r'$R^2(test)=${}'.format(test_r2),
             fontdict={'size': 16, 'color': '#000000'})
    plt.xticks(fontsize=15)
    plt.yticks(fontsize=15)
    plt.ylim((0, 10000))

#save figure
def save_fig(fig_id, tight_layout=True):
    '''
    Run to save automatic pictures

    :param fig_id: image name
    '''
    path = "./Image/"+fig_id+".png"
    print("Saving figure", fig_id)
    if tight_layout:
        plt.tight_layout()
    plt.savefig(path, format='png', dpi=300)

#input data：data_ is source_data，data_0 is "label = 0" data，data_1 is "label = 1"data,data_2 is"label = 2"data
import pandas as pd
#data_ = pd.read_csv("run_new.csv", low_memory=False)

data_0 = np.loadtxt('./dataset/Data_0.txt')
data_1 = np.loadtxt('./dataset/Data_1.txt')
data_2 = np.loadtxt('./dataset/Data_2.txt')
data_3 = np.loadtxt('./dataset/Data_3.txt')
data_4 = np.loadtxt('./dataset/Data_4.txt')
data_5 = np.loadtxt('./dataset/Data_5.txt')
data_6 = np.loadtxt('./dataset/Data_6.txt')
data_7 = np.loadtxt('./dataset/Data_7.txt')

data_apply_1 = np.loadtxt('./to predict_dataset/Mars3GPa.txt')
data_apply_2 = np.loadtxt('./to predict_dataset/Pred_Earth_Bulk_HT.txt')
data_apply_3 = np.loadtxt('./to predict_dataset/Pred_Earth_Komatiite_IT.txt')
data_apply_4 = np.loadtxt('./to predict_dataset/Pred_Earth_MORB_LT.txt')
data_apply_5 = np.loadtxt('./to predict_dataset/Pred_Mars_basalt_Dry_HT.txt')
data_apply_6 = np.loadtxt('./to predict_dataset/Pred_Mars_basalt_Dry_IT.txt')
data_apply_7 = np.loadtxt('./to predict_dataset/Pred_Mars_basalt_Dry_LT.txt')
data_apply_8 = np.loadtxt('./to predict_dataset/Pred_Mars_basalt_Wet_HT.txt')
data_apply_9 = np.loadtxt('./to predict_dataset/Pred_Mars_basalt_Wet_IT.txt')
data_apply_10 = np.loadtxt('./to predict_dataset/Pred_Mars_basalt_Wet_LT.txt')
data_apply_11 = np.loadtxt('./to predict_dataset/Pred_Moon_Longhi_HT.txt')
data_apply_12 = np.loadtxt('./to predict_dataset/Pred_Moon_Longhi_IT.txt')
data_apply_13 = np.loadtxt('./to predict_dataset/Pred_Moon_Longhi_LT.txt')
data_apply_14 = np.loadtxt('./to predict_dataset/Pred_Moon_Taylor_HT.txt')
data_apply_15 = np.loadtxt('./to predict_dataset/Pred_Moon_Taylor_IT.txt')
data_apply_16 = np.loadtxt('./to predict_dataset/Pred_Moon_Taylor_LT.txt')
data_apply_17 = np.loadtxt('./to predict_dataset/Steenstra.txt')

#Disarrange the sample order of the data set
np.random.shuffle(data_0)
np.random.shuffle(data_1)
np.random.shuffle(data_2)
np.random.shuffle(data_3)
np.random.shuffle(data_4)
np.random.shuffle(data_5)
np.random.shuffle(data_6)
np.random.shuffle(data_7)

#DataMode：Stratified sampling was conducted directly (7:3)
x1 = data_0[0:int(data_0.shape[0]*0.7)]
x2 = data_1[0:int(data_1.shape[0]*0.7)]
x3 = data_2[0:int(data_2.shape[0]*0.7)]
x4 = data_3[0:int(data_3.shape[0]*0.7)]
x5 = data_4[0:int(data_4.shape[0]*0.7)]
x6 = data_5[0:int(data_5.shape[0]*0.7)]
x7 = data_6[0:int(data_6.shape[0]*0.7)]
x8 = data_7[0:int(data_7.shape[0]*0.7)]
Data_Train = np.vstack((x1,x2,x3,x4,x5,x6,x7,x8))
print(Data_Train)

x1 = data_0[int(data_0.shape[0]*0.7):int(data_0.shape[0])]
x2 = data_1[int(data_1.shape[0]*0.7):int(data_1.shape[0])]
x3 = data_2[int(data_2.shape[0]*0.7):int(data_2.shape[0])]
x4 = data_3[int(data_3.shape[0]*0.7):int(data_3.shape[0])]
x5 = data_4[int(data_4.shape[0]*0.7):int(data_4.shape[0])]
x6 = data_5[int(data_5.shape[0]*0.7):int(data_5.shape[0])]
x7 = data_6[int(data_6.shape[0]*0.7):int(data_6.shape[0])]
x8 = data_7[int(data_7.shape[0]*0.7):int(data_7.shape[0])]
Data_Test = np.vstack((x1,x2,x3,x4,x5,x6,x7,x8))
print(Data_Test)

pd.DataFrame(Data_Test).to_csv("file1.csv")
pd.DataFrame(Data_Train).to_csv("file2.csv")

Data_Train_X = Data_Train[:,0:-1]
Data_Train_Y = Data_Train[:,-1]
print(Data_Train_Y)
Data_Test_X = Data_Test[:,0:-1]
Data_Test_Y = Data_Test[:,-1]
print(Data_Test_X)
print(Data_Test_Y)
Regress_Mode = 3  #0-linear 1-extratree 2-Random forest 3-XGBoost
list_R2_RMSE = model_train(Data_Train_X, Data_Train_Y, Data_Test_X, Data_Test_Y,Regress_Mode, data_apply_1, data_apply_2, data_apply_3, data_apply_4, data_apply_5, data_apply_6, data_apply_7, data_apply_8, data_apply_9, data_apply_10, data_apply_11, data_apply_12, data_apply_13, data_apply_14, data_apply_15, data_apply_16, data_apply_17)

linear and ensemble tree SCSS models/SCSS_predict.py


import logging
import os
import sys
import uuid

from . import containerize
from . import deploy
from . import docker_config as docker_config_module
from . import machine_config
from . import preprocess
from . import validate
from tensorflow_cloud.utils import google_api_client

logger = logging.getLogger(__name__)

def remote():
  """True when code is run in a remote cloud environment by TF Cloud."""
  return bool(os.environ.get("TF_KERAS_RUNNING_REMOTELY"))

def run_cloudtuner(num_jobs=1, **kwargs):
    """A wrapper for tfc.run that allows for running concurrent CloudTuner jobs.

    This method takes the same parameters as tfc.run() and it allows duplicating
    a job multiple times to enable running parallel tuning jobs using
    CloudTuner. All jobs are identical except they will have a unique
    KERASTUNER_TUNER_ID environment variable set in the cluster to enable tuning
    job concurrency. This feature is only supported in Notebooks and Colab.

    Args:
        num_jobs: Number of concurrent jobs to be submitted to AI Platform
        training. Note that these are clones of the same job that are executed
        independently. Setting this value to 1 is identical to just calling
        `tfc.run()`.
        **kwargs: keyword arguments for `tfc.run()`.

    Returns:
        A dictionary with two keys.'job_ids' - a list of training job ids
        and 'docker_image'- Docker image generated for the training job.
    """
    # If code is triggered in a cloud environment, do nothing.
    if remote():
        return

    if num_jobs < 1:
        raise ValueError("num_jobs must be greater than 0.")

    run_results = run(**kwargs)

    # Setting prameters for rerun, notes paramters have already been validated
    # in tfc.run()
    docker_img_uri = run_results["docker_image"]
    chief_config = kwargs.pop("chief_config", "auto")
    worker_count = kwargs.pop("worker_count", 0)
    worker_config = kwargs.pop("worker_config", "auto")
    entry_point_args = kwargs.pop("entry_point_args", None)
    stream_logs = kwargs.pop("stream_logs", False)
    job_labels = kwargs.pop("job_labels", None)
    service_account = kwargs.pop("service_account", None)

    job_ids = [run_results["job_id"]]
    for _ in range(1, num_jobs):
        # Setting a unique default Tuner_ID for each Job,
        # This is to ensure all workers within a cluster (job) ask for the same
        # Tuner parameters, while across multiple jobs they recive different
        # HP Tuning parameters.
        default_tuner_id = f"TUNER_ID_{uuid.uuid4().hex}"
        exnteded_entry_point_args = [default_tuner_id]
        if entry_point_args:
            exnteded_entry_point_args.extend(entry_point_args)

        # Deploy Docker image on the cloud.
        job_ids.extend([
            deploy.deploy_job(
                docker_img_uri,
                chief_config,
                worker_count,
                worker_config,
                exnteded_entry_point_args,
                stream_logs,
                job_labels=job_labels,
                service_account=service_account,
            )
        ])

    return {
        "job_ids": job_ids,
        "docker_image": docker_img_uri,
    }

def run(
    entry_point=None,
    requirements_txt=None,
    docker_config="auto",
    distribution_strategy="auto",
    chief_config="auto",
    worker_config="auto",
    worker_count=0,
    entry_point_args=None,
    stream_logs=False,
    job_labels=None,
    service_account=None,
    **kwargs
):
    """Runs your Tensorflow code in Google Cloud Platform.

    Args:
        entry_point: Optional string. File path to the python file or iPython
            notebook that contains the TensorFlow code.
            Note this path must be in the current working directory tree.
            Example - 'train.py', 'training/mnist.py', 'mnist.ipynb'
            If `entry_point` is not provided, then
            - If you are in an iPython notebook environment, then the
                current notebook is taken as the `entry_point`.
            - Otherwise, the current python script is taken as the
                `entry_point`.
        requirements_txt: Optional string. File path to requirements.txt file
            containing additional pip dependencies if any. ie. a file with a
            list of pip dependency package names.
            Note this path must be in the current working directory tree.
            Example - 'requirements.txt', 'deps/reqs.txt'
        docker_config: Optional `DockerConfig`. Represents Docker related
            configuration for the `run` API.
            - image: Optional Docker image URI for the Docker image being built.
            - parent_image: Optional parent Docker image to use.
            - cache_from: Optional Docker image URI to be used as a cache when
                building the new Docker image.
            - image_build_bucket: Optional GCS bucket name to be used for
                building a Docker image via
                [Google Cloud Build](https://cloud.google.com/cloud-build/).
            Defaults to 'auto'. 'auto' maps to a default `tfc.DockerConfig`
            instance.
        distribution_strategy: 'auto' or None. Defaults to 'auto'.
            'auto' means we will take care of creating a Tensorflow
            distribution strategy instance based on the machine configurations
            you have provided using the `chief_config`, `worker_config` and
            `worker_count` params.
            - If the number of workers > 0, we will use
                `tf.distribute.experimental.MultiWorkerMirroredStrategy` or
                `tf.distribute.experimental.TPUStrategy` based on the
                accelerator type.
            - If number of GPUs > 0, we will use
                `tf.distribute.MirroredStrategy`
            - Otherwise, we will use `tf.distribute.OneDeviceStrategy`
            If you have created a distribution strategy instance in your script
            already, please set `distribution_strategy` as None here.
            For example, if you are using `tf.keras` custom training loops,
            you will need to create a strategy in the script for distributing
            the dataset.
        chief_config: Optional `MachineConfig` that represents the
            configuration for the chief worker in a distribution cluster.
            Defaults to 'auto'. 'auto' maps to a standard gpu config such as
            `COMMON_MACHINE_CONFIGS.T4_1X` (8 cpu cores, 30GB memory,
            1 Nvidia Tesla T4).
            For TPU strategy, `chief_config` refers to the config of the host
            that controls the TPU workers.
        worker_config: Optional `MachineConfig` that represents the
            configuration for the general workers in a distribution cluster.
            Defaults to 'auto'. 'auto' maps to a standard gpu config such as
            `COMMON_MACHINE_CONFIGS.T4_1X` (8 cpu cores, 30GB memory,
            1 Nvidia Tesla T4).
            For TPU strategy, `worker_config` should be a TPU config with
            8 TPU cores (eg. `COMMON_MACHINE_CONFIGS.TPU`).
        worker_count: Optional integer that represents the number of general
            workers in a distribution cluster. Defaults to 0. This count does
            not include the chief worker.
            For TPU strategy, `worker_count` should be set to 1.
        entry_point_args: Optional list of strings. Defaults to None.
            Command line arguments to pass to the `entry_point` program.
        stream_logs: Boolean flag which when enabled streams logs back from
            the cloud job.
        job_labels: Dict of str: str. Labels to organize jobs. You can specify
            up to 64 key-value pairs in lowercase letters and numbers, where
            the first character must be lowercase letter. For more details see
            [resource-labels](
            https://cloud.google.com/ai-platform/training/docs/resource-labels)
        service_account: The email address of a user-managed service account
            to be used for training instead of the service account that AI
            Platform Training uses by default. see [custom-service-account](
            https://cloud.google.com/ai-platform/training/docs/custom-service-account)
        **kwargs: Additional keyword arguments.

    Returns:
        A dictionary with two keys.'job_id' - the training job id and
        'docker_image'- Docker image generated for the training job.
    """
    # If code is triggered in a cloud environment, do nothing.
    # This is required for the use case when `run` is invoked from within
    # a python script.
    if remote():
        return

    docker_base_image = kwargs.pop("docker_base_image", None)
    docker_image_bucket_name = kwargs.pop("docker_image_bucket_name", None)

    if kwargs:
        # We are using kwargs for forward compatibility in the cloud. For eg.,
        # if a new param is added to `run` API, this will not exist in the
        # latest tensorflow-cloud package installed in the cloud Docker envs.
        # So, if `run` is used inside a python script or notebook, this python
        # code will fail to run in the cloud even before we can check
        # `TF_KERAS_RUNNING_REMOTELY` env var because of an additional unknown
        # param.
        raise TypeError("Unknown keyword arguments: %s" % (kwargs.keys(),))

    # Get defaults values for input param

    # If `entry_point` is not provided it means that the `run` API call
    # is embedded in the script/notebook that contains the Keras module.
    # For this to run successfully in the cloud env, `tensorflow-cloud` pip
    # package is required to be installed in addition to the user provided
    # packages.
    if chief_config == "auto":
        chief_config = machine_config.COMMON_MACHINE_CONFIGS["T4_1X"]
    if worker_config == "auto":
        worker_config = machine_config.COMMON_MACHINE_CONFIGS["T4_1X"]
    if docker_config == "auto":
        docker_config = docker_config_module.DockerConfig()
    docker_config.parent_image = (docker_config.parent_image or
                                  docker_base_image)
    docker_config.image_build_bucket = (docker_config.image_build_bucket or
                                        docker_image_bucket_name)

    # Working directory in the Docker container filesystem.
    destination_dir = "/app/"
    if not isinstance(worker_count, int):
        worker_count = int(worker_count)
    called_from_notebook = _called_from_notebook()

    # Run validations.
    print("Validating environment and input parameters.")
    validate.validate(
        entry_point,
        requirements_txt,
        distribution_strategy,
        chief_config,
        worker_config,
        worker_count,
        entry_point_args,
        stream_logs,
        docker_config.image_build_bucket,
        called_from_notebook,
        job_labels=job_labels or {},
        service_account=service_account,
        docker_parent_image=docker_config.parent_image,
    )
    print("Validation was successful.")

    # Make the `entry_point` cloud and distribution ready.
    # A temporary script called `preprocessed_entry_point` is created.
    # This contains the `entry_point` wrapped in a distribution strategy.
    preprocessed_entry_point = None
    if (distribution_strategy == "auto"
        or entry_point is None
        or entry_point.endswith("ipynb")):
        preprocessed_entry_point, \
          pep_file_descriptor = preprocess.get_preprocessed_entry_point(
              entry_point,
              chief_config,
              worker_config,
              worker_count,
              distribution_strategy,
              called_from_notebook=called_from_notebook,
              return_file_descriptor=True,
          )

    # Create Docker file, generate a tarball, build and push Docker
    # image using the tarball.
    print("Building and pushing the Docker image. This may take a few minutes.")
    cb_args = (
        entry_point,
        preprocessed_entry_point,
        chief_config,
        worker_config,
    )
    cb_kwargs = {
        "requirements_txt": requirements_txt,
        "destination_dir": destination_dir,
        "docker_config": docker_config,
        "called_from_notebook": called_from_notebook,
    }
    if docker_config.image_build_bucket is None:
        container_builder = containerize.LocalContainerBuilder(
            *cb_args, **cb_kwargs)
    else:
        container_builder = containerize.CloudContainerBuilder(
            *cb_args, **cb_kwargs)
    docker_img_uri = container_builder.get_docker_image()

    # Delete all the temporary files we created.
    if preprocessed_entry_point is not None:
        os.close(pep_file_descriptor)
        os.remove(preprocessed_entry_point)
    for file_path, file_descriptor in container_builder.get_generated_files(
        return_descriptors=True):
        os.close(file_descriptor)
        os.remove(file_path)

    # Setting a unique default Tuner_ID to support kerasTuner and CloudTuner.
    default_tuner_id = f"TUNER_ID_{uuid.uuid4().hex}"
    exnteded_entry_point_args = [default_tuner_id]
    if entry_point_args:
        exnteded_entry_point_args.extend(entry_point_args)

    # Deploy Docker image on the cloud.
    job_id = deploy.deploy_job(
        docker_img_uri,
        chief_config,
        worker_count,
        worker_config,
        exnteded_entry_point_args,
        stream_logs,
        job_labels=job_labels,
        service_account=service_account,
    )

    # Call `exit` to prevent training the Keras model in the local env.
    # To stop execution after encountering a `run` API call in local env.
    if not remote() and entry_point is None and not called_from_notebook:
        sys.exit(0)
    return {
        "job_id": job_id,
        "docker_image": docker_img_uri,
    }

def _called_from_notebook():
    """Detects if we are currently executing in a notebook environment."""
    client_env = google_api_client.get_client_environment_name()
    if client_env in (
        google_api_client.ClientEnvironment.KAGGLE_NOTEBOOK.name,
        google_api_client.ClientEnvironment.COLAB.name):
        return True
    if client_env == google_api_client.ClientEnvironment.HOSTED_NOTEBOOK:
        logger.warning("Vertex AI notebook environment is not supported.")
    return False


# com8 ペリフェラルコード

import ujson
import bluetooth
import random
import struct
import time
import binascii
from BLE_advertising import advertising_payload
import get
import info
import json

from micropython import const

# BLEイベントの定数
_IRQ_CENTRAL_CONNECT = const(1)
_IRQ_CENTRAL_DISCONNECT = const(2)
_IRQ_GATTS_INDICATE_DONE = const(20)

# BLEフラグの定数
_FLAG_READ = const(0x0002)
_FLAG_NOTIFY = const(0x0010)
_FLAG_INDICATE = const(0x0020)

# デバイス情報サービス
_Dev_Info_UUID = bluetooth.UUID(0x180A)
# デバイスの名前
_Dev_CHAR = (bluetooth.UUID(0x2A00), _FLAG_READ | _FLAG_NOTIFY | _FLAG_INDICATE,)  # 読み取り、通知、応答要求付き通知
_Dev_SERVICE = (_Dev_Info_UUID, (_Dev_CHAR,),)

# BLE関連のクラス
class BLE:
    ble = None
    name = None

    def __init__(self, ble, name):
        self._ble = ble
        self._name = name
        self._ble.active(True)
        self._ble.irq(self._irq)
        ((self._handle,),) = self._ble.gatts_register_services((_Dev_SERVICE,))
        self._connections = set()
        self._check = False

    def _payload_1(self, name):
        self._name = name
        self._payload_1 = advertising_payload(
            name=name, services=[_Dev_Info_UUID], appearance=0)
        self._advertise_1()

    def _payload_2(self, name):
        self._name = name
        self._payload_2 = advertising_payload(
            name=name, services=[_Dev_Info_UUID], appearance=0)
        self._advertise_2()

    def _irq(self, event, data):
        # 接続を追跡して通知を送信できるようにします。
        if event == _IRQ_CENTRAL_CONNECT:
            conn_handle, _, _ = data
            self._connections.add(conn_handle)
            self._check = True
        elif event == _IRQ_CENTRAL_DISCONNECT:
            conn_handle, _, _ = data
            self._connections.remove(conn_handle)
            # 新しい接続を許可するために再度広告を開始します。
            self._advertise()
        elif event == _IRQ_GATTS_INDICATE_DONE:
            conn_handle, value_handle, status = data

    def set_dev_name(self, data, notify=False, indicate=False):
        # データは摂氏温度で、0.01度の分解能を持っています。
        # ローカル値を書き込んで、セントラルが読み取るのに備えます。
        self._ble.gatts_write(self._handle, struct.pack('12si', data)) #読み込み可能な書き込み
        if notify or indicate:
            for conn_handle in self._connections:
                if notify:
                    # 接続されたセントラルに通知
                    self._ble.gatts_notify(conn_handle, self._handle)
                if indicate:
                    # 接続されたセントラルに指示
                    self._ble.gatts_indicate(conn_handle, self._handle)

    def _advertise_1(self, interval_us=100000):
        self._ble.gap_advertise(interval_us, adv_data=self._payload_1)

    def _advertise_2(self, interval_us=100000):
        self._ble.gap_advertise(interval_us, adv_data=self._payload_2)

    def _stop(self, interval_us=None):
        self._ble.gap_advertise(interval_us)

    def _key(self, nd):
        with open('data/packet_table.json', 'r') as file:
            data = json.load(file)

        target_val = nd
        target_key = 0

        for key, value in data.items():
            if value == target_val:
                target_key = key
        return target_key

# メインのペリフェラル関数
def periph(distance, timeout):
    i = 0
    flag = 0
    data = None
    name = None
    break_dev = 0
    next_dev = 0
    breaking = 0

    jf_open = open('info/SN01_DN05.json', 'r')
    jf_load = json.load(jf_open)
    gapname = jf_load["device_number"]

    ble = bluetooth.BLE()
    ble.config(gap_name= gapname)
    set_name = ble.config('gap_name')
    b = BLE(ble, name)

    set_name = set_name.decode()
    str_flag = str(flag)

    print(distance)
    print(type(distance))

    route = ujson.loads(open("data/routeinfo.json").read())

    # デバッグ用: ルート情報を表示
    # print(route.values())
    # print(route["relay01"])
    # print(route["relay11"])

    jf_open = open('info/SN01.json', 'r')
    jf_load = json.load(jf_open)
    gapname = jf_load["device_number"]

    if b._check is False and flag == 0:
        next_dev = route["relay01"]
        b._payload_1(next_dev)
        while b._check is False and timeout > 0:
            data = gapname + '_' + distance + '_' + str(break_dev)
            print(data)
            i = (i + 1) % 10
            b.set_dev_name(data, notify=i == 0, indicate=False)
            payload = binascii.hexlify(b._payload_1)
            pay1 = str(binascii.unhexlify(payload), 'utf-8')
            print(pay1)
            print('.')
            time.sleep_ms(1000)
            timeout -= 1

    if b._check is False:
        print("change")
        breaking = next_dev
        flag = 1
        str_flag = str(flag)
        print(type(str_flag))
        print(type(flag))
        print(flag)
        timeout = 10

    if b._check is False and flag == 1:
        next_dev = route["relay11"]
        b._payload_2(next_dev)
        break_dev = b._key(breaking)
        while b._check is False and timeout > 0:
            data = gapname + '_' + distance + '_' + str(break_dev)
            print(data)
            i = (i + 1) % 10
            b.set_dev_name(data, notify=i == 0, indicate=False)
            payload = binascii.hexlify(b._payload_2)
            pay2 = str(binascii.unhexlify(payload), 'utf-8')
            print(pay2)
            print('*')
            time.sleep_ms(1000)
            timeout -= 1

    if b._check is False:
        print("conection faild")
    else:
        print("conected")
        print(data)

    b._stop()
    print("終了")

if __name__ == "__main__":
    dist = 1111
    to = 10
    periph(str(dist),to)


import disnake
import requests

from random import choice
from io import BytesIO
from disnake.ext import commands
from resources.check import check_it
from resources.db import Database
from PIL import Image, ImageDraw, ImageOps

class Booket(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @check_it(no_pm=True, is_nsfw=True)
    @commands.cooldown(1, 5.0, commands.BucketType.user)
    @commands.check(lambda ctx: Database.is_registered(ctx, ctx, vip=True))
    @commands.command(name='bok', aliases=['boquete', 'glubglub', 'blowjob'])
    async def bok(self, ctx, member: disnake.Member = None):
        """eu não vou explicar oq isso faz
        Use ash bok <@pessoa que vc é casado/a>"""
        if member is not None:
            data_user = await self.bot.db.get_data("user_id", ctx.author.id, "users")
            data_member = await self.bot.db.get_data("user_id", member.id, "users")
            if data_member is None:
                return await ctx.send('<:alert:739251822920728708>│**ATENÇÃO** : '
                                      '`esse usuário não está cadastrado!`', delete_after=5.0)
            if member.id == ctx.author.id:
                return await ctx.send('<:alert:739251822920728708>│`VOCE NÃO PODE FAZER SEXO COM VOCÊ MESMO! ISSO '
                                      'SERIA MASTUBARÇÃO...`')

            if data_user['user']['married'] is True and data_member['user']['married'] is True:
                if data_user['user']['married_at'] == member.id and data_member['user']['married_at'] == ctx.author.id:
                    img_ = choice(['images/married/bokfb2.png', 'images/married/bokfb1.png'])
                    original = Image.open(img_).convert('RGBA')
                    original = original.resize((992, 1402))
                    original.save('marrysend.png')
                    mens = member
                    alvo = member.display_avatar
                    autor = ctx.author.display_avatar
                    lista = [[autor, alvo], [427, 290, 190, 208, 237, 200],
                             [(18, 98), (580, 142), (140, 744), (656, 753), (164, 1076), (652, 1078)]]
                    for c in range(6):
                        if c == 0:
                            avatarurl = requests.get(lista[0][0])
                        else:
                            avatarurl = requests.get(lista[0][1])
                        avatar = Image.open(BytesIO(avatarurl.content)).convert('RGBA')
                        avatar = avatar.resize((lista[1][c], lista[1][c]))
                        big_avatar = (avatar.size[0] * 3, avatar.size[1] * 3)
                        mascara = Image.new('L', big_avatar, 0)
                        trim = ImageDraw.Draw(mascara)
                        trim.ellipse((0, 0) + big_avatar, fill=255)
                        mascara = mascara.resize(avatar.size, Image.ANTIALIAS)
                        avatar.putalpha(mascara)
                        exit_avatar = ImageOps.fit(avatar, mascara.size, centering=(0.5, 0.5))
                        exit_avatar.putalpha(mascara)
                        exit_avatar.save('avatar.png')
                        img = Image.open('marrysend.png')
                        img.paste(avatar, lista[2][c], avatar)
                        img.save('marrysend.png')

                    await ctx.send('O casal {} e {} acabam de trocar alguns carinhos orais... '
                                   ':smirk: :flushed:'.format(ctx.author.mention, mens.mention),
                                   file=disnake.File('marrysend.png'))
                else:
                    await ctx.send("<:alert:739251822920728708>│`VOCÊ NÃO ESTÁ CASADO COM ESSA PESSOA!`")
            elif data_member['user']['married'] is False:
                return await ctx.send('<:alert:739251822920728708>│`ELE(A) NÃO ESTA CASADO(A)!`')
            else:
                return await ctx.send('<:alert:739251822920728708>│`VOCE NÃO ESTA CASADO(A)!`')
        else:
            return await ctx.send('<:alert:739251822920728708>│`Você precisa mencionar alguem.`')

    @check_it(no_pm=True)
    @commands.cooldown(1, 5.0, commands.BucketType.user)
    @commands.check(lambda ctx: Database.is_registered(ctx, ctx, cooldown=True, time=3600))
    @commands.command(name='love')
    async def love(self, ctx, member: disnake.Member = None):
        if member is not None:

            query = {"_id": 0, "user_id": 1, "user": 1}
            data_user = await (await self.bot.db.cd("users")).find_one({"user_id": ctx.author.id}, query)

            query = {"_id": 0, "user_id": 1, "user": 1}
            data_member = await (await self.bot.db.cd("users")).find_one({"user_id": member.id}, query)

            if data_member is None:
                try:
                    data_ = await self.bot.db.get_data("user_id", ctx.author.id, "users")
                    update_ = data_
                    del data_['cooldown'][str(ctx.command)]
                    await self.bot.db.update_data(data_, update_, 'users')
                except KeyError:
                    pass
                return await ctx.send('<:alert:739251822920728708>│**ATENÇÃO** : '
                                      '`esse usuário não está cadastrado!`', delete_after=5.0)

            if member.id == ctx.author.id:
                try:
                    data_ = await self.bot.db.get_data("user_id", ctx.author.id, "users")
                    update_ = data_
                    del data_['cooldown'][str(ctx.command)]
                    await self.bot.db.update_data(data_, update_, 'users')
                except KeyError:
                    pass
                return await ctx.send('<:alert:739251822920728708>│`VOCE SO PODE USAR ESSE COMANDO NO(A) SEU(A) '
                                      'PARCEIRO(A)!`')

            if data_user['user']['married'] is True and data_member['user']['married'] is True:
                if data_user['user']['married_at'] == member.id and data_member['user']['married_at'] == ctx.author.id:

                    reward = choice(["heart_left", "heart_right"])
                    cl = await self.bot.db.cd("users")
                    query = {"$inc": {f"inventory.{reward}": 1}}
                    await cl.update_one({"user_id": data_user["user_id"]}, query, upsert=False)
                    icon, name = self.bot.items[reward][0], self.bot.items[reward][1]
                    await ctx.send(f'<a:fofo:524950742487007233>│`PARABENS POR GANHAR O` ✨ **LOVE ITEM** ✨\n'
                                   f'{icon} **1** `{name}`')

                else:
                    try:
                        data_ = await self.bot.db.get_data("user_id", ctx.author.id, "users")
                        update_ = data_
                        del data_['cooldown'][str(ctx.command)]
                        await self.bot.db.update_data(data_, update_, 'users')
                    except KeyError:
                        pass
                    return await ctx.send("<:alert:739251822920728708>│`VOCÊ NÃO ESTÁ CASADO COM ESSA PESSOA!`")

            elif data_member['user']['married'] is False:
                try:
                    data_ = await self.bot.db.get_data("user_id", ctx.author.id, "users")
                    update_ = data_
                    del data_['cooldown'][str(ctx.command)]
                    await self.bot.db.update_data(data_, update_, 'users')
                except KeyError:
                    pass
                return await ctx.send('<:alert:739251822920728708>│`ELE(A) NÃO ESTA CASADO(A)!`')

            else:
                try:
                    data_ = await self.bot.db.get_data("user_id", ctx.author.id, "users")
                    update_ = data_
                    del data_['cooldown'][str(ctx.command)]
                    await self.bot.db.update_data(data_, update_, 'users')
                except KeyError:
                    pass
                return await ctx.send('<:alert:739251822920728708>│`VOCE NÃO ESTA CASADO(A)!`')

        else:
            try:
                data_ = await self.bot.db.get_data("user_id", ctx.author.id, "users")
                update_ = data_
                del data_['cooldown'][str(ctx.command)]
                await self.bot.db.update_data(data_, update_, 'users')
            except KeyError:
                pass
            return await ctx.send('<:alert:739251822920728708>│`Você precisa mencionar alguem.`')

def setup(bot):
    bot.add_cog(Booket(bot))
    print('\033[1;32m( 🔶 ) | O comando \033[1;34mBOOKET\033[1;32m foi carregado com sucesso!\33[m')


# -*- coding: utf-8 -*-
"""
Created on Thu Feb 11 09:40:34 2021

@author: Grant
"""

import random
import math
import numpy
import statistics

def chunks(l, n):
    n = max(1, n)
    return (l[i:i+n] for i in range(0, len(l), n))

n = 15
m = 10

x = [1, 3, 5, 11, 15, 21, 18, 19, 5, 8, 23, 35, 9, 16, 38]

p = 1
theta_array = [0] * (n * m)
r_array = [0] * (n * m)
pi_array = [0] * (n * m)

for count in range(m*n):
    theta = random.uniform(-math.pi/2, math.pi/2)
    r = random.uniform(0, 1)

    temp = (math.sin(p * theta) / (math.cos(theta))**(1/p)) * (math.cos(theta * (1 - p)) / math.log(1 / r))**((1 - p) / p)

    pi_array[count] = temp

pi = list(chunks(pi_array, n))

x_matrix = numpy.array(x)
pi_matrix = numpy.array(pi)

y = numpy.dot(pi_matrix, x_matrix)

for k in range(len(y)):
    y[k] = abs(y[k])

result = statistics.median(y)

print(result)


"""Command-line (script) interface to instapy"""

import argparse
import sys

import numpy as np
from PIL import Image

import instapy
from . import get_filter, io

def run_filter(
    file: str,
    out_file: str = None,
    implementation: str = "python",
    filter: str = "color2gray",
    scale: int = 1,
) -> None:
    """Run the selected filter"""
    # load the image from a file
    image = io.read_image('rain.jpg')
    if scale != 1:
        # Resize image, if needed
        w, h, _ = image.shape
        image = np.resize(image, (int(w*scale), int(h*scale), 3))

    # Apply the filter
    filter = get_filter(filter, implementation)
    filtered = filter(image)
    if out_file:
        # save the file
        io.write_image(filtered, out_file)
    else:
        # not asked to save, display it instead
        io.display(filtered)

def main(argv=None):
    """Parse the command-line and call run_filter with the arguments"""
    if argv is None:
        argv = sys.argv[1:]

    parser = argparse.ArgumentParser()

    # filename is positional and required
    parser.add_argument("file", help="The filename to apply filter to")
    parser.add_argument("-o", "--out", help="The output filename")

    # Add required arguments
    parser.add_argument("implementation", help="The implementation to use for filtering")
    parser.add_argument("-h", "--help", help="show this help message and exit")
    parser.add_argument("-g", "--gray", help="Select gray filter")
    parser.add_argument("-se", "--sepia", help="Select sepia filter")
    parser.add_argument("-sc", "--scale", help="Scale factor to resize image")
    parser.add_argument("-i", "--implementation" , help="The implementation")

    # parse arguments and call run_filter
    args = parser.parse_args()
    args.func(args)