class ObjList:
    def __init__(self, data):
        self.__next = None
        self.__prev = None
        self.__data = data

    def set_next(self, obj):
        self.__next = obj

    def set_prev(self, obj):
        self.__prev = obj

    def get_next(self):
        return self.__next

    def get_prev(self):
        return self.__prev

    def set_data(self, data):
        self.__data = data

    def get_data(self):
        return self.__data

class LinkedList:
    def __init__(self):
        self.head = None
        self.tail = None

    def add_obj(self, obj):
        """добавление нового объекта obj класса ObjList в конец связного списка"""
        if self.head is None and self.tail is None:
            self.head = self.tail = obj
        else:
            self.tail.set_next(obj)
            obj.set_prev(self.tail)
            self.tail = obj

    def remove_obj(self):
        """удаление крайнего объекта из связного списка"""
        if self.head == self.tail:
            self.head = None
            self.tail = None
        else:
            self.tail = self.tail.get_prev()
            self.tail.set_next(None)

    def get_data(self) -> list:
        """получение списка из строк локального свойства __data всех объектов связного списка"""
        pointer, result = self.head, []
        while pointer:
            result.append(pointer.get_data())
            pointer = pointer.get_next()
        return result

lst = LinkedList()
lst.add_obj(ObjList("данные 1"))
lst.add_obj(ObjList("данные 2"))
lst.add_obj(ObjList("данные 3"))
res = lst.get_data()
print(res)

lst = LinkedList()
lst.add_obj(ObjList("данные 1"))
lst.add_obj(ObjList("данные 2"))
lst.remove_obj()
res = lst.get_data()
print(res)
lst.add_obj(ObjList(12))
res = lst.get_data()
print(res)
lst.remove_obj()
lst.remove_obj()
lst.remove_obj()
res = lst.get_data()
print(res)


import math
#import numbertheory
from numbertheory import *
#import multiprocessing
from multiprocessing import Pool
import gc
#import numpy as np
#from numpy.polynomial import polynomial as poly

####### HELPER FUNCTIONS #######

# performs the extended euclidean algorithm
# returns info to help calculate inverses
def egcd(a, b):

    x, y, u, v = 0, 1, 1, 0

    while a != 0:
        q, r = b // a, b % a
        m, n, = x - u*q, y-v*q
        b, a, x, y, u, v = a, r, u, v, m, n

    gcd = b

    return gcd, x, y

# returns the modular inverse of a mod m if a is coprime to m
# returns the gcd of a and m if a is not coprime to m
def modinv(a, m):

    a = a%m

    gcd, x, y = egcd(a, m)

    if gcd != 1: return False, gcd

    else: return True, x % m

# returns whether a is a quadratic residue mod something
def isQR(a, mod):

    squareList = list()

    for i in range(0, mod):
        squareList.append(i**2 % mod)

    return a in squareList

# returns a list of the quadratic residues mod something
def listQRs(mod):

    squareList = list()

    for i in range(0, mod):
        squareList.append(i**2 % mod)

    return squareList

# returns the modular square root of a number if it exists
def sqrtMod(a, mod):

    if not isQR(a, mod): return []

    answerList = list()
    singleList = list(range(0, mod))
    squareList = listQRs(mod)

    for i in range(0, mod):
        if squareList[i] == a:
            answerList.append(singleList[i])

    return answerList

# credit to martin-thoma.com
def legendre_symbol(a, p):

    if a >= p or a < 0:
        return legendre_symbol(a % p, p)
    elif a == 0 or a == 1:
        return a
    elif a == 2:
        if p%8 == 1 or p%8 == 7:
            return 1
        else:
            return -1
    elif a == p-1:
        if p%4 == 1:
            return 1
        else:
            return -1
    elif not isPrime(a):
        factors = primeFactors(a)
        product = 1
        for pi in factors:
            product *= legendre_symbol(pi, p)
        return product
    else:
        if ((p-1)/2)%2==0 or ((a-1)/2)%2==0:
            return legendre_symbol(p, a)
        else:
            return (-1)*legendre_symbol(p, a)

# returns a list of prime factors
# credit to stackoverflow.com/questions/16996217/prime-factorization-list
def primeFactors(n):

    primes = list()

    d = 2
    while d*d <= n:
        while (n%d) == 0:
            primes.append(d)
            n//=d
        d+=1

    if n>1:
        primes.append(n)

    return primes

# creates a proper set of primes involved in the prime factorization of n
# each member is a double: (base, power)
def groupPrimes(n):

    groups = list()
    primes = primeFactors(n)

    distincts = list(set(primes))

    distincts.sort()

    for i in distincts:

        temp = 0
        for j in primes:

            if j == i:
                temp += 1

        groups.append((i, temp))

    return groups

# to solve systems of congruences - credit to rosetta code
def chinese_remainder(mods, exes, lena):

    p = i = prod = 1; sm = 0

    for i in range(lena): prod *= mods[i]
    for i in range(lena):
        p = prod / mods[i]
        sm += exes[i] * modinv(p, mods[i])[1] * p
    return sm % prod

# Fermat primality test - credit to codeproject.com
def isPrime(number):

    import random
    ''' if number != 1 '''
    if (number > 1):
        ''' repeat the test few times '''
        for time in range(3):
            ''' Draw a RANDOM number in range of number ( Z_number )  '''
            randomNumber = random.randint(2, number)-1

            ''' Test if a^(n-1) = 1 mod n '''
            if ( pow(randomNumber, number-1, number) != 1 ):
                return False

        return True
    else:
        ''' case number == 1 '''
        return False

homework = 495960937377360604920383605744987602701101399399359259262820733407167
def multE_Factor(n):

    # point = (1, 2)

    # jobs = []
    # for i in range(15):

    #     factors = list()
    #     print("Curve", i, "\n")

    #     p = multiprocessing.Process(target = E_Factor(factors, i, n))
    #     jobs.append(p)
    #     p.start()

    #     del factors[:]

    outcomes = list()
    for i in range(15): outcomes.append([])

    pool = Pool(processes = 15)
    results = [pool.apply(E_Factor, args = (outcomes[i], i, n)) for i in range(5)]
    print(results)
    print(outcomes)

# Executes multiple factoring processes simultaneously
def Mult_E_Factor(n):

    pool = Pool(processes=20)
    result = pool.map(e_factorize, (range(0, 20), n))
    print(results)

# checks the list generated by E_Factor and reruns it as necessary
def E_Factor_Manager(a, n):

    factors = []
    E_Factor(factors, a, n)
    #print(factors)

    finalFactors = []
    for i in range(len(factors)):

        if not isPrime(factors[i]):
            if factors[i] > 100:
                finalFactors.extend(e_factorize(a+1, factors[i]))
            else: finalFactors.extend(primeFactors(factors[i]))
        else: finalFactors.append(factors[i])
    finalFactors.sort()
    #print(finalFactors)

    return finalFactors

# creates a list of elliptic curve generated factors of an number
def E_Factor(factors, a, n):

    gc.collect()
    print("Factor of", n)
    if isPrime(n):
        factors.append(n)
        return

    point = (1,3,1)
    curve = findB(point, a, n)
    factor = curve.factor(point, math.ceil(math.log(n)))

    if factor != False:
        factors.append(factor)
        E_Factor(factors, a, n//factor)

    if factor == False:
        factors.append(n)
        #print(n)

# finds value b and creates a curve, given a point, a mod, and an a
def findB(point, a, mod):

    b = 0
    while True:

        testCurve = EllipticCurve(a, b, mod)

        if testCurve.onCurve(point):

            testCurve.printme()
            return testCurve

        b += 1

####### ELLIPTIC CURVE CLASS #######

class EllipticCurve:

    def __init__(self, a, b, mod):

        self.a = a
        self.b = b
        self.mod = mod

    def printme(self):

        print("E: y^2 = x^3 +", self.a, "x +", self.b, "( mod", self.mod, ")")

    def neg(self, point):

        if point == (0, 1, 0): return (0, 1, 0)

        return point[0], (-1 * point[1]) % self.mod, 1

    def onCurve(self, point):

        if len(point) < 3:
            print("Point must be a triple.")
            return

        if point[2] == 0: return True

        x, y = point[0], point[1]

        if y in sqrt_mod_m(x**3 + self.a*x + self.b, self.mod):
            return True

        return False

    def add(self, point1, point2):

        if len(point1) < 3 or len(point2) < 3:
            print("Point must be a triple.")
            return

        # anything times the identity is itself
        if point1[2] == 0: return point2
        if point2[2] == 0: return point1

        # the identity times the identity is itself
        if point1[2] == 0 and point2[2] == 0: return (0, 1, 0)

        if point1 != point2:

            if modinv(point1[0] - point2[0], self.mod)[0] == False:
                return (0, modinv(point2[0] - point1[0], self.mod)[1], 2)

            if point1[0] != point2[0]:

                slope = (point2[1] - point1[1]) * modinv(point2[0] - point1[0], self.mod)[1]

            else: return (0, 1, 0)

        if point1 == point2:

            if modinv((2*point1[1])%self.mod, self.mod)[0] == False:
                return (0, modinv(2*point1[1], self.mod)[1], 2)

            slope = (3*(point1[0]**2) + self.a) * modinv(2*point1[1], self.mod)[1]

        x3 = (slope**2 - point1[0] - point2[0]) % self.mod
        y3 = (slope * (point1[0] - x3) - point1[1]) % self.mod

        return (x3, y3, 1)

    def mult(self, point, k):

        if k == 1: return point

        sum = (0, 1, 0)

        for i in range(k):

            sum = self.add(sum, point)

        return sum

    # recursive repeated addition via doubling
    # doubles until next doubling would exceed k
    # then calls itself on the difference until 1 left
    def multP(self, point, k):

        if k == 0: return (0, 1, 0)
        if k == 1: return point

        else:

            temp = point
            doubles = 0

            while True:

                doubles += 1
                if 2**doubles >= k:
                    doubles -= 1
                    break

                temp = self.add(temp, temp)
                if temp[2] == 2: return temp

            leftovers = k - 2**doubles

            temp = self.add(temp, self.multP(point, leftovers))
            if temp[2] == 2: return temp

        return temp

    # this works, slowly
    def pointOrder(self, point):

        answer = (0, 1, 0)
        count = 0

        while True:

            answer = self.add(answer, point)
            #print(count, answer, test.onCurve(answer))
            count += 1
            if answer == (0, 1, 0): break

        return count

    def bsgsGroupOrder(self, point):

        p = self.mod                            # set the constants
        m = p + 1 - math.ceil(2*(p**(1/2)))
        z = math.ceil(2*(p**(1/4)))
        m, z = int(m), int(z)
        mP = self.multP(point,m)

        babyList  = list()
        giantList  = list()
        answerList  = list()
        matchList = list()

        for i in range(z):                      # create the lists

            babyList.append(self.multP(point,i))
            giantList.append(self.neg(self.add(mP, self.multP(point,i*z))))

        for i in babyList:                      # find the matches
            for j in giantList:
                if i == j:

                    answerList.append(m + babyList.index(i) + giantList.index(j)*z)
                    matchList.append((i, j))

        for i in range(len(babyList)): print(babyList[i], "\t", giantList[i])
        print("ANSWER:")
        for i in matchList: print(i)            # print results
        return answerList

    def pohlig_hellman(self, P, Q):

        originalQ = Q
        N = self.pointOrder(P)

        factors = groupPrimes(N)        # groupPrimes() returns a list of doubles where
                                        # the first element of each double is the base
        mods = list()                   # and the second is the exponent, so we can
        exes = list()                   # refer to each as necessary

        for n in factors:

            mods.append(n[0]**n[1])

        for q in factors:               # for each component of the modulus N

            print("\n***********************")

            T = list()
            Ks = list()
            Q = originalQ               # reset Q

            e = q[1]                    # the power of the prime factor

            for j in range(q[0]):

                T.append(self.multP(P, j*(N/q[0])))     # create T list

            print("T:", T)

            for i in range(1, e+1):                     # for all elements of the base-k
                                                        # expansion of current q
                candidate = self.multP(Q, N/(q[0]**i))
                K = T.index(candidate)                  # find the candidate in T
                Ks.append(K)                            # add to the list of ks ()
                                                        # then update Q

                Q = self.add(Q, self.neg(self.multP(P, K*q[0]**(i-1))))
                print("Q", i, " is", Q, "-", K, "*",q[0], "^", i-1, "*", P)

            sum = 0
            for k in Ks:                                # evaluate the expansion

                sum += k*q[0]**Ks.index(k)
                sum %= q[0]**q[1]

            print(sum, "mod ", q[0]**q[1], "=", sum)
            exes.append(sum)                            # add it to the list

        print("\n***********************")
        print("SYSTEM:")

        print("X VALUES:\t", exes)
        print("MOD VALUES:\t", mods)

        print("ANSWER:\t\t", chinese_remainder(mods, exes, len(exes)))

    def factor(self, point, b):

        for i in range(2, b):
            #print(i)
            #print(math.factorial(i))
            temp = self.multP(point, math.factorial(i))
            #print(temp)
            if temp[2] == 2:

                if temp[1] != self.mod:

                    return temp[1]
                    break
                    # return(temp[1])
                    #new = EllipticCurve(self.a, self.b, self.mod / temp[1])

                if isPrime(temp[1]):
                    if temp[1] == self.mod:

                        print(temp[1], "is a trivial factor.")
                        return False

                    else: return temp[1]

        return False
        #print("Nothing broken")

def bitwise_xor(a, b):

    c = list()
    for i in range(len(a)):

        c.append((a[i] + b[i])%2)

    return c

def bitwise_and(a, b):

    c = list()
    for i in range(len(a)):

        c.append((a[i] & b[i]))

    return c

def bitwise_or(a, b):

    c = list()
    for i in range(len(a)):

        c.append((a[i] | b[i]))

    return c

def linear_complexity(sequence, polynomial, debug):

    Bx = make_bin_poly([0])             # make these into polynomials
    Cx = make_bin_poly([0])
    Tx = make_bin_poly([0])

    L, N = 0, 0                         # complexity and test length start at 0
    s = sequence

    m = -1
    n = len(sequence)

    d = 0                               # discrepancy

    while N < n:

        if debug: print("----------------\nN =", N, "\n")

        if N==0:

            d = s[0]
            if debug: print("s 0 (", s[0], ")")

        else:

            d = 0
            for i in range(0, L+1):

                if debug: print("s", N-i,"(", s[N-i], ") * ", "c", (i), "(", Cx[i], ") = ", s[N-i] * Cx[i])

                d += s[N-i] * Cx[i]           # calculate the discrepancy

            d%=2

        if debug: print('\nd = ', d)

        if d==1:

            x = make_bin_poly([N-m])    # create x**(N-m)

            Tx = Cx

            Cx = addpoly(Cx, mulpoly(Bx,x))

            if debug: print('\nC(x) = \n', Cx, '\n')

            if L <= N/2:

                L = N + 1 - L
                m = N
                Bx = Tx

        N += 1

    print("\nCOMPLEXITY = ", L)
    if polynomial: print("TAP POLYNOMIAL = \n", Cx)

def make_bin_poly(terms):

    poly = [0]*(terms[0]+1)             # length is the degree + 1
    #print(poly)

    for i in terms:
        poly[len(poly)-(i+1)] = 1

    #print(poly)
    realpoly = np.poly1d(poly)

    return realpoly

def mulpoly(a, b):

    c = np.polymul(a, b)

    return np.poly1d(c.coeffs % 2)

def addpoly(a, b):

    c = a + b

    return np.poly1d(c.coeffs % 2)

def xorStreams(a, b, debug):

    #print(len(a))
    #print(len(b))

    #if len(a) != len(b): print("Sizes not equal")

    C = list()

    for i in range(0, len(a)):

        C.append( (a[i]+b[i]) % 2 )

    if debug: print("*********************")

    if debug: print('A:\t', a)
    if debug: print('B:\t', b)
    if debug: print('C:\t', C)

    return C

def testC(A, B, length, printSequences):

    linear_complexity(xorStreams(A.putout(length, False), B.putout(length, False), printSequences), False)

class LFSR:

    def __init__(self, fill, taps):

        self.fill = list(fill)
        self.register = list(fill)
        self.taps = list(taps)

        for i in range(0, len(self.taps)):

            self.taps[i] -= 1

    def printtaps(self):

        print(self.taps)

    def printfill(self):

        print(self.register)

    def printregister(self):

        print(self.register)

    def newregister(self, sequence):

        self.register = sequence

    def newtaps(self, taps):

        self.taps = taps

        #print(self.taps)

    def reset(self):

        self.register = list(self.fill)

    def tick(self):

        return (self.putout(1, False, False))[0]

    def putout(self, bits, reset, printRegisters):

        if reset: self.reset()

        self.output = []

        next = 0
        for i in range(bits):

            #print(i)

            if printRegisters: print(self.register)
            next = self.xor(self.register, self.taps)
            self.output.append(self.register[0])
            self.register.pop(0)
            self.register.append(next)

        return self.output

    def xor(self, fill, taps):

        sum = 0
        for i in taps:

            sum += fill[len(fill)-i-1]

        sum %= 2

        return sum


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

import traceback
from src.plugins.base import BasePlugin
from lib.response import BaseResponse
from config import settings

class CpuPlugin(BasePlugin):
    def run(self):
        response = BaseResponse()
        try:
            response.data = {'cpu_model': None, 'cpu_physical_count': 0, 'cpu_count': 0}
            temp = self.exec_shell_cmd('snmpwalk -v 2c -c %s %s .1.3.6.1.4.1.674.10892.5.4.1100.30.1.23.1' % (settings.community_name, self.manager_ip))
            cpu_model = temp.split('"')[1]
            response.data['cpu_model'] = cpu_model
            temp = self.exec_shell_cmd('snmpwalk -v 2c -c %s %s .1.3.6.1.4.1.674.10892.5.4.1100.30.1.23.1|wc -l' % (settings.community_name, self.manager_ip))
            cpu_physical_count = int(temp)
            response.data['cpu_physical_count'] = cpu_physical_count
            temp = self.exec_shell_cmd('snmpwalk -v 2c -c %s %s .1.3.6.1.4.1.674.10892.5.4.1100.30.1.18.1' % (settings.community_name, self.manager_ip))
            cpu_count = 0
            for line in temp.split('\n'):
                cpu_count += int(line.split(':')[-1])
            response.data['cpu_count'] = cpu_count
        except Exception as e:
            msg = "%s dell cpu plugin error: %s"
            self.logger.log(msg % (self.hostname, traceback.format_exc()), False)
            response.status = False
            response.error = msg % (self.hostname, traceback.format_exc())
        return response


from .base_page import BasePage
from .locators import ProductPageLocators
from selenium.common.exceptions import NoAlertPresentException
from selenium.webdriver.common.by import By
import math
import webbrowser

class ProductPage(BasePage):
    def go_product_basket_add(self):
        self.browser.find_element(*ProductPageLocators.BTN_ADD_BASKET).click()

    def solve_quiz_and_get_code(self):
        alert = self.browser.switch_to.alert
        x = alert.text.split(" ")[2]
        answer = str(math.log(abs((12 * math.sin(float(x))))))
        alert.send_keys(answer)
        alert.accept()
        try:
            alert = self.browser.switch_to.alert
            alert_text = alert.text
            print(f"Your code: {alert_text}")
            alert.accept()
        except NoAlertPresentException:
            print("No second alert presented")

    def should_be_name_product(self):
        product_name = self.is_element_present(*ProductPageLocators.PRODUCT_NAME)
        message = self.is_element_present(*ProductPageLocators.CONFIRM_MESSAGE)
        assert product_name == message, "Наименование товара отсутсвует в корзине"

    def should_be_price_product(self):
        product_price = self.browser.find_element(*ProductPageLocators.PRODUCT_PRICE).text
        message_price = self.browser.find_element(*ProductPageLocators.PRICE_BASKET).text
        assert product_price in message_price, "Цена товара не соответствует цене в корзине"

    def should_not_be_success_message(self):
        assert self.is_not_element_present(*ProductPageLocators.SUCCESS_MESSAGE), \
            "Success message is presented, but should not be"

    def should_not_be_success_message_disappeared(self):
        assert self.is_disappeared(*ProductPageLocators.SUCCESS_MESSAGE), \
            "Success message is presented, but should not be"


from youtubesearchpython import VideosSearch
import os
import glob

#     __       _       _
#    /  \     | |     | |
#   /    \    | | /\  | | /\   _   _
#  /  /\  \   | |/ /  | |/ /  | | | |
# /  ____  \  | |\ \  | |\ \  | |_| |
#/__/    \__\ |_| \_\ |_| \_\  \___/
#
# Copyright of Akash, 2021
# https://www.github.com/akkupy
# https://t.me/akkupy

def yt_music(song_name, chat_id, msg_id, bot):
    try:
        videosSearch = VideosSearch(song_name, limit=1)

        result = videosSearch.result()
        first_result = result["result"]
        yt_url = first_result[0]["link"]
        yt_title = first_result[0]["title"]
        yt_pub_time = first_result[0]["publishedTime"]
        yt_id = first_result[0]["id"]
        yt_duration = first_result[0]["duration"]

        if not os.path.isdir("./music/"):
            os.makedirs("./music/")
        yt_song = (
                f'youtube-dl --force-ipv4 -q -o "./music/{yt_title}.%(ext)s" --extract-audio --audio-format mp3 --audio-quality 128k '
                + yt_url
        )

        os.system(yt_song)
        try:
            a = glob.glob("./music/*.webm")
            b = a[0]
            c = b[8:]
        except:
            a = glob.glob("./music/*.mp3")
            b = a[0]
            c = b[8:]
        dir = f"./music/{c}"
        dir1 = f"./music/{c}"
        capy = f"**Song Name ➠** `{yt_title}` \n**Published On ➠** `{yt_pub_time}` \n**Duration ➠** `{yt_duration}` \n**Link ➠** `{yt_url}`"
        if os.path.exists(dir):
            try:
                bot.sendChatAction(chat_id=chat_id, action="upload_audio")
                bot.send_audio(audio=open(dir, 'rb'), caption=capy, chat_id=chat_id, reply_to_message_id=msg_id)
                os.remove(dir)
            except:
                bot.sendMessage(chat_id=chat_id, text="Audio Size is too large,Check the link below",
                                reply_to_message_id=msg_id)
                bot.sendMessage(chat_id=chat_id, text=yt_url, reply_to_message_id=msg_id)
                os.remove(dir)
        elif os.path.exists(dir1):
            try:
                bot.sendChatAction(chat_id=chat_id, action="upload_audio")
                bot.send_audio(audio=open(dir1, 'rb'), caption=capy, chat_id=chat_id, reply_to_message_id=msg_id)
                os.remove(dir1)
            except:
                bot.sendMessage(chat_id=chat_id, text="Audio Size is too large,Check the link below",
                                reply_to_message_id=msg_id)
                bot.sendMessage(chat_id=chat_id, text=yt_url, reply_to_message_id=msg_id)
                os.remove(dir1)

        else:
            bot.sendChatAction(chat_id=chat_id, action="typing")
            bot.sendMessage(chat_id=chat_id, text="Song Not Found!", reply_to_message_id=msg_id)

    except:
        bot.sendChatAction(chat_id=chat_id, action="typing")
        bot.sendMessage(chat_id=chat_id, text="Unable to retreive the Song :( Check out the link", reply_to_message_id=msg_id)
        if yt_url is not "":
            bot.sendMessage(chat_id=chat_id, text=yt_url, reply_to_message_id=msg_id)


from collections import deque
from dataclasses import dataclass, field, replace
from typing import Type
import copy
import numpy as np
import pandas as pd
import re

# little helper class
class ldf_dict(dict):
    def __init__(self):
        self = dict()

    def add(self, key, value):
        self[key] = value

@dataclass
class Nodes:
    master: str
    timer_base_ms: float
    jitter_ms: float
    slaves: list = field(default_factory=list)

@dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)
class Signal:
    size: int
    init_val: int
    publisher: str
    subscriber: str

@dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)
class Frame:
    identifier: int
    publisher: str
    response_length: int
    signals: ldf_dict()

@dataclass(init=True, repr=True, eq=True, order=False, unsafe_hash=False, frozen=False)
class Diagnostic_signal:
    size: int
    init_val: int

@dataclass
class Node_attribute:
    lin_protocol: float
    configure_NAD: str
    product_id: list
    response_error: str
    P2_min_ms: int
    ST_min_ms: int
    configure_frames: ldf_dict()

class LDFParser:
    """
    Wording: every element of the ldf e.g. Nodes {} or Signals {} is
    called attribute.
    """
    __closed_curly: np.ndarray
    __opened_curly: np.ndarray
    __ldf_data: np.ndarray
    __ldf_header: np.ndarray
    __start_of_attribute: np.ndarray
    __start_of_frames: np.ndarray

    # frames: key=frame_name, value=frame data
    frames = ldf_dict()
    node_attributes = ldf_dict()
    schedule_tables = ldf_dict()
    signals = ldf_dict()
    diagnostic_signals = ldf_dict()
    signal_encoding_types = ldf_dict()
    signal_representation = ldf_dict()
    nodes = Nodes
    bus_name = ""

    def __init__(self, ldf_path):
        self.__ldf_data = pd.read_csv(ldf_path, sep="\n", encoding='latin-1')
        self.__ldf_data = self.__ldf_data.values
        self.__remove_header_info()
        self.__get_bus_name()
        self.__analyse_ldf_elements()

    def parse_all(self):
        for (line_number, axis), value in np.ndenumerate(self.__start_of_attribute):
            if value and self.__ldf_data[line_number]   == "Nodes {":
                self.get_nodes(line_number)
            elif value and self.__ldf_data[line_number] == "Signals {":
                self.get_signals(line_number)
            elif value and self.__ldf_data[line_number] == "Diagnostic_signals {":
                self.get_dignostic_signals(line_number)
            elif value and self.__ldf_data[line_number] == "Frames {":
                self.get_frames()
            elif value and self.__ldf_data[line_number] == "Node_attributes {":
                self.get_node_attributes(line_number)
            elif value and self.__ldf_data[line_number] == "Schedule_tables {":
                self.get_schedule_table(line_number)
            elif value and self.__ldf_data[line_number] == "Signal_encoding_types {":
                self.get_signal_encoding_types(line_number)
            elif value and self.__ldf_data[line_number] == "Signal_representation {":
                self.get_signal_representation(line_number)
        del self.__ldf_data, self.__closed_curly, self.__start_of_frames, self.__start_of_attribute

    def get_nodes(self, line_number=-1):
        nodes = Nodes
        if line_number == -1:
            line_number = int(np.where(self.__ldf_data == "Nodes {")[0]) + 1
        end_of_nodes = self.__get_index_of_next_closed_curly(line_number)
        while line_number < end_of_nodes:
            line_number = line_number + 1
            current_line_value = self.__ldf_data[line_number][0]
            current_line_value = self.__remove_unwanted(current_line_value).split(':')
            if current_line_value[0] == "Master":
                master_values = current_line_value[1].split(',')
                nodes.master = master_values[0]
                nodes.timer_base_ms = float(self.__remove_all_but_num(master_values[1]))
                nodes.jitter_ms = float(self.__remove_all_but_num(master_values[2]))
            elif current_line_value[0] == "Slaves":
                nodes.slaves = current_line_value[1].split(',')
        self.nodes = nodes

    def get_frames(self):
        # self.start_of_frame contains all starting positons of the frame elements
        start_frame_indizes = np.where(self.__start_of_frames[:, 0])[0]
        end_frame_indizes = np.where(self.__closed_curly[:, 0])[0]
        end_frame_indizes = deque(end_frame_indizes)
        # remove not needed closing curly braces
        while end_frame_indizes[0] < start_frame_indizes[0]:
            end_frame_indizes.popleft()
        end_frames_index = self.__get_end_of_attribute(start_frame_indizes[0])
        start_frame_indizes = deque(start_frame_indizes)
        current_line_number = start_frame_indizes.popleft()
        while current_line_number < end_frames_index:
            # first parse the frame header ..
            frame = Frame(identifier=0, publisher="", response_length=0, signals=ldf_dict())
            frame_header = self.__raw_line_to_list(self.__ldf_data[current_line_number][0])
            frame.identifier = frame_header[1]
            frame.publisher = frame_header[2]
            frame.response_length = int(frame_header[3])
            current_line_number = current_line_number + 1
            # .. and then the signals
            end_of_frame_signals = self.__get_end_of_attribute(current_line_number, 1)
            signals = ldf_dict()
            while current_line_number < end_of_frame_signals:
                signal = ldf_dict()
                signal_line = self.__remove_unwanted(self.__ldf_data[current_line_number][0]).split(",")
                signal_name = signal_line[0]
                signal_offset = signal_line[1]
                signal.add("Offset", signal_offset)
                signals.add(signal_name, signal)
                current_line_number = current_line_number + 1
            frame.signals = signals
            self.frames.add(frame_header[0], frame)
            current_line_number = current_line_number + 1

    def get_node_attributes(self, line_number):
        end_of_node_attr = self.__get_end_of_attribute(line_number, 3)
        line_number = line_number + 1
        while line_number < end_of_node_attr:
            node_attribute = Node_attribute(lin_protocol=0.0, configure_NAD="", product_id=[], response_error="",
                                            P2_min_ms=0, ST_min_ms=0, configure_frames=ldf_dict())
            node_attribute_name = self.__remove_unwanted(self.__ldf_data[line_number][0])
            line_number = line_number + 1
            node_attribute.lin_protocol = float(self.__remove_unwanted(self.__ldf_data[line_number][0]).split("=")[1])
            line_number = line_number + 1
            node_attribute.configure_NAD = self.__remove_unwanted(self.__ldf_data[line_number][0]).split("=")[1]
            line_number = line_number + 1
            if node_attribute_name == "DS":
                self.node_attributes.add(node_attribute_name, node_attribute)
                line_number = self.__get_end_of_attribute(line_number, 1) + 1
            else:
                node_attribute.product_id = self.__remove_unwanted(self.__ldf_data[line_number][0]).split("=")[1].split(",")
                line_number = line_number + 1
                node_attribute.response_error = self.__remove_unwanted(self.__ldf_data[line_number][0]).split("=")[1]
                line_number = line_number + 1
                node_attribute.P2_min_ms = int(re.sub(r'[^0-9]', '', self.__remove_unwanted(self.__ldf_data[line_number][0]).split("=")[1]))
                line_number = line_number + 1
                node_attribute.ST_min_ms = int(re.sub(r'[^0-9]', '', self.__remove_unwanted(self.__ldf_data[line_number][0]).split("=")[1]))
                line_number = line_number + 2
                end_of_configurable_frames = self.__get_end_of_attribute(line_number, 1)
                conf_frame_dict = ldf_dict()
                while line_number < end_of_configurable_frames:
                    conf_frame = self.__remove_unwanted(self.__ldf_data[line_number][0]).split("=")
                    conf_frame_dict.add(conf_frame[0], conf_frame[1])
                    line_number = line_number + 1
                node_attribute.configure_frames = conf_frame_dict
                self.node_attributes.add(node_attribute_name, node_attribute)
                line_number = self.__get_end_of_attribute(line_number, 2) + 2

    def get_signal_representation(self, current_line_number):
        current_line_number = current_line_number + 1
        end_of_signal_representation = self.__get_index_of_next_closed_curly(current_line_number)
        while current_line_number < end_of_signal_representation:
            signal_representation_list = self.__remove_unwanted(self.__ldf_data[current_line_number][0]).split(":")
            signal_repre_key = signal_representation_list[0]
            signal_repre_val = signal_representation_list[1].split(",")
            current_line_number = current_line_number + 1
            self.signal_representation.add(signal_repre_key, signal_repre_val)

    def get_signal_encoding_types(self, current_line_number):
        current_line_number = current_line_number + 1
        end_of_signal_enc_types = self.__get_end_of_attribute(current_line_number, 2)
        while current_line_number < end_of_signal_enc_types:
            signal_encoding_name = self.__remove_unwanted(self.__ldf_data[current_line_number][0])
            current_line_number = current_line_number + 1
            end_of_current_sign_enc_type = self.__get_index_of_next_closed_curly(current_line_number)
            encoding_list = []
            while current_line_number < end_of_current_sign_enc_type:
                val_list = self.__ldf_data[current_line_number][0].split(",")
                for i in range(0, len(val_list)):
                    val_list[i] = re.sub(r"^[\s]*|[\";]", "", val_list[i])
                encoding_list.append(val_list)
                current_line_number = current_line_number + 1
            self.signal_encoding_types.add(signal_encoding_name, encoding_list)
            current_line_number = current_line_number + 1

    def get_schedule_table(self, current_line_number):
        current_line_number = current_line_number + 1
        end_of_schedule_tables = self.__get_end_of_attribute(current_line_number, 2)
        while current_line_number < end_of_schedule_tables:
            schedule_table_name = self.__remove_unwanted(self.__ldf_data[current_line_number][0])
            current_line_number = current_line_number + 1
            end_of_current_schedule_table = self.__get_index_of_next_closed_curly(current_line_number)
            frame_slots = ldf_dict()
            while current_line_number < end_of_current_schedule_table:
                #schedule_table = Schedule_table(frame_slot_name="", frame_slot_duration_ms=0)
                current_line_list = re.sub(r"[\t]", "", self.__ldf_data[current_line_number][0]).split(" ")
                frame_slot_name = current_line_list[0]
                frame_slot_duration_ms = current_line_list[2]
                frame_slots.add(frame_slot_name, int(frame_slot_duration_ms))
                current_line_number = current_line_number + 1
            self.schedule_tables.add(schedule_table_name, frame_slots)
            current_line_number = current_line_number + 1

    def get_signals(self, current_line_number):
        current_line_number = current_line_number + 1
        end_of_signals = self.__get_index_of_next_closed_curly(current_line_number)
        while current_line_number < end_of_signals:
            signal = Signal(size=0, init_val=0, publisher="", subscriber="")
            raw_line = self.__ldf_data[current_line_number][0]
            line_as_list = self.__raw_line_to_list(raw_line)
            signal.size = line_as_list[1]
            signal.init_val = line_as_list[2]
            signal.publisher = line_as_list[3]
            signal.subscriber = line_as_list[4]
            current_line_number = current_line_number + 1
            self.signals.add(line_as_list[0], signal)

    def get_dignostic_signals(self, current_line_number):
        current_line_number = current_line_number + 1
        end_of_diagnostic_signals = self.__get_index_of_next_closed_curly(current_line_number)
        while current_line_number < end_of_diagnostic_signals:
            diagnostic_signal = Diagnostic_signal(size=0, init_val=0)
            raw_line = self.__ldf_data[current_line_number][0]
            line_as_list = self.__raw_line_to_list(raw_line)
            diagnostic_signal.size = line_as_list[1]
            diagnostic_signal.init_val = line_as_list[2]
            self.diagnostic_signals.add(line_as_list[0], diagnostic_signal)
            current_line_number = current_line_number + 1

    def __get_bus_name(self):
        for (line_number, axis), value in np.ndenumerate(self.__ldf_header):
            if value.find("Network") != -1:
                self.bus_name = self.__remove_unwanted(value).split(":")[1]

    def __remove_unwanted(self, string: str) -> str:
        """
        :param string: string that contains commas, semicols, whitespace, tabspace or closed curly
        :return: cleaned string
        """
        string = re.sub(r'[\s\t;{}"*/]*', '', string, flags=re.M)
        return string

    def __analyse_ldf_elements(self):
        # TODO: optimzable since it runs three times over the file
        start_pattern = re.compile(r'\b\w+\s{$')
        start_vmatch = np.vectorize(lambda x: bool(start_pattern.match(x)))
        self.__start_of_attribute = start_vmatch(self.__ldf_data)

        # find all closed curlys
        close_curly_pattern = re.compile(r'\s*}$')
        end_vmatch = np.vectorize(lambda x: bool(close_curly_pattern.match(x)))
        self.__closed_curly = end_vmatch(self.__ldf_data)

        open_curly_pattern = re.compile(r'.*{$')
        open_curly_vmatch = np.vectorize(lambda x: bool(open_curly_pattern.match(x)))
        self.__opened_curly = open_curly_vmatch(self.__ldf_data)

        frames_pattern = re.compile(r'\s*[A-Za-z0-9_]+:[\d\sA-Za-z,_]+{$')
        # example: 	AQSe_01: 10, Klima_LIN1, 6 {
        frames_vmatch = np.vectorize(lambda x: bool(frames_pattern.match(x)))
        self.__start_of_frames = frames_vmatch(self.__ldf_data)

    def __remove_all_but_num(self, string: str) -> str:
        return  re.sub(r'[^0-9.]', '', string, flags=re.M)

    def __raw_line_to_list(self, line):
        line = self.__remove_unwanted(line).split(":")
        line = line[:1] + line[1].split(",")
        return line

    def __remove_header_info(self):
        counter = 0
        for line in self.__ldf_data:
            if "/*" in line[0]:
                counter = counter + 1
        if counter != 0:
            self.__ldf_header = copy.deepcopy(self.__ldf_data[:counter])
            self.__ldf_data = self.__ldf_data[counter:]

    def __get_index_of_next_closed_curly(self, index):
        index_ = index + 1
        while not self.__closed_curly[index_]:
            index_ = index_ + 1
        return index_

    def __write_to_arr_till_closed_curly(self, index, np_arr):
        index_ = index + 1
        while not self.__closed_curly[index_]:
            np_arr = np.append(np_arr, self.__ldf_data[index_][0])
            index_ = index_ + 1
        return np_arr

    def __get_end_of_attribute(self, index, successive_closed_curly=2):
        # find end of block by double or tripple closed curly braces
        i = index
        if successive_closed_curly == 1:
            while not self.__closed_curly[i]:
                i = i + 1
        elif successive_closed_curly == 2:
            while not self.__closed_curly[i] or not self.__closed_curly[i + 1]:
                i = i + 1
        elif successive_closed_curly == 3:
            while not self.__closed_curly[i] or not self.__closed_curly[i + 1] or not self.__closed_curly[i + 2]:
                i = i + 1
        else:
            print("Number of curly not supported")
        return i


longest = 0
shortSide = 0
while True:
  A, B, C = map(int, input().split())
  if A == B == C == 0:
    break
  if A > B and A > C:
    longest = A**2
    shortSide = (B**2 + C**2)
  elif B > C and B > A:
    longest = B**2
    shortSide = (A**2 + C**2)
  elif C > A and C > B:
    longest = C**2
    shortSide = (B**2 + A**2)

  if longest == shortSide:
    print("right")
  else:
    print('wrong')


from mymodule_2nd_exercise import *
try:
    a = int(input("Input A: "))
    b = int(input("Input B: "))

    operation = input("What operation to be done: ")
    if b == 0 and operation == "/" or operation == "division":
        raise ZeroDivisionError
    if operation == "add" or operation == "+":
        print(add(a, b))
    elif operation == "minus" or operation == "-":
        print(substract(a, b))
    elif operation == "multiplication" or operation == "*":
        print(multiplication(a, b))
    elif operation == "division" or operation == "/":
        print(division(a, b))
    else:
        raise WrongOperation

except ValueError:
    print("Invalid number")
except WrongOperation:
    print("Wrong operation")
except ZeroDivisionError:
    print("Cant divide by 0")


from django import http

import six
from django.db.models import ProtectedError
from rest_framework import views, exceptions, status
from rest_framework.exceptions import UnsupportedMediaType
from rest_framework.response import Response

from backpack.serializers_bcv1 import BadgeConnectErrorSerializer
from entity.serializers import V2ErrorSerializer, Rfc7591ErrorSerializer
from entity.authentication import CSRFPermissionDenied

def exception_handler(exc, context):
    version = context.get('kwargs', {}).get('version', 'v1')

    if version in ['v2', 'rfc7591']:
        description = 'miscellaneous error'
        field_errors = {}
        validation_errors = []

        if isinstance(exc, exceptions.ParseError):
            description = 'bad request'
            validation_errors = [exc.detail]

            response_code = status.HTTP_400_BAD_REQUEST

        elif isinstance(exc, exceptions.ValidationError):
            description = 'bad request'

            if isinstance(exc.detail, list):
                validation_errors = exc.detail
            elif isinstance(exc.detail, dict):
                field_errors = exc.detail
            elif isinstance(exc.detail, six.string_types):
                validation_errors = [exc.detail]

            response_code = status.HTTP_400_BAD_REQUEST

        elif isinstance(exc, (exceptions.AuthenticationFailed, exceptions.NotAuthenticated)):
            description = 'no valid auth token found'
            response_code = status.HTTP_401_UNAUTHORIZED

        elif isinstance(exc, CSRFPermissionDenied):
            description = 'no valid csrf token found'
            response_code = status.HTTP_401_UNAUTHORIZED

        elif isinstance(exc, (http.Http404, exceptions.PermissionDenied)):
            description = 'entity not found or insufficient privileges'
            response_code = status.HTTP_404_NOT_FOUND

        elif isinstance(exc, ProtectedError):
            description, protected_objects = exc.args
            response_code = status.HTTP_400_BAD_REQUEST

        elif isinstance(exc, UnsupportedMediaType):
            description = exc.detail
            validation_errors = [exc.detail]
            response_code = status.HTTP_415_UNSUPPORTED_MEDIA_TYPE

        elif isinstance(exc, exceptions.APIException):
            field_errors = exc.detail
            response_code = exc.status_code

        else:
            # Unrecognized exception, return 500 error
            return None
        if version == 'v2':
            serializer = V2ErrorSerializer(
                instance={}, success=False, description=description,
                field_errors=field_errors, validation_errors=validation_errors
            )
        else:
            serializer = Rfc7591ErrorSerializer(
                instance={}, field_errors=field_errors, validation_errors=validation_errors
            )
        return Response(serializer.data, status=response_code)

    elif version == 'bcv1':
        # Badge Connect errors
        error = None
        status_code = status.HTTP_400_BAD_REQUEST
        status_text = 'BAD_REQUEST'

        if isinstance(exc, exceptions.ParseError):
            error = exc.detail

        elif isinstance(exc, exceptions.ValidationError):
            error = exc.detail
            status_text = 'REQUEST_VALIDATION_ERROR'

        elif isinstance(exc, exceptions.PermissionDenied):
            status_code = status.HTTP_401_UNAUTHORIZED
            status_text = 'PERMISSION_DENIED'

        elif isinstance(exc, (exceptions.AuthenticationFailed, exceptions.NotAuthenticated)):
            status_code = status.HTTP_401_UNAUTHORIZED
            status_text = 'UNAUTHENTICATED'

        elif isinstance(exc, exceptions.MethodNotAllowed):
            status_code = status.HTTP_405_METHOD_NOT_ALLOWED
            status_text = 'METHOD_NOT_ALLOWED'

        serializer = BadgeConnectErrorSerializer(instance={},
                                                 error=error,
                                                 status_text=status_text,
                                                 status_code=status_code)
        return Response(serializer.data, status=status_code)

    else:
        # Use the default exception-handling logic for v1
        if isinstance(exc, ProtectedError):
            description, protected_objects = exc.args
            return Response(description, status=status.HTTP_400_BAD_REQUEST)
        return views.exception_handler(exc, context)


###
###
### note: had to install webpack, webpack-cli, web-ext globally

from OpenWPM.automation import CommandSequence,TaskManager
import pandas as pd

NUM_BROWSERS = 2
NUM_SITES = 100
vanilla_path = './data_vanilla'
adblock_path = './data_adblock'
sites_path = 'top-1m.csv'

data = pd.read_csv(sites_path,header=None)
sites = data.iloc[:NUM_SITES,1]

def crawl(mode):
    # Loads the default manager preferences and copies of the default browser dictionaries
    manager_params, browser_params = TaskManager.load_default_params(NUM_BROWSERS)
    adblock = (mode == 'adblock')

    # Update browser configuration (use this for per-browser settings)
    for i in range(NUM_BROWSERS):
        browser_params[i]['http_instrument'] = True #Record http requests and responses, saved to http_requests table
        browser_params[i]['cookie_instrument'] = True #Record cookie data, saved to javascript_cookies table
        browser_params[i]['js_instrument'] = True #Record JS calls, saved to javascript table
        browser_params[i]['disable_flash'] = False #Enable flash for all three browsers
        browser_params[i]['display_mode'] = 'native' #Launch all browsers headless
        browser_params[i]['ublock-origin'] = adblock # True for adblock mode, False for vanilla mode

    # Update TaskManager configuration (use this for crawl-wide settings)
    if adblock:
        manager_params['data_directory'] = adblock_path
        manager_params['log_directory'] = adblock_path
    else:
        manager_params['data_directory'] = vanilla_path
        manager_params['log_directory'] = vanilla_path

    # Instantiates the measurement platform
    # Commands time out by default after 60 seconds
    manager = TaskManager.TaskManager(manager_params, browser_params)

    # Visits the sites with all browsers simultaneously
    for site in sites:
        site = 'http://' + site
        command_sequence = CommandSequence.CommandSequence(site,reset=True)
        command_sequence.get(sleep=10, timeout=60)
        #command_sequence.dump_profile_cookies(120)
        manager.execute_command_sequence(command_sequence) # ** = synchronized browsers

    # Shuts down the browsers and waits for the data to finish logging
    manager.close()
    return

# run crawl in vanilla and ad-blocking modes
crawl('vanilla')
crawl('adblock')


'''
Read and write Olympia state files.
'''

import os
import os.path
import sys
from contextlib import redirect_stdout

from .oid import to_oid
from .formatters import print_one_thing, read_oly_file

def fixup_ms(data):
    '''
    For whatever reason, the value in IM/ms needs to have a trailing space
    '''
    for box in data:
        if 'IM' in data[box]:
            if 'ms' in data[box]['IM']:
                value = data[box]['IM']['ms']
                value[0] = value[0].strip() + ' '
                data[box]['IM']['ms'] = value

def write_oly_file(data, kind=False, verbose=False):
    '''
    The main function that drives outputting a file
    '''

    fixup_ms(data)

    order = sorted([int(box) for box in data.keys()])

    count = 0
    for box in order:
        box = str(box)
        if kind:
            if ' '+kind+' ' not in data[box].get('firstline', '')[0]:
                continue
        print_one_thing(data[box])
        del data[box]
        count += 1

    if verbose:
        print('wrote', count, verbose, 'boxes.', file=sys.stderr)

def write_player(data, box, verbose=False):
    player_box = box
    boxlist = data[box].get('PL', {}).get('un', {})
    print_one_thing(data[box])
    del data[box]
    count = 0
    for box in boxlist:
        print_one_thing(data[box])
        del data[box]
        count += 1
    if verbose:
        print('wrote', count, 'characters for player', to_oid(int(player_box)), file=sys.stderr)

def read_players(dir, verbose=False):
    '''
    read every fie in dir whose name is an integer
    '''
    ret = {}
    files = os.listdir(dir)
    for name in files:
        if name.isdigit():
            data = read_oly_file(os.path.join(dir, name), verbose='player ' + name)
            ret.update(data)
    return ret

def write_players(data, dir, verbose=False):
    boxlist = list(data.keys())  # we're deleting as we go
    for box in boxlist:
        if data.get(box) is None:
            continue
        if ' player ' in data[box]['firstline'][0]:
            fact = os.path.join(dir, 'fact')
            if not os.path.isdir(fact):
                os.mkdir(fact)
            filename = os.path.join(dir, 'fact', box)
            with open(filename, 'w') as f:
                with redirect_stdout(f):
                    write_player(data, box, verbose=verbose)

def write_system_file(data):
    fr = None
    lt = 1
    tr = None
    ur = None
    hr = None
    hp = None
    nr = None
    nl = None
    cr = None
    for k, v in data.items():
        fl = v['firstline'][0]
        try:
            na = v['na'][0]
        except KeyError:
            na = ''
        if ' player pl_regular' in fl:
            lt = max(lt, int(v['PL']['lt'][0]))
        if fr is None and ' loc region' in fl and na == 'Faery':
            if v.get('LI', {}).get('hl'):
                fr = k
            else:
                fr = 0
        if tr is None and ' loc region' in fl and na == 'Undercity':
            if data[k].get('LI', {}).get('hl'):
                tr = k
            else:
                tr = 0
        if ur is None and ' loc region' in fl and na == 'Subworld':
            if data[k].get('LI', {}).get('hl'):
                ur = k
            else:
                ur = 0
        if hr is None and ' loc region' in fl and na == 'Hades':
            if data[k].get('LI', {}).get('hl'):
                hr = k
            else:
                hr = 0
        if hp is None and fl.endswith(' loc pit'):  # normal pits are 'pits'
            hp = k
        if nr is None and ' loc region' in fl and na == 'Nowhere':
            nr = k
            nl = v['LI']['hl'][0]
        if cr is None and ' loc region' in fl and na == 'Cloudlands':
            if data[k].get('LI', {}).get('hl'):
                cr = k
            else:
                cr = 0

    if hp is None:
        # not surprising for a player sim
        # if I wanted to do this right I have to also create City of the Dead in a provinces.
        # fake it.
        hp = hr

    days_per_month = 30
    days_since_epoch = lt * days_per_month

    system = '''sysclock: {} {} {}
indep_player=100
gm_player=200
skill_player=202
from_host=foo@example.com
reply_host=foo@example.com
game_title=SIMULATION
post=1
init=1
fr={}
tr={}
ur={}
fp=204
hr={}
hp={}
hl=205
nr={}
nl={}
np=206
cr={}
cp=210
'''.format(lt, days_per_month, days_since_epoch, fr, tr, ur, hr, hp, nr, nl, cr)
    if 'None' in system:
        raise ValueError('failed to find some stuff for system:\n' + system)
    print(system)

def read_lib(libdir):
    if not os.path.isdir(libdir):
        raise ValueError('libdir {} is not a directory'.format(libdir))
    data = read_oly_file(os.path.join(libdir, 'loc'), verbose='loc')
    data.update(read_oly_file(os.path.join(libdir, 'item'), verbose='item'))
    data.update(read_oly_file(os.path.join(libdir, 'skill'), verbose='skill'))
    data.update(read_oly_file(os.path.join(libdir, 'gate'), verbose='gate'))
    data.update(read_oly_file(os.path.join(libdir, 'road'), verbose='road'))
    data.update(read_oly_file(os.path.join(libdir, 'ship'), verbose='ship'))
    data.update(read_oly_file(os.path.join(libdir, 'unform'), verbose='unform'))
    data.update(read_oly_file(os.path.join(libdir, 'misc'), verbose='misc'))

    data.update(read_players(os.path.join(libdir, 'fact'), verbose=True))

    return data

def write_lib(data, libdir):
    if os.path.exists(libdir):
        if not os.path.isdir(libdir):
            raise ValueError('libdir {} is not a directory'.format(libdir))
    else:
        os.mkdir(libdir)

    with open(os.path.join(libdir, 'system'), 'w') as f:
        with redirect_stdout(f):
            write_system_file(data)

    with open(os.path.join(libdir, 'loc'), 'w') as f:
        with redirect_stdout(f):
            write_oly_file(data, kind='loc', verbose='loc')
    with open(os.path.join(libdir, 'item'), 'w') as f:
        with redirect_stdout(f):
            write_oly_file(data, kind='item', verbose='item')
    with open(os.path.join(libdir, 'skill'), 'w') as f:
        with redirect_stdout(f):
            write_oly_file(data, kind='skill', verbose='skill')
    with open(os.path.join(libdir, 'gate'), 'w') as f:
        with redirect_stdout(f):
            write_oly_file(data, kind='gate', verbose='gate')
    with open(os.path.join(libdir, 'road'), 'w') as f:
        with redirect_stdout(f):
            write_oly_file(data, kind='road', verbose='road')
    with open(os.path.join(libdir, 'ship'), 'w') as f:
        with redirect_stdout(f):
            write_oly_file(data, kind='ship', verbose='ship')
    with open(os.path.join(libdir, 'unform'), 'w') as f:
        with redirect_stdout(f):
            write_oly_file(data, kind='unform', verbose='unform')

    write_players(data, libdir, verbose=True)

    with open(os.path.join(libdir, 'misc'), 'w') as f:
        with redirect_stdout(f):
            write_oly_file(data, verbose='misc')  # catchall


types = {
    "root_list": {
        1: ("day_session"),
    },
    "day_session": {
        1: ("string", "session_uuid"),
        2: ("int32"),
        3: ("sfixed64", "main_timestamp"),
        4: ("string", "location_name"),
        5: ("location_list"),
    },
    "location_list": {
        2: ("gps_location"),
    },
    "gps_location": {
        1: ("sfixed64", "timestamp"),
        2: ("double", "x"),
        3: ("double", "y"),
        4: ("double", "z")
    }
}


# -*- coding: utf-8 -*-
# Author：sen
# Date：2020/3/4 19:09

from typing import List

# Definition for singly-linked list.
class ListNode:
    def __init__(self, x):
        self.val = x
        self.next = None

def buildListNodeA():
    n0 = ListNode(1)
    n1 = ListNode(2)
    n2 = ListNode(3)
    n3 = ListNode(2)
    n4 = ListNode(1)
    n0.next = n1
    n1.next = n2
    n2.next = n3
    n3.next = n4
    n4.next = None
    return n0

def buildListNodeB():
    n0 = ListNode(1)
    n1 = ListNode(2)
    n2 = ListNode(3)
    n2_2 = ListNode(3)
    n3 = ListNode(2)
    n4 = ListNode(1)
    n0.next = n1
    n1.next = n2
    n2.next = n2_2
    n2_2.next = n3
    n3.next = n4
    n4.next = None
    return n0

class Solution:
    def isPalindrome(self, head: ListNode) -> bool:
        if head is None:
            return True
        if head.next is None:
            return True

        mid = self.get_mid(head)
        part2 = mid.next
        reverse_part2 = self.reverseList(part2)
        p1, p2 = head, reverse_part2
        while p2:
            if p1.val != p2.val:
                return False
            p1 = p1.next
            p2 = p2.next
        return True

    def reverseList(self, head: ListNode) -> ListNode:
        # 反转链表
        prev, curr = None, head
        while curr:
            temp = curr.next  # temp变为下一个节点
            curr.next = prev  # 指向前个节点，此时链表断裂
            prev = curr  # prev变为当前节点
            curr = temp  # curr变为temp节点
        return prev

    def get_mid(self, head):
        # 获取链表中间
        if head is None:
            return head
        fast = slow = head
        while fast.next and fast.next.next:
            slow = slow.next
            fast = fast.next.next
        return slow

if __name__ == '__main__':
    so = Solution()
    headA = buildListNodeA()
    headB = buildListNodeB()
    print(so.isPalindrome(headA))
    print(so.isPalindrome(headB))


import time
import aura_sdk as aura
import atexit

atexit.register(aura.close)

print("Devices found:")
for dev in aura.get_devices():
    print("  " + dev.Name)

for j in range(5):
    for i in range(255):
        aura.set_all_to_color(aura.rgb_to_color(i, i, i))
        time.sleep(0.005)
    for i in range(255):
        aura.set_all_to_color(aura.rgb_to_color(255 - i, 255 - i, 255 - i))
        time.sleep(0.005)


"""
Script that trains an NFC bounding interval annotator.

To use tensorboard during or after model training, open a terminal and say:

    conda activate vesper-dev-tf2
    tensorboard --logdir "/Users/Harold/Desktop/NFC/Data/Vesper ML/
        NFC Bounding Interval Annotator 1.0/Logs/<training log dir path>"

and then visit:

    127.0.0.1:6006

in Chrome.
"""

from collections import defaultdict
import math
import time

from matplotlib.backends.backend_pdf import PdfPages
from tensorflow.keras.layers import (
    BatchNormalization, Conv2D, Dense, Flatten, MaxPooling2D)
# from tensorflow.keras.layers import Dropout
from tensorflow.keras.models import Sequential
import matplotlib.pyplot as plt
import numpy as np
import tensorflow as tf

from vesper.mpg_ranch.nfc_bounding_interval_annotator_1_0.inferrer \
    import Inferrer
from vesper.util.settings import Settings
import vesper.mpg_ranch.nfc_bounding_interval_annotator_1_0.annotator_utils \
    as annotator_utils
import vesper.mpg_ranch.nfc_bounding_interval_annotator_1_0.dataset_utils \
    as dataset_utils
import vesper.util.yaml_utils as yaml_utils

TSEEP_SETTINGS = Settings(

    clip_type='Tseep',

    bound_type='Start',

    waveform_sample_rate=24000,

    positive_example_probability=.5,
    positive_example_call_start_offset=.025,

    waveform_slice_duration=.080,

    # `True` if and only if the waveform amplitude scaling data
    # augmentation is enabled. This augmentation scales each waveform
    # randomly to distribute the waveform log RMS amplitudes uniformly
    # within a roughly 48 dB window.
    waveform_amplitude_scaling_data_augmentation_enabled=False,

    # spectrogram settings
    spectrogram_window_size=.005,
    spectrogram_hop_size=20,
    spectrogram_log_epsilon=1e-10,

    # spectrogram frequency axis slicing settings
    spectrogram_start_freq=4000,
    spectrogram_end_freq=10500,

    # The maximum spectrogram frequency shift for data augmentation,
    # in bins. Set this to zero to disable this augmentation.
    max_spectrogram_frequency_shift=2,

    spectrogram_background_normalization_percentile_rank=30,

    # training settings
    training_batch_size=128,
    training_epoch_step_count=100,  # epoch size is batch size times step count
    training_epoch_count=30,
    model_save_period=5,            # epochs
    dropout_rate=.25,

    # validation settings
    validation_batch_size=1,
    validation_step_count=1000,

    # evaluation plot settings
    max_evaluation_inlier_diff=20,

    # offsets for converting inference value to spectrogram index
    call_start_index_offset=23,
    call_end_index_offset=22,

)

def main():

    settings = TSEEP_SETTINGS

    train_annotator(settings)

    # evaluate_annotator('2020-07-06_09.33.54')

    # show_model_summary('start_2020-06-10_12.13.39', 20)

    # test_get_spectrogram_percentiles()

    # test_create_waveform_dataset_from_tensors()

    # test_create_waveform_dataset_from_tfrecord_files('Training', settings)

    # test_create_training_dataset('Training', settings)

    # test_create_inference_dataset(settings)

    # show_dataset_sizes(settings)

def train_annotator(settings):

    s = settings

    training_name = annotator_utils.create_training_name(s)

    training_dataset = get_dataset('Training', s).batch(s.training_batch_size)
    validation_dataset = \
        get_dataset('Validation', s).batch(s.validation_batch_size)

    input_shape = dataset_utils.get_spectrogram_slice_shape(settings)

    model = Sequential([

        Conv2D(32, (3, 3), activation='relu', input_shape=input_shape),
        # Dropout(s.dropout_rate),
        BatchNormalization(),
        MaxPooling2D((1, 2)),

        # Conv2D(16, (1, 1), activation='relu'),
        # BatchNormalization(),

        Conv2D(32, (3, 3), activation='relu'),
        # Dropout(s.dropout_rate),
        BatchNormalization(),
        MaxPooling2D((1, 2)),

        # Conv2D(16, (1, 1), activation='relu'),
        # BatchNormalization(),

        Flatten(),

        # Dense(32, activation='relu'),
        # BatchNormalization(),

        Dense(32, activation='relu'),
        # Dropout(s.dropout_rate),
        BatchNormalization(),

        Dense(1, activation='sigmoid')

    ])

    model.compile(
        optimizer='adam',
        loss='binary_crossentropy',
        metrics=['accuracy'])

    model.summary()

    log_dir_path = annotator_utils.get_training_log_dir_path(training_name)
    tensorboard_callback = tf.keras.callbacks.TensorBoard(
        log_dir=log_dir_path, histogram_freq=1)

    model_save_callback = ModelSaveCallback(training_name, settings)

    model.fit(
        training_dataset, epochs=s.training_epoch_count,
        steps_per_epoch=s.training_epoch_step_count, verbose=2,
        validation_data=validation_dataset,
        validation_steps=s.validation_step_count,
        callbacks=[tensorboard_callback, model_save_callback])

class ModelSaveCallback(tf.keras.callbacks.Callback):

    def __init__(self, training_name, settings):
        self._training_name = training_name
        self._settings = settings

    def on_epoch_end(self, epoch, logs=None):

        epoch_num = epoch + 1

        if epoch_num % self._settings.model_save_period == 0:

            model_dir_path = \
                annotator_utils.get_tensorflow_saved_model_dir_path(
                    self._training_name, epoch_num)

            self.model.save(model_dir_path)

            save_training_settings(self._settings, self._training_name)

            print(f'Saved model at end of epoch {epoch_num}.')

            print('Evaluating model...')
            evaluate_annotator(self._training_name, epoch_num)

def get_dataset(name, settings):
    dir_path = annotator_utils.get_dataset_dir_path(settings.clip_type, name)
    return dataset_utils.create_training_dataset(dir_path, settings)

def save_training_settings(settings, training_name):
    file_path = annotator_utils.get_training_settings_file_path(training_name)
    text = yaml_utils.dump(settings.__dict__, default_flow_style=False)
    file_path.write_text(text)

def evaluate_annotator(training_name, epoch_num):

    _, settings = annotator_utils.load_model_and_settings(
        training_name, epoch_num)

    dir_path = annotator_utils.get_dataset_dir_path(
        settings.clip_type, 'Validation')
    dataset = dataset_utils.create_validation_dataset(dir_path, settings)

    dataset = dataset.take(settings.validation_step_count)

    inferrer = Inferrer((training_name, epoch_num))

    bounds = inferrer.get_call_bounds(dataset)

    start_diff_counts = defaultdict(int)
    end_diff_counts = defaultdict(int)

    for (inferred_start_index, inferred_end_index, dataset_start_index,
            dataset_end_index) in bounds:

        dataset_start_index = dataset_start_index.numpy()
        dataset_end_index = dataset_end_index.numpy()

        sample_rate = settings.waveform_sample_rate
        start_diff = _get_diff(
            inferred_start_index, dataset_start_index, sample_rate)
        end_diff = _get_diff(
            inferred_end_index, dataset_end_index, sample_rate)

        if start_diff is not None:
            start_diff_counts[start_diff] += 1
            end_diff_counts[end_diff] += 1

#         print(
#             start_diff, end_diff,
#             inferred_start_index, inferred_end_index,
#             dataset_start_index, dataset_end_index)

    _show_diff_counts('Start', start_diff_counts, settings)
    _show_diff_counts('End', end_diff_counts, settings)

    _plot_diff_counts(
        training_name, epoch_num, start_diff_counts, end_diff_counts, settings)

def _get_diff(inferred_index, dataset_index, sample_rate):

    if inferred_index is None:
        return None

    else:
        sample_count = inferred_index - dataset_index
        return int(round(1000 * sample_count / sample_rate))

def _show_diff_counts(name, counts, settings):

    diffs = sorted(counts.keys())

    # Calculate error mean and standard deviation, excluding outliers.
    diff_sum = 0
    diff_sum_2 = 0
    inlier_count = 0
    outlier_count = 0
    for diff in diffs:
        count = counts[diff]
        if diff <= settings.max_evaluation_inlier_diff:
            diff_sum += count * diff
            diff_sum_2 += count * diff * diff
            inlier_count += count
        else:
            outlier_count += count
    diff_mean = diff_sum / inlier_count
    diff_std = math.sqrt(diff_sum_2 / inlier_count - diff_mean * diff_mean)

    print(f'{name} {inlier_count} {diff_mean} {diff_std} {outlier_count}')

def _plot_diff_counts(
        training_name, epoch_num, start_diff_counts, end_diff_counts,
        settings):

    file_path = annotator_utils.get_evaluation_plot_file_path(
        training_name, epoch_num)

    with PdfPages(file_path) as pdf:

        _, (start_axes, end_axes) = plt.subplots(2)

        title = f'{training_name} Epoch {epoch_num} Call Start Errors'
        _plot_diff_counts_aux(start_axes, title, start_diff_counts, settings)

        title = f'{training_name} Epoch {epoch_num} Call End Errors'
        _plot_diff_counts_aux(end_axes, title, end_diff_counts, settings)

        plt.tight_layout()

        pdf.savefig()

        plt.close()

def _plot_diff_counts_aux(axes, title, counts, settings):

    limit = settings.max_evaluation_inlier_diff
    x = np.arange(-limit, limit + 1)

    total_count = sum(counts.values())
    y = np.array([counts[d] for d in x]) / total_count

    axes.bar(x, y)
    axes.set_title(title)
    axes.set_xlabel('diff (ms)')
    axes.set_ylabel('fraction')

def show_model_summary(training_name, epoch_num):
    model_dir_path = annotator_utils.get_tensorflow_saved_model_dir_path(
        training_name, epoch_num)
    model = tf.keras.models.load_model(model_dir_path)
    model.summary()

def test_get_spectrogram_percentiles():

    # For convenience of specification, here first dimension is frequency,
    # second is time. This tensor is transposed below, though, preceding
    # the call to `_get_spectrogram_percentiles`.
    gram = tf.constant([
        [1.1, 0, 0, 89.9],      # 0, 0, 1, 90
        [80, 60, 40, 20],       # 20, 40, 60, 80
        [40, 80, 130, -10]      # 0, 40, 80, 120
    ])

    print('gram:')
    print(gram)

    # Transpose gram so it's a sequence of spectra (i.e. so that first
    # dimension is time and second is frequency), as expected by
    # `_get_spectrogram_percentiles`.
    gram = tf.transpose(gram)

    ranks = tf.constant([25, 50, 75, 100])

    percentiles = dataset_utils._get_spectrogram_percentiles(gram, ranks)

    print('gram percentiles:')
    print(percentiles)

def test_create_waveform_dataset_from_tensors():

    waveforms = [
        np.array([0, 16384]),
        np.array([0, 16384, 32768])]

    dataset = dataset_utils.create_waveform_dataset_from_tensors(waveforms)

    for waveform in dataset:
        print(waveform)

def test_create_waveform_dataset_from_tfrecord_files(dataset_name, settings):

    dir_path = annotator_utils.get_dataset_dir_path(
        settings.clip_type, dataset_name)

    dataset = dataset_utils.create_waveform_dataset_from_tfrecord_files(
        dir_path)

    show_waveform_dataset_stats(dataset, settings.waveform_sample_rate)

def show_waveform_dataset_stats(dataset, sample_rate):

    example_count = 10000
    dataset = dataset.take(example_count)

    min_start_time = 1000000
    max_start_time = 0
    min_end_time = 1000000
    max_end_time = 0
    min_duration = 1000000
    max_duration = 0

    start_time = time.time()

    for _, clip_start_index, clip_end_index, call_start_index, \
            call_end_index, clip_id in dataset:

        clip_start_index = clip_start_index.numpy()
        clip_end_index = clip_end_index.numpy()
        call_start_index = call_start_index.numpy()
        call_end_index = call_end_index.numpy()
        clip_id = clip_id.numpy()

        call_start_time = int(round(1000 * call_start_index / sample_rate))
        min_start_time = min(min_start_time, call_start_time)
        max_start_time = max(max_start_time, call_start_time)

        call_end_time = int(round(1000 * call_end_index / sample_rate))
        min_end_time = min(min_end_time, call_end_time)
        max_end_time = max(max_end_time, call_end_time)

        call_duration = call_end_time - call_start_time
        min_duration = min(min_duration, call_duration)
        max_duration = max(max_duration, call_duration)

#         print(
#             clip_id, len(waveform), clip_start_index, clip_end_index,
#             call_start_index, call_end_index, call_start_time, call_end_time,
#             call_duration)

    end_time = time.time()
    delta_time = end_time - start_time
    rate = example_count / delta_time
    print(
        f'Generated {example_count} examples in {delta_time} seconds, '
        f'a rate of {rate} examples per second.')

    print(f'call start time range ({min_start_time}, {max_start_time})')
    print(f'call end time range ({min_end_time}, {max_end_time})')
    print(f'call duration range ({min_duration}, {max_duration})')

def test_create_training_dataset(dataset_name, settings):

    dir_path = annotator_utils.get_dataset_dir_path(
        settings.clip_type, dataset_name)

    dataset = dataset_utils.create_training_dataset(dir_path, settings)

    show_training_dataset_stats(dataset)

def show_training_dataset_stats(dataset):

    example_count = 10000
    dataset = dataset.take(example_count)

    start_time = time.time()

    positive_count = 0
    for _, label in dataset:
        # print(f'gram {gram.shape} {label}')
        if label == 1:
            positive_count += 1

    end_time = time.time()
    delta_time = end_time - start_time
    rate = example_count / delta_time
    print(
        f'Generated {example_count} examples in {delta_time} seconds, '
        f'a rate of {rate} examples per second.')

    percent = 100 * positive_count / example_count
    print(f'{positive_count} examples, or {percent} percent, were positives.')

def test_create_inference_dataset(settings):

    waveform_durations = [.5, .6]
    sample_rate = settings.waveform_sample_rate
    waveforms = [
        _create_random_waveform(d, sample_rate)
        for d in waveform_durations
    ]
    dataset = dataset_utils.create_waveform_dataset_from_tensors(waveforms)

    dataset = dataset_utils.create_inference_dataset(dataset, settings)

    for forward_slices, backward_slices in dataset:
        slice_count = forward_slices.shape[0]
        assert(backward_slices.shape[0] == slice_count)
        for i in range(slice_count):
            forward_slice = forward_slices[i]
            backward_slice = backward_slices[slice_count - 1 - i]
            _compare_tensors(forward_slice, backward_slice)

def _compare_tensors(x, y):

    """
    Checks that tensor x is the same as tensor y but with the first axis
    reversed.
    """

    assert(tf.reduce_all(x == tf.reverse(y, (0,))))

def _create_random_waveform(duration, sample_rate):
    length = int(round(duration * sample_rate))
    return np.random.randint(-32768, 32768, length)

def show_dataset_sizes(settings):

    from tensorflow.data import TFRecordDataset

    for dataset_name in ('Training', 'Validation'):

        total_size = 0

        print(f'Sizes of files in dataset "{dataset_name}":')

        dir_path = annotator_utils.get_dataset_dir_path(
            settings.clip_type, dataset_name)

        file_paths = sorted(dir_path.glob('*.tfrecords'))

        for file_path in file_paths:
            dataset = TFRecordDataset([str(file_path)])
            size = 0
            for _ in dataset:
                size += 1
            print(f'    {file_path.name}: {size}')
            total_size += size

        print(f'Total size of dataset "{dataset_name}": {total_size}')

if __name__ == '__main__':
    main()


# encoding: utf8

# A class for reading task data from the Mosaiq database.
#
# Authors:
# Christoffer Lervåg
# Helse Møre og Romsdal HF
#
# Python 3.6

# Used for GUI debugging:
#from tkinter import *
#from tkinter import messagebox

from .database import Database

class Task:

  # Returns a single task matching the given database id (TSK_ID) (or None if no match).
  @classmethod
  def find(cls, id):
    instance = None
    row = Database.fetch_one("SELECT * FROM QCLTask WHERE TSK_ID = '{}'".format(str(id)))
    if row != None:
      instance = cls(row)
    return instance

  # Creates a Task instance from a task database row.
  def __init__(self, row):
    # Database attributes:
    self.tsk_id = row['TSK_ID']
    self.created_date = row['Create_DtTm']
    self.created_by_id = row['Create_ID']
    self.edited_date = row['Edit_DtTm']
    self.edited_by_id = row['Edit_ID']
    self.description = row['Description'].rstrip() # If this crashes sometimes, we have to test if the string exists.
    self.inactive = row['Inactive']
    self.due_date = row['Due_DtTm']
    self.responsible_id = row['Responsible_Staff_ID']
    self.estimated_duration = row['Est_Dur']
    self.elapsed_action = row['Elpsd_Action']
    # Convenience attributes:
    self.id = self.tsk_id
    # Cache attributes:
    self.instance_created_by = None
    self.instance_edited_by = None

  # The staff who created the task.
  def created_by(self):
    if not self.instance_created_by:
      self.instance_created_by = Location.find(self.created_by_id)
    return self.instance_created_by

  # The staff who last edited the task.
  def edited_by(self):
    if not self.instance_edited_by:
      self.instance_edited_by = Location.find(self.edited_by_id)
    return self.instance_edited_by


# Flask-Netpad
# version 1.0-alpha
# (C) Abstergo 2018
## netpad.py [MongoDB logic]

from flask_netpad.models import db, Note

# Custom Error

def errorCode(code=404, msg='Object Not Found :( '):
    """
    Returns a custom error code in a dictionary
    :param code: Error Code
    :param msg: Message to return
    :return: error
    """
    data = dict()
    data['code'] = code
    data['error'] = msg
    return data

# ==
def createDB(*args, **kwargs):
    try:
        return 'create db'
    except:
        errorCode()

# ==  List Notes
def listNote(**kwargs):
    try:
        note = Note.objects(**kwargs)
        return note
    except:
        return errorCode()

# == Pagination Note
def pageNote(page=1, per_page=40, **kwargs):
    try:
       note = Note.objects(deleted=False).paginate(page=page, per_page=per_page)
       data = dict()
       data['page_current'] = note.page
       data['page_total'] = note.pages
       data['per_page'] = note.per_page
       data['total_items'] = note.total
       data['data'] = note.items
       return data
    except:
        note = errorCode()
        return note

# ==  Read Note
def readNote(nid):
    try:
        note = Note.objects(id=nid)
        return note
    except:
        return errorCode()

# == New / Create Note
def newNote(slug, content, title=None, **kwargs):
    try:
        note = Note(slug=slug, title=title, content=content, fat={**kwargs})
        note.save()
        return note
    except:
        return errorCode(404, 'Note not Created!')

# Update Note
def updateNote(nid, noteData):
    try:
        # BlogPost.objects(id=post.id).update(title='Example Post')
        note=Note.objects(id=nid).get()
        note.content= noteData.content
        note.title= noteData.title
        note.slug= noteData.slug
        note.save()
        return note
    except:
        return errorCode(404, 'Note not Found!')

# Delete / Remove Note
def delNote(nid):
    # Soft Delete note
    try:
        note = Note.objects(id=nid).update(deleted=True)
        data = dict()
        data['total'] = note
        data['id'] = nid
        return data
    except:
        return errorCode()


#!/usr/bin/env python

import sys

def main ():
    if len(sys.argv) < 2:
        return

    for filepath in sys.argv[1:]:
        process_file(filepath)

def process_file (filepath):
    file_in = open(filepath, "rb")
    content = file_in.read()
    file_in.close()

    if content[0] != '/' or content[1] != '*':
        return

    # Find the position of "*/".
    n = len(content)
    has_star = False
    for i in xrange(2, n):
        c = content[i]
        if has_star and c == '/':
            # Dump all after this position.
            if i == n-2:
                return

            file_out = open(filepath, "wb")
            file_out.write(content[i+2:])
            file_out.close()
            return

        has_star = c == '*'

if __name__ == '__main__':
    main()


import json
from typing import Dict, Generic, TypeVar, cast

import attr
import yaml

from psqlgml.types import GmlData

__all__ = [
    "load_resource",
    "load_by_resource",
    "ResourceFile",
]

T = TypeVar("T")

def load_by_resource(resource_dir: str, resource_name: str) -> Dict[str, GmlData]:
    """Loads all resources reference within the input resource and returns a mapping
    with each resource having an entry.
    For example, if the main resource extends another resource which does not extend
    anything, this function will return two entries, one for each resource
    """
    schema_data: Dict[str, GmlData] = {}
    resource_names = {resource_name}

    while resource_names:
        name = resource_names.pop()
        f = ResourceFile[GmlData](f"{resource_dir}/{name}")
        obj = f.read()
        schema_data[name] = obj

        sub_resource = obj.get("extends")
        if sub_resource:
            resource_names.add(sub_resource)
    return schema_data

def load_resource(resource_folder: str, resource_name: str) -> GmlData:
    """Loads all data resource files into a single Gml Data instance"""

    file_name = f"{resource_folder}/{resource_name}"
    f = ResourceFile[GmlData](file_name)
    rss: GmlData = f.read()

    extended_resource = rss.pop("extends", None)
    if not extended_resource:
        return rss

    extended = load_resource(resource_folder, extended_resource)

    # merge
    rss["nodes"] += extended["nodes"]
    rss["edges"] += extended["edges"]

    if "summary" not in rss:
        rss["summary"] = extended.get("summary", {})
        return rss

    for summary in extended.get("summary", {}):
        if summary in rss["summary"]:
            rss["summary"][summary] += extended["summary"][summary]
        else:
            rss["summary"][summary] = extended["summary"][summary]

    return rss

@attr.s(frozen=True, auto_attribs=True)
class ResourceFile(Generic[T]):
    absolute_name: str

    @property
    def extension(self) -> str:
        return self.absolute_name.split(".")[-1]

    def read(self) -> T:
        loaded: T
        with open(self.absolute_name, "r") as r:
            if self.extension == "json":
                loaded = cast(T, json.loads(r.read()))

            if self.extension in ["yml", "yaml"]:
                loaded = cast(T, yaml.safe_load(r))
        return loaded


from distutils.core import setup
import setuptools

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

setup(
    name='django-view-extractor',
    version='0.1.0',
    packages=setuptools.find_packages(),
    url='https://www.quickrelease.co.uk',
    license='GNU GPLv3',
    author='Nick Solly',
    author_email='nick.solly@quickrelease.co.uk',
    description='Extract Django views, urls and permissions',
    long_description=long_description,
    long_description_content_type="text/markdown",
    install_requires=[
        'tabulate==0.8.6',
    ],
)


n = int(input())
m = int(input())
graph = [[] for _ in range(n + 1)]
cnt = 0
visited = [0] * (n + 1)
for i in range(m):
    a,b = map(int, input().split())
    graph[a].append(b)
    graph[b].append(a)

for i in graph:
    i.sort(reverse = True)

def dfs(v,cnt):
    stack = [v]
    while stack:
        v = stack.pop()
        if visited[v] == 0:
            visited[v] = 1
            cnt += 1
            stack += graph[v]
    return cnt-1

print(dfs(1,cnt))


import spacy

nlp = spacy.load('en_core_web_sm')

example1 = nlp("Animals")
for token in example1:
    print(token.lemma_)

print()

example2 = nlp("I am god")
for token in example2:
    print(token.lemma_)