import os.path
from pathlib import Path
from datetime import datetime
import socket
import selectors
import uuid
from Crypto.Cipher import AES, PKCS1_OAEP
from Crypto.PublicKey import RSA
from Crypto.Random import get_random_bytes
from Crypto.Util.Padding import unpad
from base64 import b64decode, b64encode
from checksum import checksum
import database
import protocol

class Server:
    """
    Server code for mmn15 - Defensive System Programing
    course number 20937

    this is a simple server-client code for exchanging encrypted files based on users
    files are kept inside folders named as the user id of the client that sent them

    @author yonatan tzukerman
    @date 23/03/2023
    """
    DATABASE = "server.db"
    PACKET_SIZE = 1024
    BLOCK_FLAG = False

    def __init__(self, port, host=''):
        """
        set up server parameters
        :param host: hosting ip
        :param port: port number for server to be hosted on
        """
        self.host = host
        self.port = port
        self.users = []  # stores UUID of all users
        self.sel = selectors.DefaultSelector()

        # connect to the database and restore any previous data
        self.backup_db = database.Database(Server.DATABASE)
        self.load_backup_data()

        # keeps track of all files pending crc approval
        self.pending_crc = []

        # handlers for the protocols
        self.requestHandler = {
            protocol.RequestCodes.REQUEST_REGISTRATION.value: self.registration,
            protocol.RequestCodes.REQUEST_PUBLIC_KEY.value: self.public_key_request,
            protocol.RequestCodes.REQUEST_LOGIN.value: self.login_request,
            protocol.RequestCodes.REQUEST_SEND_FILE.value: self.file_request,
            protocol.RequestCodes.REQUEST_VALID_CRC.value: self.valid_crc,
            protocol.RequestCodes.REQUEST_WARNING_CRC.value: self.wrong_crc,
            protocol.RequestCodes.REQUEST_ERROR_CRC.value: self.failed_crc
        }

    def load_backup_data(self):
        """
        load backup user data from database
        """
        data = self.backup_db.fetch_data("clients", "ID, Name")
        self.users = data

        print("Printing user list:")
        for user in self.users:
            print(f"User name - {user[1]}, \nID - {user[0]}\n")

    def start(self):
        """
        Start up the server
        contains an infinite loop for listening to connections
        """
        try:
            # just some socket code to setup the server
            sock = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
            sock.bind((self.host, self.port))
            sock.listen()
            sock.setblocking(Server.BLOCK_FLAG)
            # register the accept connection function for the selector
            self.sel.register(sock, selectors.EVENT_READ, self.accept_connection)
        except Exception as e:
            print(f"Error while setting up server: {e}")
            return

        print(f"Server up and listening in {self.port}!")

        # the main loop
        while True:
            try:
                events = self.sel.select()
                for key, mask in events:
                    try:
                        callback = key.data
                        callback(key.fileobj)
                    except:
                        self.sel.unregister(key.fileobj)
            except Exception as e:
                print(f"Error while listening: {e}")

    def accept_connection(self, sock):
        """
        This function is called whenever there's a new connection
        :param sock: the socket setup in start
        """
        # accept the connection, log it and send to read()
        conn, addr = sock.accept()
        conn.setblocking(Server.BLOCK_FLAG)
        print(f"connection from {addr}")
        self.sel.register(conn, selectors.EVENT_READ, self.read)

    def read(self, conn: socket.socket):
        """
        this is called to read the data from any connection
        :param conn: socket connection
        :return: communicates back to the client if needed
        """
        data = conn.recv(Server.PACKET_SIZE)
        if data:
            try:
                # read the code from the header and send to the proper handler function
                req = protocol.RequestHeader()
                req.unpack(data)
                print(f"Received code: {req.code}")
                if req.code in self.requestHandler.keys():
                    result = self.requestHandler[req.code](conn, data)

                    # try to respond with 2107 if an error happened
                    if not result:
                        try:
                            response = protocol.ErrorResponse()
                            self.write(conn, response.pack())
                        except Exception as e:
                            print(f"failed to deliver exception message - {e}")
            except Exception as e:
                print(f"Exception while reading data from request - {e}")
        else:
            print("No data in connection")

        # closing things
        self.sel.unregister(conn)
        conn.close()

    def write(self, conn: socket.socket, data):
        """
        Write data to client
        :param conn: connection to write back to
        :param data: (bytes) a packed request based on the assignment protocol
        :return: True if sent, False if failed
        """
        size = len(data)
        sent = 0

        # in case data is somehow bigger than packet size (it shouldn't be), we send it in chunks
        while sent < size:
            send_size = min(size - sent, Server.PACKET_SIZE)
            send_data = data[sent:sent + send_size]

            # padding data with 0 until reached packet size
            if len(send_data) < Server.PACKET_SIZE:
                send_data += bytearray(Server.PACKET_SIZE - len(send_data))

            # try writing to client
            try:
                conn.send(send_data)
                sent += len(send_data)
            except:
                print(f"Failed to respond to {conn}")
                return False
        print("Response sent")
        return True

    def registration(self, conn: socket.socket, data):
        """
        CODE = 1100

        client wants to register for the server
        payload is the client name
        if client name is already taken, respond with 2101
        otherwise, register the client as a user with his own UUID and respond with 2100

        :param conn: connection to write back to
        :param data: Registration Request header + payload in bytes (packed)
        :return: (bool) succeeded?
        """
        try:
            request = protocol.RegistrationRequest()
            request.unpack(data)
            print(f"client trying to register as {request.name}")

            # check if name already registered:
            name_used = False
            for user in self.users:
                if user[1] == request.name:
                    name_used = True

            if not name_used:
                # username isn't taken. generate UUID and write him down
                user_id = uuid.uuid4()
                print(f"registration accepted. Generated UUID: {user_id.hex}")

                if not self.backup_db.query(f"INSERT INTO clients (ID, Name, LastSeen) VALUES (?, ?, ?)",
                                            [user_id.hex, request.name, str(datetime.now())]):
                    return False
                self.users.append((user_id.hex, request.name))

                # load data into a response and send it
                response = protocol.RegistrationResponse()  # 2100
                response.client_id = user_id.bytes
                response.header.payload_size = len(response.client_id)

                return self.write(conn, response.pack())
            else:
                # username already taken. send 2101
                response = protocol.RegistrationFailedResponse()
                return self.write(conn, response.pack())

        except Exception as e:
            # print and fall back on exception
            print(f"Exception in registration: {e}")
            return False

    def generate_keys(self, public_key, user_id):
        """
        inner function to generate AES session key
        and encrypt it using a public RSA key and

        :param public_key: public RSA key in base 64
        :param user_id: user id in hex
        :return: tuple - (encrypted session key, session key)
        """
        try:
            print(f"Generating session key for user {user_id}")

            # using Crypto (pycrypto) generate a random session key and encrypt it with public RSA key
            session_key = get_random_bytes(protocol.SYMMETRIC_KEY_SIZE)
            rsa_key = RSA.importKey(b64decode(public_key))
            rsa_cipher = PKCS1_OAEP.new(rsa_key)
            enc_session_key = rsa_cipher.encrypt(session_key)

            print(f"Public key is {public_key} \nSession key is {session_key.hex()}")
            return enc_session_key, session_key

        except Exception as e:
            print(f"Exception while generating keys {e}")
            return None

    def public_key_request(self, conn, data):
        """
        CODE = 1101

        a user is trying to start a new session with a new public key
        this can either be a user that wants to replace his public key, or just a new user
        payload is the client name + public key

        respond with 2102 containing the encrypted session key

        :param conn: connection to write back to
        :param data: Registration Request header + payload in bytes (packed)
        :return: (bool) succeeded?
        """
        try:
            # unpack the data from user
            request = protocol.PublicKeyRequest()
            request.unpack(data)

            user_id = request.header.client_id.hex()
            user_name = request.name
            pub_key = b64encode(request.public_key)

            # make sure user_id and username match the registered data
            if (user_id, user_name) not in self.users:
                return False

            # create an AES session key
            enc_session_key, session_key = self.generate_keys(pub_key, request.header.client_id.hex())

            # delete the old user data and insert the new data
            # this is basically like an update... I decided to divide the "half registered"
            # users from the fully registered ones so delete and insert seems more fitting
            self.backup_db.query(f"DELETE FROM clients WHERE ID = ? AND name = ?", [user_id, user_name])
            if not self.backup_db.query(f"INSERT INTO clients (ID, Name, PublicKey, LastSeen, AESKey) "
                                        f"VALUES (?, ?, ?, ?, ?)",
                                        [user_id, user_name, request.public_key, str(datetime.now()), session_key]):
                return False

            # load data into response and send it
            response = protocol.PublicKeyResponse()  # 2102
            response.client_id = request.header.client_id
            response.symmetric_key = enc_session_key
            response.header.payload_size = len(response.client_id) + len(response.symmetric_key)

            return self.write(conn, response.pack())

        except Exception as e:
            # print and fall back on exception
            print(f"Exception in public key request: {e}")
            return False

    def login_request(self, conn, data):
        """
        CODE = 1102

        a registered user is trying to log in
        need to make sure we have their details in the database before responding

        respond with 2105 containing the encrypted session key if all is good
        respond with 2106 with UUID if data is missing and user needs to register

        :param conn: connection to write back to
        :param data: Registration Request header + payload in bytes (packed)
        :return: (bool) succeeded?
        """
        try:
            # unpacking the data
            request = protocol.LoginRequest()
            request.unpack(data)
            user_id = request.header.client_id.hex()
            user_name = request.name

            # check if user is registered in the database
            query = self.backup_db.query_with_result(f"SELECT PublicKey FROM clients WHERE ID = ? AND Name = ?",
                                                     [user_id, user_name])
            if query:
                # if user is in database, we're all good to send 2105
                public_key = b64encode(query[0][0])

                # create session key
                enc_session_key, session_key = self.generate_keys(public_key, user_id)
                if not self.backup_db.query(f"UPDATE clients SET AESKey = ?, LastSeen = ? WHERE ID = ? AND Name = ?",
                                            [session_key, str(datetime.now()), user_id, user_name]):
                    return False

                # load data into response and send
                response = protocol.LoginResponse()  # 2105
                response.client_id = request.header.client_id
                response.symmetric_key = enc_session_key
                response.header.payload_size = protocol.CLIENT_ID_SIZE + len(response.symmetric_key)

                return self.write(conn, response.pack())
            else:
                # if no data found, we send 2106
                print(f"No data found for user {user_name}, {user_id} during login attempt. sending 2106")
                response = protocol.LoginFailedResponse()  # 2106
                response.client_id = request.header.client_id

                return self.write(conn, response.pack())

        except Exception as e:
            # print and fall back on exception
            print(f"Exception in login request: {e}")
            return False

    def send_checksum(self, conn, file_path, client_id, file_name):
        """
        "private" function to calculate and send the checksum
        this is seperated just in case we ever want to calculate and send the checksum in other functions

        :param conn: connection to write back to
        :param file_path: path to the file we're doing the checksum for
        :param client_id: client id that owns the file
        :param file_name: name of the actual file
        :return: (bool) succeeded?
        """
        try:
            # check the checksum
            cksum, content_size = checksum(str(file_path))
            print(f"check sum is {cksum}")

            # create and pack the response
            response = protocol.CRCResponse()  # 2103
            response.client_id = client_id
            response.content_size = content_size
            response.file_name = bytearray(file_name, 'utf-8')
            response.cksum = cksum

            response.header.payload_size = protocol.CLIENT_ID_SIZE + protocol.CONTENT_SIZE_SIZE
            response.header.payload_size += protocol.NAME_SIZE + protocol.CHECK_SUM_SIZE

            return self.write(conn, response.pack())
        except:
            # if an error happened, we fall back
            return False

    def file_request(self, conn, data):
        """
        CODE = 1103

        a registered user is trying to send a file
        the file should be encrypted using the most recent AES session key
        we want to decrypt it, save and return the details + CRC using 2103

        CRC is the error detecting code. a hashed version of the file data to make sure we (by very high probability)
        got the same file that the client sent us
        CRC is calculated in the same way it does in linux cksum command

        important note:
        this function can be very memory heavy
        that's because we're storing file data and there isn't really a limit on file size...
        I try to minimize it by writing to hard disk and not storing in memory for further use
        yet still the entire request is heavy...
        this can be optimized by decrypting and writing the file while reading the packets
        however, the code is already fairly messy and this will only complicate if further
        so for the current use, this should be fine.

        :param conn: connection to write back to
        :param data: Registration Request header + payload in bytes (packed)
        :return: (bool) succeeded?
        """
        try:
            # unpacking the data. because the file size can be very large,
            # we block other connections while reading and unpacking
            conn.setblocking(True)
            request = protocol.FileSendRequest()  # 1103
            request.unpack(conn, data)
            conn.setblocking(False)
            user_id_hex = request.header.client_id.hex()

            print(f"1103 request from user id is = {user_id_hex} \nFile name is {request.file_name} and size is {request.content_size}")

            # get AES key from db
            query = self.backup_db.query_with_result(f"SELECT AESKey FROM clients WHERE ID = ?",
                                                     [user_id_hex])
            if not query:
                print("Missing user session key for file decryption")
                return False

            session_key = query[0][0]

            # create a directory named after the user id (if non is there)
            path = os.path.join(Path().resolve(), user_id_hex)
            file_path = os.path.join(path, request.file_name)
            if not os.path.exists(user_id_hex):
                os.makedirs(path)

            # check if it's a file that's pending checksum result. in which case we need to check again
            if file_path not in self.pending_crc:
                # make sure user doesn't already have a file by this name another way to handle duplicate files is by
                # adding (1), (2) and so on.. but in that way we'll need to return the new name with the protocol
                # which as per my understanding of the assignment means changing the protocol,
                # and we're not allowed to do that
                if os.path.exists(file_path):
                    print(f"User already has a file by the name {request.file_name}")
                    return False
                self.pending_crc.append(file_path)
            else:
                # remove the file to rewrite it again before the checksum
                print(f"file path is {file_path}")
                os.remove(file_path)

            # decrypt file content
            iv = AES.block_size * b'\0'
            dec_bytes = b''
            for chunk in request.content:
                base64_chunk = b64encode(chunk)
                cipher = AES.new(session_key, AES.MODE_CBC, iv)
                dec_bytes += unpad(cipher.decrypt(b64decode(base64_chunk)), AES.block_size)

            # write the file
            # I'm writing it here and not after making sure the CRC is valid to not store everything in memory
            with open(file_path, "wb") as f:
                f.write(dec_bytes)

            # writing the file in database
            self.backup_db.query(f"INSERT INTO files (ID, FileName, FilePath, Verified) VALUES (?, ?, ?, ?)",
                                 [user_id_hex, request.file_name, file_path, 0])
            self.backup_db.query(f"UPDATE clients SET LastSeen = ? WHERE ID = ?",
                                 [str(datetime.now()), request.header.client_id.hex()])

            return self.send_checksum(conn, file_path, request.header.client_id, request.file_name)

        except Exception as e:
            print(f"Error while receiving file - {e}")
            return False

    def valid_crc(self, conn, data):
        """
        CODE = 1104

        the CRC we sent is valid!
        meaning we can change the status inside the database and remove from pending list

        respond with 2104

        :param conn: connection to write back to
        :param data: Registration Request header + payload in bytes (packed)
        :return: (bool) succeeded?
        """
        try:
            request = protocol.ValidCRCRequest()  # 1104
            request.unpack(data)
            file_name = request.file_name
            user_id = request.header.client_id.hex()

            print(f"CRC is VALID for file {file_name} by user {user_id}")

            # update db (and make sure it worked)
            db_flag_1 = self.backup_db.query(f"UPDATE clients SET LastSeen = ? WHERE ID = ?",
                                             [str(datetime.now()), user_id])
            db_flag_2 = self.backup_db.query(f"UPDATE files SET Verified = ? WHERE ID = ? AND fileName = ?",
                                             [1, user_id, file_name])
            if not db_flag_1 or not db_flag_2:
                return False

            # remove from pending list
            file_path = os.path.join(Path().resolve(), user_id, file_name)
            self.pending_crc.remove(file_path)

            # create and pack the response
            response = protocol.GenericResponse()  # 2104
            response.client_id = request.header.client_id
            return self.write(conn, response.pack())

        except Exception as e:
            print(f"Exception in valid CRC - {e}")
            return False

    def wrong_crc(self, conn, data):
        """
        CODE = 1105

        the CRC we sent is wrong.
        that means we should get a new file request from the user

        not responding with anything (unless 2107), but note that this should only happen 3 times
        I didn't add any checks for that from server side
        mainly because there's nothing stopping the client from sending more files or requests

        :param conn: connection to write back to
        :param data: Registration Request header + payload in bytes (packed)
        :return: (bool) succeeded?
        """
        try:
            request = protocol.WarningCRCRequest()  # 1105
            request.unpack(data)
            user_id = request.header.client_id.hex()
            file_name = request.file_name

            print(f"CRC is WRONG for file {file_name} by user {user_id}")

            # update last seen
            if not self.backup_db.query(f"UPDATE clients SET LastSeen = ? WHERE ID = ?",
                                        [str(datetime.now()), user_id]):
                return False
            return True
        except Exception as e:
            print(f"Exception in failed CRC - {e}")
            return False

    def failed_crc(self, conn, data):
        """
        CODE = 1106

        the CRC we sent is wrong, and we failed the 3 checks
        meaning we should remove the file from directory and pending list

        respond with 2104

        :param conn: connection to write back to
        :param data: Registration Request header + payload in bytes (packed)
        :return: (bool) succeeded?
        """
        try:
            request = protocol.ErrorCRCRequest()  # 1106
            request.unpack(data)

            file_name = request.file_name
            user_id = request.header.client_id.hex()

            print(f"CRC is WRONG. Checksum failed for file {file_name} by user {user_id}")

            db_flag_1 = self.backup_db.query(f"UPDATE clients SET LastSeen = ? WHERE ID = ?",
                                             [str(datetime.now()), user_id])
            query = self.backup_db.query_with_result(f"SELECT FilePath FROM files WHERE ID = ? AND fileName = ?",
                                                     [user_id, file_name])
            # no need to keep the file
            db_flag_2 = self.backup_db.query(f"DELETE FROM files WHERE ID = ? AND fileName = ?",
                                             [user_id, file_name])

            if not db_flag_1 or not db_flag_2 or not query:
                return False
            file_path = query[0][0]

            # TODO: validate that this is safe and we're not deleting anything important
            # it should be because it's ID based but it's always good to double check
            print(f"file path is {file_path}")
            os.remove(file_path)
            self.pending_crc.remove(file_path)

            # pack and send response
            response = protocol.GenericResponse()  # 2104
            response.client_id = request.header.client_id
            return self.write(conn, response.pack())

        except Exception as e:
            print(f"Exception in failed CRC - {e}")
            return False


""" 히스토그램 평탄화
 사용자로부터 R, G, B 중의 하나의 채널을 입력받고 입력받은 채널에 대한 히스토그램을 그리고
평탄화를 한 후에 그 영상을 출력하시오. (선택받은 채널 이외의 채널 값은 변화하지 않음)
"""

import cv2
import numpy as np
import matplotlib.pyplot as plt
mode = -1

rgb = input('R, G, B 입력:')

if rgb == 'r' or rgb == 'R':
    mode = 2
elif rgb == 'g' or rgb == 'G':
    mode = 1
elif rgb == 'b' or rgb == 'B':
    mode = 0

img = cv2.imread('D:\TestImage\image_Peppers512rgb.png')

img_to_his= np.copy(img)

img_G = img[:,:,mode]
#cv2.imshow('gray',img_G)

hsv = cv2.cvtColor(img, cv2.COLOR_BGR2HSV)

img_to_his[:,:,mode] = cv2.equalizeHist(img_G)
#histEqualizedR = np.histogram(img_to_his, 256, [0,255])
#color_eq = cv2.cvtColor(img_to_his, cv2.COLOR_HSV2BGR)

orgChannels = cv2.split(img)
channels = cv2.split(img_to_his)

colors = ("blue", "green", "red")
plt.figure()
plt.figure(figsize=(8,8))

plt.subplot(221)
plt.axis('off')
plt.title('original')
plt.imshow(img[:,:,[2,1,0]])

plt.subplot(222)
plt.axis('off')
plt.title('equalized color')
plt.imshow(img_to_his[:,:,[2,1,0]])

plt.subplot(223)
plt.title("Orig Histogram")
for (channel, color) in zip(orgChannels, colors):
    color_calchist = cv2.calcHist([channel], [0], None, [256], [0, 256])
    plt.plot(color_calchist, color = color)
    plt.xlim([0, 256])
plt.ylabel("Pixels")
plt.xlabel('pixel value')

plt.subplot(224)
plt.title("equalized Histogram")
for (channel, color) in zip(channels, colors):
    color_calchist = cv2.calcHist([channel], [0], None, [256], [0, 256])
    plt.plot(color_calchist, color = color)
    plt.xlim([0, 256])

plt.ylabel("Pixels")
plt.xlabel('pixel value')
plt.show()


# Class and Object
from time import sleep

class Employee():
    def __init__(self,eid,ename,esal):
        self.eid = eid
        self.ename = ename
        self.esal = esal

    def employeeStatus(self):
        print('Employee Id : ',self.eid)
        print('Employee Name : ',self.ename)
        print('Employee Salary : ',self.esal)
        print();print()

# 1st
e1 = Employee(101,'Micky',900000)
e1.employeeStatus()
sleep(3)
# 2nd way
Employee(102,'Rahul',35000).employeeStatus()


import numpy as np

from experiments import Experiments
from utilities import *

radius = [0.001, 0, 0] # [input, weight, bias]
outputIndex = 0
stop_conditions = [1e-6, 1, 3000, 4] #[minGap, maxiteration, maxBoxes, maxSame]
needBisect = False
experimentIndex = 10
dataIndex=0
c_vector=[1, 0]

layer_sizes = [2, 2, 2]
radius_list = np.arange(0, 0.01, 1e-4).tolist()
offset_list = np.arange(0, 0.02, 1e-2).tolist()
# radius_list = np.arange(0, 0.1, 0.02).tolist()
# offset_list = np.arange(0, 0.1, 0.03).tolist()
input = [1, 1]

ept = Experiments(radius, layer_sizes, outputIndex, stop_conditions, needBisect, experimentIndex, input, dataIndex, c_vector)
ept.loadSavedNetwork("WeightBias", str(8))
inputNearBoundary = ept.nearBoundary()

results = []
for offset in offset_list:
    operations = [1, 0, -1]
    tmp = []
    for i in range(3):
        for j in range(3):
            inputNew = [(inputNearBoundary[0]+operations[i]*offset), (inputNearBoundary[1]+operations[j]*offset)]
            ept.setInput(inputNew)
            tmpResult = ept.weightBiasExperiment(radius_list)
            tmp.append(tmpResult)
    results.append(tmp)

ept.saveNetwork(folderName="WeightBias", networkName=str(experimentIndex))

plotAll(results, radius_list, experimentIndex)


from unittest import mock

from django.contrib.auth.models import User
from django.test import TestCase
from django_dynamic_fixture import get
from djstripe import models as djstripe

from readthedocs.organizations.models import Organization

class TestSignals(TestCase):
    def setUp(self):
        email = "test@example.com"
        self.user = get(User)
        self.stripe_customer = get(
            djstripe.Customer,
            email=email,
            name="org",
        )
        self.organization = get(
            Organization,
            slug="org",
            name="org",
            owners=[self.user],
            email=email,
            stripe_customer=self.stripe_customer,
        )
        self.stripe_customer.metadata = self.organization.get_stripe_metadata()
        self.stripe_customer.description = self.organization.name
        self.stripe_customer.save()

    @mock.patch("readthedocs.subscriptions.signals.stripe.Customer")
    def test_update_organization_email(self, customer):
        new_email = "new@example.com"
        self.organization.email = new_email
        self.organization.save()
        customer.modify.assert_called_once_with(
            self.stripe_customer.id,
            email=new_email,
        )

    @mock.patch("readthedocs.subscriptions.signals.stripe.Customer")
    def test_update_organization_name(self, customer):
        new_name = "New organization"
        self.organization.name = new_name
        self.organization.save()
        customer.modify.assert_called_once_with(
            self.stripe_customer.id,
            description=new_name,
            name=self.organization.name,
        )

    @mock.patch("readthedocs.subscriptions.signals.stripe.Customer")
    def test_update_organization_slug(self, customer):
        new_slug = "new-org"
        self.organization.slug = new_slug
        self.organization.save()
        new_metadata = self.organization.get_stripe_metadata()
        customer.modify.assert_called_once_with(
            self.stripe_customer.id,
            metadata=new_metadata,
        )

    @mock.patch("readthedocs.subscriptions.signals.stripe.Customer")
    def test_save_organization_no_changes(self, customer):
        self.organization.save()
        customer.modify.assert_not_called()


# Максимальная длина монотонного фрагмента

N = int(input())
counterUp = 1
counterDown = 1
maxUp = 1
maxDown = 1
while N != 0:
    x = N
    N = int(input())
    if x >= N and N != 0:
        counterUp = 0
    elif x < N:
        counterUp += 1
        if counterUp > maxUp:
            maxUp = counterUp
    if x <= N and N != 0:
        counterDown = 0
    elif x > N:
        counterDown += 1
        if counterDown > maxDown:
            maxDown = counterDown
if maxUp >= maxDown:
    print(maxUp)
else:
    print(maxDown)


"""
完成数据集的加载
"""
from torch.utils.data import DataLoader,Dataset
import os
import config
import torch
from tokenlize import tokenlize
import pickle

class ImdbDataset(Dataset):
    def __init__(self,train,using):
        self.train_data_path = r"C:\Users\Alen\Desktop\gitcode\NLPSA\data\train"
        self.test_data_path = r"C:\Users\Alen\Desktop\gitcode\NLPSA\data\test"
        self.data_path = r"C:\Users\Alen\Desktop\gitcode\NLPSA\data\steam"
        if using:
            self.total_file_path = []                                                   # 所有评论文件的path
            file_name_list = os.listdir(self.data_path)
            file_path_list = [os.path.join(self.data_path, i) for i in file_name_list]
            self.total_file_path.extend(file_path_list)
        else:
            data_path = self.train_data_path if train else self.test_data_path           #把所有文件名放入列表
            temp_data_path = [os.path.join(data_path,"pos"),os.path.join(data_path,"neg")]
            self.total_file_path = []                                                     #所有评论文件的path
            for path in temp_data_path:
                file_name_list = os.listdir(path)
                file_path_list = [os.path.join(path,i)  for i in file_name_list]
                self.total_file_path.extend(file_path_list)
    def __getitem__(self, index):
        file_path=self.total_file_path[index]
        lable_str = file_path.split("\\")[-2]                                              #获取lable
        if lable_str == 'neg':
            lable = 0
        elif lable_str == 'pos':
            lable = 1
        else:
            lable=10000
        tokens = tokenlize(open(file_path,encoding='utf-8').read())                         #获取内容
        return lable,tokens
    def __len__(self):
        return len(self.total_file_path)

def my_collate(batch):
    ws = pickle.load(open('./model/ws.pkl', 'rb'))
    label ,content = list(zip(*batch))
    content = torch.LongTensor([ws.transform(i,max_len=config.max_len) for i in content])
    label = torch.LongTensor(label)
    return label,content

def get_dataloader(train,using,batch_size):
    imdb_dataset = ImdbDataset(train,using)
    data_loader = DataLoader(dataset=imdb_dataset,batch_size=batch_size,shuffle=True,collate_fn=my_collate)
    return data_loader


# Given a directory containing SQL queries and another directory containing the corresponding UDFs,
# this script will rewrite the UDFs to use batched execution and rewrite the queries to use the new UDFs.
# The rewritten queries and UDFs will be written to the output directory.
#
# Usage: python test.py <query_input_dir> <udf_input_dir> <output_dir>

from rewriter import Rewriter
import sys
import time

query_input_dir = sys.argv[1]
udf_input_dir = sys.argv[2]
output_dir = sys.argv[3]

udfs = [1, 5, 6, 7, 12, 13]
files = [f"sudf_{udf}.sql" for udf in udfs]

rewriting_times = []

def rewrite_query(query_file_name, udf_file_name, output_file_name):
    print("Rewriting", query_file_name)
    with open(query_file_name, "r") as query_file:
        query = query_file.read()
    with open(udf_file_name, "r") as udf_file:
        udf = udf_file.read()
    before_time = time.time()
    for i in range(100):
        r = Rewriter(query, udf, remove_laterals=True)
    after_time = time.time()
    rewriting_times.append(after_time - before_time)
    with open(output_file_name, "w") as out_file:
        out_file.write(r.new_udf())
        out_file.write("\n\n\n")
        out_file.write(r.new_query())

for file in files:
    rewrite_query(
        f"{query_input_dir}/{file}", f"{udf_input_dir}/{file}", f"{output_dir}/{file}"
    )

print("Rewriting times:", rewriting_times)


import requests

from bs4 import BeautifulSoup
from sqlalchemy.orm import Session
from sqlalchemy import create_engine

from urllib import parse
from urllib.parse import urlparse

from base import Base
from website import Website
from page import Page

class Crawler():
    def __init__(self, domain):
        self.domain = domain
        self.scanned_list = []

    def scan_page(self, url, session):
        print(url)
        self.scanned_list.append(url)
        request = requests.get(url)
        request.encoding = 'utf-8'
        html = request.text
        soup = BeautifulSoup(html)

        try:
            self.save_soup(session, soup, url)
        except Exception as e:
            print(e)

        links = soup.find_all('a')
        for link in links:
            href = link.get('href')
            next_page = self.href_to_url(url, href)
            if not self.is_outgoing(next_page) and next_page not in self.scanned_list:
                if self.is_valid(next_page):
                    self.scan_page(next_page, session)

    def scan_website(self, session):
        url = "http://" + self.domain
        self.scan_page(url, session)

    def href_to_url(self, url, href):
        return parse.urljoin(url, href)

    def is_outgoing(self, url):
        url = urlparse(url)
        if self.domain == url.netloc:
            return False
        if url.netloc[:4] == "www." and self.domain in url.netloc:
            return False
        return True

    def is_valid(self, url):
        if "#" in url:
            return False
        if ".pdf" in url:
            return False
        if ".jpg" in url or ".gif" in url:
            return False
        return True

    def save_soup(self, session, soup, page_url):
        try:
            soup_description = soup.find(
                attrs={"property": "og:description"}).get("content")
        except Exception:
            soup_description = ""

        session.add(Page(title=soup.title.string,
                         description=soup_description,
                         url=page_url,
                         website_id=self.domain))
        session.commit()

    def save_website(self, session):
        session.add(Website(url=self.domain,
                            html=True))

def main():
    engine = create_engine("sqlite:///searchengine.db")
    Base.metadata.create_all(engine)
    session = Session(bind=engine)
    crawler = Crawler("24chasa.bg")
    crawler.save_website(session)
    crawler.scan_website(session)

if __name__ == '__main__':
    main()


import sys

def main(in_string):

    surface_area = 0
    cube_list = []

    for cube in in_string.splitlines():
        split = cube.split(',')
        x = int(split[0])
        y = int(split[1])
        z = int(split[2])
        surface_area += 6
        for other_cube in cube_list:
            if manhat((x,y,z), other_cube) == 1:
                surface_area -= 2
        cube_list.append((x,y,z))

    print(surface_area)

def manhat(cube1, cube2):
    ret = 0
    for dim in range(len(cube1)):
        ret += abs(cube1[dim]-cube2[dim])

    return ret

if __name__ == "__main__":
    if len(sys.argv) < 2:
        print('No input found.')
    else:
        with open(sys.argv[1],'r') as f:
            in_string = f.read().strip()
            main(in_string)


import math
import sys

input = sys.stdin.readline

def get(lo: int, hi: int) -> int:
    lo += BASE - 1
    hi += BASE - 1

    v = _DEFAULT
    while lo < hi:
        if lo % 2 == 1:
            v = _GET(v, st[lo])
            lo += 1
        if hi % 2 == 0:
            v = _GET(v, st[hi])
            hi -= 1
        lo //= 2
        hi //= 2

    if lo == hi:
        v = _GET(v, st[lo])
    return v

def set(i: int, v: int):
    st[BASE + i - 1] = _SET(i, v)
    i = (i + BASE - 1) // 2
    while i > 0:
        st[i] = _GET(st[i * 2], st[i * 2 + 1])
        i //= 2

_DEFAULT = 0
_GET = lambda x, y: max(x, y)
_SET = lambda i, v: v
# _INPUT_TYPE = 'N'
_INPUT_TYPE = 'NM_TOGETHER'

if _INPUT_TYPE == 'NM_TOGETHER':
    n, m = map(int, input().split())
else:
    n = int(input())
a = [int(x) for x in input().split()]
a = [_SET(i, v) for i, v in enumerate(a)]
if _INPUT_TYPE != 'NM_TOGETHER':
    m = int(input())
BASE = 2 ** math.ceil(math.log(n, 2))

st = [_DEFAULT] * BASE * 2

st[BASE:BASE + n] = a
for i in range(BASE - 1, 0, -1):
    st[i] = _GET(st[i * 2], st[i * 2 + 1])

ans = []
for i in range(m, n - m + 2):
    ans.append(get(i - m + 1, i + m - 1))

print(' '.join(map(str, ans)))


import numpy as np
import math

def read_netlists(file_name):

    with open(f'{file_name}') as f:
        lines = f.read().splitlines()

    return lines

def get_elements(lines):

    elements = []

    for line in lines:
        line=line.split(' ')
        if line[0]!= '*':
            element = {'id':line[0],'nodeA':int(line[1]),'nodeB':int(line[2]),'value':line[3]}
            if line[0][0] == "I":
                element['type']= line[3]
                if element['type'] == 'sin' or element['type']== 'SIN':
                    del element['value']
                    element['amp'] = float(line[4])
                    element['freq'] = float(line[5])
                    element['phase']= float(line[6])
                else:
                    element['value'] = float(line[4])

            elif line[0][0] == "G":
                element['nodeC'] = int(line[3])
                element['nodeD'] = int(line[4])
                element['value'] = float(line[5])
            elif line[0][0] == "K":
                del element['value']
                element['L1'] = float(line[3])
                element['nodeC'] = int(line[4])
                element['nodeD'] = int(line[5])
                element['L2'] = float(line[6])
                element['M'] = float(line[7])
            else:
                element['value'] = float(element['value'])

            elements.append(element)

    return elements

def init_matrix(elements):

    biggest_node = 0
    for element in elements:
        if element['nodeA'] > biggest_node:
            biggest_node =  element['nodeA']
        if element['nodeB'] > biggest_node:
            biggest_node =  element['nodeB']

    Gn_matrix = []
    In_vector = []

    for line in range(0, biggest_node+1, 1):
        Gn_matrix.append([])
        In_vector.append(0)
        for column in range(0,biggest_node+1,1):
            Gn_matrix[line].append(0)

    return Gn_matrix, In_vector

def current_pattern(In_vector, element):

    if element['type'] == 'DC' or element['type'] == 'dc':
        In_vector[element['nodeA']] += -element['value']
        In_vector[element['nodeB']] += element['value']
    else:
        In_vector[element['nodeA']] += -element['amp']*math.e**(element['phase']*1j)
        In_vector[element['nodeB']] += element['amp']*math.e**(element['phase']*1j)

def dependent_current_pattern(Gn_matrix, element):

    Gn_matrix[element['nodeA']][element['nodeC']] += element['value']
    Gn_matrix[element['nodeB']][element['nodeC']] += -element['value']
    Gn_matrix[element['nodeA']][element['nodeD']] += -element['value']
    Gn_matrix[element['nodeB']][element['nodeD']] += element['value']

def resistor_pattern(Gn_matrix, element):

    Gn_matrix[element['nodeA']][element['nodeA']] += 1/(element['value'])
    Gn_matrix[element['nodeB']][element['nodeB']] += 1/(element['value'])
    Gn_matrix[element['nodeA']][element['nodeB']] += -1/(element['value'])
    Gn_matrix[element['nodeB']][element['nodeA']] += -1/(element['value'])

def inductor_pattern(Gn_matrix, element, freq):

    if freq == 0:
        print('frequencia zero')
    else:
        Gn_matrix[element['nodeA']][element['nodeA']] += 1/(1j*freq*element['value'])
        Gn_matrix[element['nodeB']][element['nodeB']] += 1/(1j*freq*element['value'])
        Gn_matrix[element['nodeA']][element['nodeB']] += -1/(1j*freq*element['value'])
        Gn_matrix[element['nodeB']][element['nodeA']] += -1/(1j*freq*element['value'])

def capacitor_pattern(Gn_matrix, element, freq):

    if freq == 0:
        print('frequencia zero')
    else:
        Gn_matrix[element['nodeA']][element['nodeA']] += 1j*freq*element['value']
        Gn_matrix[element['nodeB']][element['nodeB']] += 1j*freq*element['value']
        Gn_matrix[element['nodeA']][element['nodeB']] += -1j*freq*element['value']
        Gn_matrix[element['nodeB']][element['nodeA']] += -1j*freq*element['value']

def transformer_pattern(Gn_matrix, element, freq):

    denominator = element['L1']*element['L2'] - element['M']**2
    T11 = element['L2']/denominator
    T22 = element['L1']/denominator
    T12 = -element['M']/denominator

    Gn_matrix[element['nodeA']][element['nodeA']] += T11/(1j*freq)
    Gn_matrix[element['nodeA']][element['nodeB']] += -T11/(1j*freq)
    Gn_matrix[element['nodeA']][element['nodeC']] += T12/(1j*freq)
    Gn_matrix[element['nodeA']][element['nodeD']] += -T12/(1j*freq)

    Gn_matrix[element['nodeB']][element['nodeA']] += -T11/(1j*freq)
    Gn_matrix[element['nodeB']][element['nodeB']] += T11/(1j*freq)
    Gn_matrix[element['nodeB']][element['nodeC']] += -T12/(1j*freq)
    Gn_matrix[element['nodeB']][element['nodeD']] += T12/(1j*freq)

    Gn_matrix[element['nodeC']][element['nodeA']] += T12/(1j*freq)
    Gn_matrix[element['nodeC']][element['nodeB']] += -T12/(1j*freq)
    Gn_matrix[element['nodeC']][element['nodeC']] += T22/(1j*freq)
    Gn_matrix[element['nodeC']][element['nodeD']] += -T22/(1j*freq)

    Gn_matrix[element['nodeD']][element['nodeA']] += -T12/(1j*freq)
    Gn_matrix[element['nodeD']][element['nodeB']] += T12/(1j*freq)
    Gn_matrix[element['nodeD']][element['nodeC']] += -T22/(1j*freq)
    Gn_matrix[element['nodeD']][element['nodeD']] += T22/(1j*freq)

def get_freq(elements):

    freq = 0

    for element in elements:
        if 'freq' in element.keys():
            freq = element['freq']
            break
    return freq

def apply_pattern(Gn_matrix, In_vector, elements, freq):

    for element in elements:
        if element['id'][0] == 'I':
            current_pattern(In_vector, element)
        elif element['id'][0] == 'G':
            dependent_current_pattern(Gn_matrix, element)
        elif element['id'][0]=='R':
            resistor_pattern(Gn_matrix, element)
        elif element['id'][0]=='L':
            inductor_pattern(Gn_matrix, element, freq)
        elif element['id'][0]=='C':
            capacitor_pattern(Gn_matrix, element, freq)
        elif element['id'][0] =='K':
            transformer_pattern(Gn_matrix, element, freq)

def remove_ground(Gn_matrix, In_vector):

    Gn_matrix.pop(0)
    In_vector.pop(0)

    for index in range(0,len(Gn_matrix),1):
        Gn_matrix[index].pop(0)

def solve_node(Gn_matrix, In_vector):

     Y = np.array(Gn_matrix)
     I = np.array(In_vector)
     e = np.linalg.solve(Y,I)

     return e


import numpy as np
from scipy.sparse import csc_matrix
from tensiga.iga.ktsinsop import ktsinsop
from tensiga.iga.auxkv import auxkv
from tensiga.iga.twoscaleop import twoscaleop
from tensiga.iga.delevop import delevop
from tensiga.iga.bfunsop import bfunsop
from tensiga.iga.dbfunsop import dbfunsop
from tensiga.iga.gpnts import gpnts
from tensiga.utils.mat3_dot_csc import mat3_dot_csc
from tensiga.utils.mat_dot_sp import mat_dot_sp

class Bspline:
    """A data container for a Bspline geometric object and an interface to
    applicable geometric modules.

    Attributes:
        dim (int) : dimension of the Bspline object
        codim (int) : dimension of the embedding space
        kv (list(np.array)) : list of knot vectors in each parametric direction
        deg (list(int)) : list of degrees for each parametric direction
        ctrlpts (list(np.array)) : list of control point coordinates for each
          coordinate in the embedding space
        nbfuns (np.array(int)) : number of basis functions in each direction
        nkts (np.array(int)) : knot vector length in each direction
    """

    def __init__(self, dim, codim, kv, deg, ctrlpts):
        self.dim = dim
        self.codim = codim
        self.deg = deg
        self.kv = [ np.array(kv_i, copy=True) for kv_i in kv  ]
        self.nkts = [ kv_i.size for kv_i in self.kv ]
        self.nbfuns = np.array(self.nkts) - np.array(self.deg) - 1
        self.ctrlpts = [ np.array(ctrlpts_i, copy=True) for ctrlpts_i in ctrlpts  ]

        self.__assert_kv_sanity()
        self.__assert_deg_sanity()
        self.__assert_ctrlpts_sanity()

        self.physdim = codim

    def __assert_kv_sanity(self):
        try:
            assert(len(self.kv) == self.dim)
        except AssertionError:
            print('Bspline: number of knot vectors does not match the Bspline dimension')
            exit()

    def __assert_deg_sanity(self):
        try:
            assert(len(self.deg) == self.dim)
        except AssertionError:
            print('Bspline: number of degrees does not match the Bspline dimension')
            exit()

    def __assert_ctrlpts_sanity(self):
        try:
            assert(len(self.ctrlpts) == self.codim)
        except AssertionError:
            print('Bspline: number of control point coordinates does not match the embedding space dimension')
            exit()

        try:
            self.nkts = [ kv_i.size for kv_i in self.kv ]
            self.nbfuns = np.array(self.nkts) - np.array(self.deg) - 1
            for cps in self.ctrlpts:
                assert(list(cps.shape) == self.nbfuns.tolist())
        except AssertionError:
            print('Bspline: provided control points', cps,
              'do not suite the corresponding knot vector!')
            exit()

    def _mat_dot_sp(self, A, B, axis=0):
        return mat_dot_sp(A, B, axis)

    def _mat_dot_multi_sp(self, A, B):
        C = mat_dot_sp(A, B[0], 0)
        for k in range(1, len(B)):
            C = mat_dot_sp(C, B[k], k)
        return C

    def nelem(self, k=None):
        """Computes the number of elements. If ``k = None`` compute total
        number of elements. For ``k=1,...,dim`` computes the univariate elements
        in the direction ``k``.

        Parameters:
            k (int) : parametric direction

        Returns:
            int : number of elements
        """
        if k == None:
            return np.prod([ np.unique(kv).size-1 for kv in self.kv ])
        else:
            return np.unique(self.kv[k]).size-1

    def elsz(self):
        """Computes the element sizes in the physical space. Element size is
        defined as the length of the element diagonal.

        Returns:
            array(float) : element sizes
        """
        unique_kv = [ np.unique(kv) for kv in self.kv ]
        phy_knot = [ self.eval(unique_kv, k) for k in range(self.dim)  ]
        mesh_shape = phy_knot[0].shape

        ##      + -- +  x'                                   ##
        ##     /    .|                                       ##
        ##    + -- + |                                       ##
        ##    |    | +                                       ##
        ##    |    |.                                        ##
        ##    + -- +         |x - x'| = h                    ##
        ##  x                                                ##

        nelem = self.nelem()
        h = [None] * nelem

        for el in range(nelem):
            x_indices = np.unravel_index(el, np.array(mesh_shape)-1)
            xp_indices = tuple([idx+1 for idx in x_indices])

            # x on diagonal
            x = np.array([ phy_knot[k][x_indices] for k in range(self.dim) ])

            # x' on diagonal
            xp = np.array([ phy_knot[k][xp_indices] for k in range(self.dim) ])

            h[el] = np.linalg.norm(x-xp)

        return h

    def bfunsop(self, u, k):
        (vals, (rows, cols)), shape = bfunsop(u, self.deg[k], self.kv[k])
        return csc_matrix((vals, (rows,cols)), shape=shape)

    def dbfunsop(self, u, n, k):
        (vals, (rows, cols)), shape = dbfunsop(n, u, self.deg[k], self.kv[k])
        return csc_matrix((vals, (rows, cols)), shape=shape)

    def bfunsops(self, u):
        return [ self.bfunsop(u[k], k) for k in range(self.dim) ]

    def dbfunsops(self, u, n):
        return [ self.dbfunsop(u[k], n, k) for k in range(self.dim) ]

    def eval(self, u, k=0):
        """ Evaluates the Bspline at ``u`` in the physical space in direction ``k``.

        Parameters:
            u (List(np.array(float))) : list of evaluation points in each
                parametric direction

        Returns:
            np.array(float) : coordinates at each grid point in physical
            direction ``k``.
        """
        return self.evalwrt(u, self.ctrlpts[k])

    def evalwrt(self, u, P):
        """ Evaluates the Bspline at ``u`` with respect to a set of control points ``P``.

        Parameters:
            u (List(np.array(float))) : list of evaluation points in each
                parametric direction
            P (np.array(float)) : control points
        Returns:
            np.array(float) : coordinates at each grid point in physical
            direction ``k``.
        """
        if not isinstance(u, list):
            u = [u]

        B = self.bfunsops(u)
        x = self._mat_dot_multi_sp(P, B)

        return x

    def deval(self, n, k, u):
        raise NotImplementedError('Bspline: arbitrary derivatives\
          not implemented yet!')

    def devalwrt(self, n, u, P):
        raise NotImplementedError('Bspline: arbitrary derivatives\
          not implemented yet!')

    def greville_knt(self, k):
        return gpnts(self.deg[k], self.kv[k])

    def greville_knts(self):
        return [ self.greville_knt(k) for k in range(self.dim) ]

    def href(self, u, k=0):
        if k >= self.dim:
            raise IndexError('Bspline: parametric dir for refinement exceeded!')

        A, U = ktsinsop(self.nbfuns[k], u, self.deg[k], self.kv[k])

        for d in range(self.codim):
            self.ctrlpts[d] = self._mat_dot_sp(self.ctrlpts[d], A, k)

        self.kv[k] = U
        self.nkts[k] = self.kv[k].size
        self.nbfuns[k] = self.nkts[k] - self.deg[k] - 1

    def pref(self, dp, k=0):
        U = self.kv[k]
        p = self.deg[k]

        Z, M = auxkv(U)

        V = np.repeat(Z, M+dp)
        q = p + dp

        A = twoscaleop(p, U, q, V)

        for d in range(self.codim):
            self.ctrlpts[d] = self._mat_dot_sp(self.ctrlpts[d], A, k)

        self.deg[k] = q
        self.kv[k] = V
        self.nkts[k] = self.kv[k].size
        self.nbfuns[k] = self.nkts[k] - self.deg[k] - 1

    def delev(self, dp, k=0):
        U = self.kv[k]
        p = self.deg[k]

        Z, M = auxkv(U)

        M[[0,-1]] += dp
        V = np.repeat(Z, M)
        q = p + dp

        A = delevop(p, U, q, V)

        for d in range(self.codim):
            self.ctrlpts[d] = self._mat_dot_sp(self.ctrlpts[d], A, k)

        self.deg[k] = q
        self.kv[k] = V
        self.nkts[k] = self.kv[k].size
        self.nbfuns[k] = self.nkts[k] - self.deg[k] - 1

    def jacobian(self, u):
        if not isinstance(u, list):
            u = [u]

        if not self.dim == self.physdim:
            raise NotImplementedError('Bspline: non-square Jacobian!')

        B = self.bfunsops(u)
        dB = self.dbfunsops(u, 1)

        if self.dim == 1:
            J = self.ctrlpts[0] @ dB[0]

        elif self.dim == 2:
            dxdu = self._mat_dot_multi_sp(self.ctrlpts[0],[dB[0],  B[1]])
            dxdv = self._mat_dot_multi_sp(self.ctrlpts[0],[ B[0], dB[1]])

            dydu = self._mat_dot_multi_sp(self.ctrlpts[1],[dB[0],  B[1]])
            dydv = self._mat_dot_multi_sp(self.ctrlpts[1],[ B[0], dB[1]])

            # ravel s.t. a_ij -> a_I
            dxdu = dxdu.reshape(-1)
            dxdv = dxdv.reshape(-1)
            dydu = dydu.reshape(-1)
            dydv = dydv.reshape(-1)

            # compute the determinant of the jacobian
            J = (dxdu * dydv) - (dxdv * dydu)

            # reshape J_{I} back to J_ijk
            J = J.reshape(u[0].shape + u[1].shape)

        elif self.dim == 3:
            dxdu = self._mat_dot_multi_sp(self.ctrlpts[0],[dB[0],  B[1],  B[2]])
            dxdv = self._mat_dot_multi_sp(self.ctrlpts[0],[ B[0], dB[1],  B[2]])
            dxdw = self._mat_dot_multi_sp(self.ctrlpts[0],[ B[0],  B[1], dB[2]])

            dydu = self._mat_dot_multi_sp(self.ctrlpts[1],[ dB[0],  B[1],  B[2]])
            dydv = self._mat_dot_multi_sp(self.ctrlpts[1],[  B[0], dB[1],  B[2]])
            dydw = self._mat_dot_multi_sp(self.ctrlpts[1],[  B[0],  B[1], dB[2]])

            dzdu = self._mat_dot_multi_sp(self.ctrlpts[2],[ dB[0],  B[1],  B[2]])
            dzdv = self._mat_dot_multi_sp(self.ctrlpts[2],[  B[0], dB[1],  B[2]])
            dzdw = self._mat_dot_multi_sp(self.ctrlpts[2],[  B[0],  B[1], dB[2]])

            # ravel s.t. a_ij -> a_I
            dxdu = dxdu.reshape(-1)
            dxdv = dxdv.reshape(-1)
            dxdw = dxdw.reshape(-1)

            dydu = dydu.reshape(-1)
            dydv = dydv.reshape(-1)
            dydw = dydw.reshape(-1)

            dzdu = dzdu.reshape(-1)
            dzdv = dzdv.reshape(-1)
            dzdw = dzdw.reshape(-1)

            # compute the determinant of the jacobian
            J = (dxdu * dydv * dzdw) +\
                (dxdv * dydw * dzdu) +\
                (dxdw * dydu * dzdv) -\
                (dxdw * dydv * dzdu) -\
                (dxdv * dydu * dzdw) -\
                (dxdu * dydw * dzdv)

            # reshape J_{I} back to J_ijk
            J = J.reshape(u[0].shape + u[1].shape + u[2].shape)
        else:
            pass # throw an appropriate exception

        return J

if __name__ == '__main__':
    from matplotlib import colors as c
    import matplotlib.patches as patches
    import matplotlib.pyplot as plt
    from tensiga.quadrature.glnint import glnint

    dim = 2;
    codim = 2;
    deg = [2, 1]

    kv = [ np.array([0., 0., 0., 1., 1., 1.]),
           np.array([0., 0., 1., 1.])]

    ctrlpts = [ np.array([[1.0, 0.6],
                          [1.0, 0.6],
                          [0.0, 0.0]]), # x

                np.array([[0.0, 0.0],
                          [1.0, 0.6],
                          [1.0, 0.6]])] # z

    # init primitive spline object
    spline = Bspline(dim, codim, kv, deg, ctrlpts)

    # refine the spline object
    u = np.linspace(0, 1, 20)[1:-1]
    v = np.linspace(0, 1, 6)[1:-1]
    spline.href(u, 0)
    spline.href(v, 1)

    # get the integration rule
    quadrature = glnint(spline.kv, spline.deg+np.array([1,1]))
    xip = spline.eval(quadrature.ip, 0)
    yip = spline.eval(quadrature.ip, 1)

    # compute jacobian
    J = spline.jacobian(quadrature.ip)

    # compute geometry
    ep = spline.kv
    x = spline.eval(ep, 0)
    y = spline.eval(ep, 1)

    # plot
    plt.pcolor(x, y, np.sqrt(x**2 + y**2), edgecolor='black')
    plt.plot(xip, yip, 'ko', markersize=1)
    plt.show()


"""
Program to build bioactivity prediction tool streamlit app
"""

# importing necessary libraries
import streamlit as st
import pandas as pd
from PIL import Image
from padelpy import padeldescriptor
import glob
import base64
import pickle

# molecular descriptor calculator
def desc_calc():
    """
    function to initiate PaDEL software via padelpy library to calculate molecular descriptors
    :return: calculated descriptors of input molecules
    """
    # list and sort fingerprint XML files to initiate padelpy/padel software
    xml_files = glob.glob('*.xml')
    xml_files.sort()

    # create list of "keys" for all padel fingerprint types to use for dictionary
    fp_list = ['AtomPairs2DCount',
               'AtomPairs2D',
               'EState',
               'CDKextended',
               'CDK',
               'CDKgraphonly',
               'KlekotaRothCount',
               'KlekotaRoth',
               'MACCS',
               'PubChem',
               'SubstructureCount',
               'Substructure']

    # create dictionary of keys and corresponding values (xml files)
    fp = dict(zip(fp_list, xml_files))

    # initiate padelpy and set fingerprint to "PubChem" type to calculate PubChem fingerprints
    fingerprint = 'PubChem'
    fingerprint_output_file = ''.join([fingerprint,'.csv'])     # output: Pubchem.csv
    fingerprint_descriptortypes = fp[fingerprint]

    padeldescriptor(mol_dir='molecule.smi',
                    d_file=fingerprint_output_file,  # 'PubChem.csv'
                    descriptortypes=fingerprint_descriptortypes,     # descriptortypes='PubChem.xml'
                    detectaromaticity=True,
                    standardizenitro=True,
                    standardizetautomers=True,
                    threads=2,
                    removesalt=True,
                    log=True,
                    fingerprints=True)

# file download
def filedownload(df):
    """
    function to enable users to download prediction results from webapp
    :param df:dataframe of predicted pIC50 values of input molecules
    :return: csv file
    """
    csv = df.to_csv(index=False)
    b64 = base64.b64encode(csv.encode()).decode()  # strings <-> bytes conversions
    href = f'Download Predictions'
    return href

# model building
def build_model(input_data):
    """
    function to read in Random Forest model built and saved as a pickle object. Function then uses model to predict
    pIC50 values from the molecular descriptors calculated from the input molecules.
    :param input_data: dataframe containing molecular descriptors
    :return:
    """
    # reads in saved Random Forest model
    load_model = pickle.load(open('model.pkl', 'rb'))
    # apply model to make predictions
    prediction = load_model.predict(input_data)
    st.header('**Prediction output**')
    prediction_output = pd.Series(prediction, name='pIC50')
    molecule_name = pd.Series(load_data[1], name='molecule_name')
    df = pd.concat([molecule_name, prediction_output], axis=1)
    st.write(df)
    st.markdown(filedownload(df), unsafe_allow_html=True)

# logo image for app
image = Image.open('logo.png')
st.image(image, use_column_width=True)

# formatting streamlit app
# page title
st.markdown("""
# Bioactivity Prediction App for target protein, Hepatocyte Growth Factor Receptor (HGFR)

Abnormal expression of hepatocyte growth factor receptor (HGFR) has been associated with tumors with high cell proliferation rate,
cell dissociation, tumor aggressiveness, and invasiveness. Literature has supported it as being a promising target in cancer therapy, however the protein's
characteristic of therapeutic resistance is still a barrier for developing effective drugs that can inhibit it. Discovery of novel compounds/molecules with
promising bioactivity with HGFR is needed.

This app allows users to determine if a molecule of interest has the potential to be a drug candidate by predicting the
bioactivity towards inhibiting the HGFR. The app accepts .txt files containing the canonical simplified molecular-input line-entry system (SMILES)
notation of the molecule(s) of interest and respective ChEMBLID. Results will return predicted pIC50 value(s) of the molecule(s)
of interest.

A note on predicted pIC50 values: the prediction model was trained with consideration of compounds with pIC50 values >6 as **active** while values <5 as **inactive**.

---
**Acknowledgement**
- App built in 'python' + 'streamlit' by **Sara Then** with project inspiration and guidance from [Chanin Nantasenamat/Data Professor](http://youtube.com/dataprofessor)'s Bioinformatics series.
- Descriptor calculated using [PaDEL-Descriptor](http://www.yapcwsoft.com/dd/padeldescriptor/)
- Details of the project and code are available on the github repo (https://github.com/sara-then/HGF-drugdiscovery-project)
---
""")

# sidebar
with st.sidebar.header('Upload your molecule .txt file'):
    uploaded_file = st.sidebar.file_uploader("Upload your input file", type=['txt'])
    st.sidebar.markdown("""
[Example input file](https://raw.githubusercontent.com/dataprofessor/bioactivity-prediction-app/main/example_acetylcholinesterase.txt)
""")

if st.sidebar.button('Predict'):
    load_data = pd.read_table(uploaded_file, sep=' ', header=None)
    load_data.to_csv('molecule.smi', sep='\t', header=False, index=False)

    st.header('**Original input data**')
    st.write(load_data)

    with st.spinner("Calculating descriptors..."):
        desc_calc()

    # Read in calculated descriptors and display the dataframe
    st.header('**Calculated molecular descriptors**')
    desc = pd.read_csv('PubChem.csv')
    st.write(desc)
    st.write(desc.shape)

    # Read descriptor list used in previously built model
    st.header('**Subset of descriptors from built model**')
    Xlist = list(pd.read_csv('descriptor_list.csv').columns)
    desc_subset = desc[Xlist]
    st.write(desc_subset)
    st.write(desc_subset.shape)

    # Apply trained model to make prediction on query compounds
    build_model(desc_subset)
else:
    st.info('Upload input data in the sidebar to start!')


import files

# filename = 'data/train_res.txt'
# with open(filename, 'a') as file_obj:

raw_data = files.readpkl('data/train_stat.pkl')
all_person = 19835
all_item = 624961
len_list = []
sim_list = []

# sim_list = [[0 for i in range(0, all_person)] for i in range(0, all_person)]

def initial(raw_data):
    init_list = []
    for i in raw_data:
        init_list.append(i[2])
    return init_list

def pre_process(person_list):
    for i in person_list:
        sum = 0
        for value in i.values():
            sum += value
        average = sum / all_item
        sum = 0
        for key in i.keys():
            i[key] = i[key] - average
            sum += i[key] ** 2
        sum = sum ** 0.5
        # if sum <= 0:
        #     print(sum),
        #     print(i),
        len_list.append(sum)
    return person_list

def process(person_list):
    file_count = 0
    for tmp_i in range(0, all_person):
        for tmp_j in range(0, all_person):
            flag = len(person_list[tmp_i]) <= len(person_list[tmp_j])
            cos_sum = 0
            sim = 0
            if len_list[tmp_i] != 0 and len_list[tmp_j] != 0:
                if flag:
                    for key in person_list[tmp_i].keys():
                        if key in person_list[tmp_j].keys():
                            cos_sum += person_list[tmp_i][key] * person_list[tmp_j][key]
                else:
                    for key in person_list[tmp_j].keys():
                        if key in person_list[tmp_i].keys():
                            cos_sum += person_list[tmp_i][key] * person_list[tmp_j][key]
                sim = cos_sum / (len_list[tmp_i] * len_list[tmp_j])
            sim_list.append(sim)
        if tmp_i % 100 == 99:
            files.writepkl('data/train_res%d.pkl' % file_count, sim_list)
            file_count += 1
            sim_list.clear()
            print((tmp_i, tmp_j, sim)),
    files.writepkl('data/train_res%d.pkl' % file_count, sim_list)
    print("all files finishi")

if __name__ == "__main__":
    init_list = initial(raw_data)
    # print(init_list[0]),
    res_list = pre_process(init_list)
    # print(res_list[0]),
    # print(len_list),
    process(res_list)
    print("Finish process!")


#!/usr/bin/env python
# encoding: utf-8
"""
@author: HuRuiFeng
@file: 122_minimal-delivery-delay.py
@time: 2023/7/17 20:37
@project: huawei-od-python
@desc: 122 最小传递延时
"""

def backtracking(times, start, end, paths, result):
    if start == end:
        if len(paths) == 1:
            return result.append(paths[0][2])
        elif len(paths) > 1:
            length = 0
            for node in paths:
                length += node[2]
            return result.append(length)

    for node in times:
        if node not in paths:
            if node[0] == start:
                paths.append(node)
                backtracking(times, node[1], end, paths, result)
                paths.remove(node)

def solve_method(times, start, end):
    paths = []
    result = []
    backtracking(times, start, end, paths, result)

    return -1 if len(result) == 0 else min(result)

if __name__ == '__main__':
    times = [[1, 2, 11],
             [2, 3, 13],
             [1, 3, 50]]
    assert solve_method(times, 1, 3) == 24

    times = [[1, 2, 11],
             [2, 3, 13],
             [1, 3, 50],
             [3, 4, 55],
             [4, 5, 35],
             [2, 4, 15],
             [3, 5, 40]]
    assert solve_method(times, 1, 5) == 61


import pandas as pd
import numpy as np
from ftx.clients.rest_client import FtxAuth, FtxClient
from ftx.data._wranglers import add_trades, preprocess_fills

# Account summary for all traded futures
def get_futures_summary(futures_fills: pd.DataFrame, funding: pd.DataFrame, open_positions: pd.DataFrame) -> pd.DataFrame:

    active_markets = futures_fills['market'].unique()
    futures_summary = pd.DataFrame(columns=['Volume', 'TakerVolume', 'MakerVolume', 'SellVolume', 'BuyVolume', 'Fees', 'Funding'])

    for market in active_markets:
        active_market_df = futures_fills[futures_fills['market'] == market]
        # Subtract any open shorts from the total sold value
        open_short_value = (lambda x: np.float(0) if x.empty else np.float(x))(np.minimum(open_positions[open_positions['future'] == market]['cost'], 0))
        # Subtract any open longs from the total bought value
        open_long_value = (lambda x: np.float(0) if x.empty else np.float(x))(np.maximum(open_positions[open_positions['future'] == market]['cost'], 0))

        market_summary = pd.Series(
            {
                "Volume": active_market_df['volume'].sum().round(2),
                "TakerVolume": active_market_df[active_market_df['liquidity'] == 'taker']['volume'].sum().round(2),
                "MakerVolume": active_market_df[active_market_df['liquidity'] == 'maker']['volume'].sum().round(2),
                "SellVolume": active_market_df[active_market_df['side'] == 'sell']['volume'].sum().round(2) + open_short_value,
                "BuyVolume": active_market_df[active_market_df['side'] == 'buy']['volume'].sum().round(2) - open_long_value,
                "Fees": active_market_df['fee'].sum().round(4),
                "Funding": funding[funding['future'] == market]['payment'].sum().round(4)
            },
            name=market)

        futures_summary = futures_summary.append(market_summary)

    cummulative = pd.Series(
        {
            "Volume": futures_summary['Volume'].sum(),
            "TakerVolume": futures_summary['TakerVolume'].sum(),
            "MakerVolume": futures_summary['MakerVolume'].sum(),
            "SellVolume": futures_summary['SellVolume'].sum(),
            "BuyVolume": futures_summary['BuyVolume'].sum(),
            "Fees": futures_summary['Fees'].sum(),
            "Funding": futures_summary['Funding'].sum()
        },
        name="TOTAL")
    futures_summary = futures_summary.append(cummulative)
    futures_summary['RawPNL'] = futures_summary['SellVolume'] - futures_summary['BuyVolume']
    futures_summary['RPNL'] = futures_summary['RawPNL'] - futures_summary['Fees'] - futures_summary['Funding']

    return futures_summary

# Account summary for all traded spot markets
def get_spot_summary(spot_fills: pd.DataFrame) -> pd.DataFrame:

    active_markets = spot_fills['market'].unique()
    spot_summary = pd.DataFrame(columns=[
        'Volume',
        'TakerVolume',
        'MakerVolume',
        'SellVolume',
        'BuyVolume',
        'Fees',
    ])

    for market in active_markets:
        active_market_df = spot_fills[spot_fills['market'] == market]
        fee_currency = market.split('/')[1]
        market_summary = pd.Series(
            {
                "Volume": active_market_df['volume'].sum().round(2),
                "TakerVolume": active_market_df[active_market_df['liquidity'] == 'taker']['volume'].sum().round(2),
                "MakerVolume": active_market_df[active_market_df['liquidity'] == 'maker']['volume'].sum().round(2),
                "SellVolume": active_market_df[active_market_df['side'] == 'sell']['volume'].sum().round(2),
                "BuyVolume": active_market_df[active_market_df['side'] == 'buy']['volume'].sum().round(2),
                # Use the quote currency as the fee currency ie ETH/BTC fees are denominated in BTC
                # Convert fees from fee currency to quote currency where needed
                "Fees": active_market_df.apply(lambda row: row.fee * row.price if row.feeCurrency != fee_currency else row.fee, axis=1).sum().round(4),
                "FeeCurrency": fee_currency,
            },
            name=market)

        spot_summary = spot_summary.append(market_summary)
        active_market_df.apply(lambda row: row.fee * row.price if row.feeCurrency != fee_currency else row.fee, axis=1)

    return spot_summary

# Trades that are not closed will not be shown
def get_futures_trades_by_market(fills_by_market: pd.DataFrame, funding: pd.DataFrame) -> pd.DataFrame:
    fills_by_market = {market: add_trades(df) for market, df in fills_by_market.items()}
    trades_by_market = {}
    for future, df in fills_by_market.items():

        volume = df.groupby('trade_nr')['volume'].sum()
        fees = df.groupby('trade_nr')['fee'].sum()
        value = df.groupby(['trade_nr', 'side'])['volume'].sum()
        raw_pnl = value.groupby('trade_nr').diff().droplevel('side').dropna()
        raw_pnl.name = 'raw_pnl'
        start_time = df.groupby('trade_nr')['time'].min()
        start_time.name = 'start'
        end_time = df.groupby('trade_nr')['time'].max()
        end_time.name = 'end'
        duration = end_time - start_time
        duration.name = 'duration'
        executions = df.groupby('trade_nr')['time'].count()
        executions.name = 'executions'

        f = funding[funding['future'] == df['market'].iloc[0]].copy()
        f = f.set_index('time').sort_index()

        trades = pd.concat([
            raw_pnl,
            fees,
            volume,
            executions,
            start_time,
            end_time,
            duration,
        ], axis=1)
        trades['funding'] = trades.apply(lambda x: f['payment'][x.start:x.end].sum(), axis=1)
        trades['rpnl'] = trades['raw_pnl'] - trades['fee'] - trades['funding']
        trades = trades[[
            'raw_pnl',
            'fee',
            'funding',
            'rpnl',
            'executions',
            'volume',
            'start',
            'end',
            'duration',
        ]]

        # Delete last trade if position still open
        if df.iloc[-1]['delta'] != 0:
            trades.drop(df.iloc[-1]['trade_nr'], inplace=True)

        trades_by_market[future] = trades

    return trades_by_market


'''
number = input('Enter a whole number:')
number = int(number)
print(number + 10)

number = int(input('Enter a whole number:'))
print(number + 10)
'''

# ask user for temp in Fahrenheit
fahrenheit = float(input('Enter temp in Fahrenheit:'))

# Convert temperature from Fahrenheit to Celsius
celcius = (fahrenheit - 32) * (5/9)

# Display celcius temperature to the nearest tenth
print('Celcius Temperature: {:.1f}'.format(celcius))


import json

json_fn = "../mentoriasudea2022/data/marvel.json"   #   Ruta al archivo json con los datos.

clave_gen = "Cinemateca Marvel"   #   Clave principal de búsqueda por cinemateca
clave_pel = 'Iron Man'            #   Clave de búsqueda de película

def f_trazo(texto):
    print(f"{'<'*int(len(texto)/2)} {'>'*int(len(texto)/2)}")
    print(f"{texto}")
    print(f"{'<'*int(len(texto)/2)} {'>'*int(len(texto)/2)}")

with open(json_fn) as marvel:

    data=json.load(marvel)
    texto = "01. Datos cargados de json"
    f_trazo("BEGIN " + texto)
    print(f"{type(data)} >> {data[clave_gen][clave_pel]}")
    f_trazo("END " + texto)

texto = " 02. Datos de peliculas"
f_trazo("BEGIN " + texto)
#for peli in data[clave_gen]:
for peli in data:

    print(f" 02. Datos {type(peli)} de peliculas {peli}")

f_trazo("END " + texto)

texto = " 03. Datos de peli {type(peli)} contienen {peli}"
f_trazo("BEGIN " + texto)

for peli in data[clave_gen]:
  print(f" 03. Datos de peli {type(peli)} >> {peli}")

f_trazo("END " + texto)

datos_peli = data[clave_gen][clave_pel]
texto=" 04. Detalle de {clave_gen} : {clave_pel} {type(datos_peli)}"
f_trazo("BEGIN " + texto)
print(f" 04. Detalle de {clave_gen} : {clave_pel} {type(datos_peli)}")
f_trazo("END " + texto)

texto=" 05. {det} : {datos_peli[det]} es  {type(det)}"
f_trazo("BEGIN " + texto)

for det in datos_peli:

    print(f" 05. {det} : {datos_peli[det]} es {type(det)}")
f_trazo("END " + texto)

texto=" 06. Otro detalle {type(datos_peli)} = {datos_peli}"
f_trazo("BEGIN " + texto)
print(f" 06. Otro detalle {type(datos_peli)} = {datos_peli}")
f_trazo("END " + texto)

texto=" 07. Claves de "
f_trazo("BEGIN " + texto )

for det_peli in data[clave_gen][clave_pel]:
    print(f" 07. {det_peli} : {data[clave_gen][clave_pel][det_peli]}")
f_trazo("END " + texto)

with open(json_fn) as marvel:

    data=json.load(marvel)
    for cin in data:
      print("Cin " + cin)
      for pel in data[cin]:
        texto=cin + " ****" + " Pelicula: " + pel
        f_trazo(texto)
        for det in data[cin][pel]:
            print(f' >>>> {det} = {data[cin][pel][det]}')
        f_trazo( " Fin de >>> " + texto)
        f_trazo(texto="")


#import mimetypes
#from os import *
import re

"""ruta2 = "/TRABAJO/_Programación/"

print(listdir(ruta2))

with open("/TRABAJO/_Programación/prueba2.txt", "w") as f:

    f.write('prueba')
    f.close()
"""

"""directorio = "/Users/noave/Downloads"
listArchivos = listdir(directorio)
for fichero in listArchivos:
    if mimetypes.guess_type(fichero)[0] == "image/jpeg":
        print(fichero)"""

"""for fichero in listArchivos:
    if path.isfile(path.join(directorio, fichero)):
        print(fichero)"""

leido='directorio = "/Users/noave/Downloads"'
patron=re.compile(r'"(\S+)"')

print(re.findall(patron, leido))


#!/usr/bin/python3
#--coding: utf-8; mode:python--

from curses.ascii import isdigit
from json import *
from os import stat
from classes.Bottle import *
from functionalities.Import import *
from classes.State import *
from classes.Problem import *
from functionalities.Export import*
from classes.Frontier_Deque import*
from classes.Frontier_Heapq import*
from classes.Frontier_List import*
from classes.State_space import *
import resource
import time

def main():
    menu_strategies()

def print_Menu():
    print("Welcome to our water sort agent solver\nSelect the option you want to:")
    print("0. BREADTH ALGORITHM")
    print("1. DEPTH ALGORITHM")
    print("2. UNIFORM COST ALGORITHM")
    print("3. A* ALGORITHM")
    print("4. GREEDY  ALGORITHM")
    print("5. Exit")
    print("----------------------------------------------------------------------\n")

def print_menu_funcionalities():
    print("0. Import json")
    print("1. Test frontier")
    print("2. Export the solution")
    print("3. Back")
    print("----------------------------------------------------------------------\n")

def menu_strategies():

    while True:
        while True:
            print_Menu()
            try:
                user_option = int(input("Select the strategy you want to analyze: "))
                break
            except:
                print("\nERROR: You have to choose an option between 0 and 5.\n")
        if user_option not in range(6) and isdigit(user_option) == False:
            print("\nERROR: You have to choose an option between 0 and 5.\n")
            continue
        else:
            if user_option ==0:
                print("BREADTH ALGORITHM")
                menu_main_functionality('BREADTH')
            elif user_option==1:
                print("DEPTH ALGORITHM")
                menu_main_functionality('DEPTH')
            elif user_option == 2:
                print("UNIFORM COST ALGORITHM")
                menu_main_functionality('UNIFORM')
            elif user_option == 3:
                print("A* ALGORITHM")
                menu_main_functionality('A')
            elif user_option == 4:
                print("GREEDY ALGORITHM")
                menu_main_functionality('GREEDY')
            elif user_option==5:
                print("Bye!")
                break

def menu_main_functionality(strategy):
    problem = Problem(0, [], State([]))
    already_imported = False
    while True:
        while True:
            print_menu_funcionalities()
            try:
                user_option = int(input("Select a functionality: "))
                break
            except:
                print("\nERROR: You have to choose an option between 0 and 3.\n")
        if user_option not in range(4) and isdigit(user_option) == False:
            print("\nERROR: You have to choose an option between 0 and 3.\n")
            continue
        elif (user_option == 1 or user_option == 2) and already_imported == False:
            print("\nERROR: You have to import a problem before selecting option 1 or 2.\n")
        else:
            if user_option == 0:

                path_json = input("Introduce the path of the problem:")
                problem = read_States_Txt(path_json, 1)
                if problem is not None:
                    print("Problem imported successfully!")
                    already_imported = True
                else:
                    already_imported = False

            elif user_option==1:
                random_heuristic = "{0:.2f}".format(uniform(0.0, 1000.0))
                random_value = "{0:.2f}".format(uniform(0.0, 1000.0))
                initial_node = Node(0, 0.0, problem.initState, None, None, 0, random_heuristic, random_value)
                if(initial_node == None):
                    continue
                else:
                    dq_frontier = Frontier_Deque()
                    hq_frontier = Frontier_Heapq()
                    list_frontier = Frontier_List()
                    dq_frontier.push(initial_node)
                    hq_frontier.push(initial_node)
                    list_frontier.push(initial_node)
                    #Test deque frontier
                    #test_frontier(dq_frontier)
                    #Test heapque frontier
                    test_frontier(hq_frontier)
                    #Test list frontier
                    #test_frontier(list_frontier)
            elif user_option == 2:
                state_space = State_space(strategy, problem)
                node_solution = state_space.search()
                if node_solution == 1:
                    print(f"\nERROR: Maximum depth ({problem.max_depth}) reached.\n")
                else:
                    state_space.export(node_solution)
            elif user_option == 3:
                print("Bye!")
                break

def test_frontier(frontier):
    number_nodes = 1
    id_node = 1
    minimum_time = 0
    maximum_time = 0
    sum_times = 0
    average_time = 0
    while resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/10**6 < 0.1:
        try:
            node = frontier.pop()
            number_nodes -= 1
            successors = State().successor_fn(node.state)
            depth = node.depth + 1
            for successor in successors:
                random_heuristic = "{0:.2f}".format(uniform(0.0, 1000.0))
                random_value = "{0:.2f}".format(uniform(0.0, 1000.0))
                node = Node(id_node, node.cost+successor[2], successor[1], node.ID, successor[0], depth, random_heuristic, random_value)
                pre_time = time.time()
                frontier.push(node)
                post_time = time.time()
                current_time = post_time-pre_time
                sum_times += current_time
                if(id_node == 1):
                    minimum_time = current_time
                    maximum_time = current_time
                else:
                    if(current_time < minimum_time):
                        minimum_time = current_time
                    if(current_time > maximum_time):
                        maximum_time = current_time
                number_nodes += 1
                id_node += 1
                average_time = sum_times/(id_node-1)
        except MemoryError:
            print("Memory consumed: " + str(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/10**6) + " GB" + "\nNumber of elements stored: " + str(number_nodes) + " elements" + "\nMinimum insertion time: " + str(minimum_time) + " seconds" + "\nMaximum insertion time: " + str(maximum_time) + " seconds" + "\nAverage insertion time: " + str(average_time) + " seconds\n")
    print("Memory consumed: " + str(resource.getrusage(resource.RUSAGE_SELF).ru_maxrss/10**6) + " GB" + "\nNumber of elements stored: " + str(number_nodes) + " elements" + "\nMinimum insertion time: " + str(minimum_time) + " seconds" + "\nMaximum insertion time: " + str(maximum_time) + " seconds" + "\nAverage insertion time: " + str(average_time) + " seconds\n")

if __name__ =='__main__':
    main()


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

# Scrapy settings for gplaycrawler project
#
# For simplicity, this file contains only the most important settings by
# default. All the other settings are documented here:
#
#     http://doc.scrapy.org/en/latest/topics/settings.html
#
BOT_NAME = 'insta'

SPIDER_MODULES = ['insta.spiders']
NEWSPIDER_MODULE = 'insta.spiders'
CONCURRENT_REQUESTS_PER_DOMAIN = 100
ITEM_PIPELINES = {'insta.pipelines.InstaPipeline':100}

USER_AGENT = 'Alo Ventures (+http://alo.ventures)'

REACTOR_THREADPOOL_MAXSIZE = 20
LOG_LEVEL = 'INFO'
COOKIES_ENABLED = False
##RETRY_ENABLED = False
DOWNLOAD_TIMEOUT = 60
##REDIRECT_ENABLED = False
AUTOTHROTTLE_ENABLED = True
AUTOTHROTTLE_START_DELAY = 1


import math
for _ in range(int(input())):
    n=int(input())
    arr=list(map(int,input().split()))

    maxi=0

    for i in range(1,n):
        if(arr[i]<arr[i-1]):
            maxi=max(arr[i-1]-arr[i],maxi)
            arr[i]=arr[i-1]
    if(maxi==0):
        print(0)
    else:
        print(int(math.log2(maxi))+1)


from PIL import Image
import os
import json
import random

packagePath = input("Enter the path to the package.json of the map:")
packageDir = os.path.dirname(packagePath) + "/"
package = json.load(open(packagePath,'r'))

#first, generate a base map based off of tileset image and tilemap
texturelist = package["texture"] #todo: support multi-image tilemaps and find some way to differentiate them
textures = list()
for texture in texturelist:
    textures.append([texture["name"] + ".png",Image.open(packageDir + texture["name"] +".png")])

for texture in textures:
    texture[1] = texture[1].transpose(Image.FLIP_TOP_BOTTOM)

maps = package["map"]

for Map in maps:
    tilemap = json.load(open(packageDir+Map["tilemap"]+".json",'r'))
    #with the tilemap we can start some interpretation of the map
    outputMaps = list()
    outputMap = None
    layers = tilemap["layers"]
    for layer in layers:
        #print(layer)
        if layer["name"] == "TileGroup":
            #this means it's the actual data layer
            #tiled also supports shader layers, which is used for water/lava
            if "tilesets" in tilemap:
                #go ahead and generate tilemaps
                tilesets = list()
                for tileset in tilemap["tilesets"]:
                    print(tileset["name"])
                    tiles = list()
                    texture = next(x for x in textures if x[0] == tileset["image"])
                    texture = texture[1]
                    theight = tileset["tileheight"]
                    twidth = tileset["tilewidth"]
                    tcolumns = tileset["columns"]
                    for y in range(int(tileset["imageheight"]/theight)):
                        for x in range(tcolumns):
                            tiles.append(texture.crop(((x*twidth),(y*theight),((x+1)*twidth),((y+1)*theight))))
                    #tile animation remap (we only want the first frame)
                    if "tiles" in tileset:
                        for tile in tileset["tiles"]:
                            if "animation" in tile:
                                tiles[tile["id"]] = tiles[tile["animation"][0]["tileid"]]
                    #print(tcolumns, len(tiles))
                    tilesets.append([twidth,theight,tiles])
                lLayers = list()
                for lLayer in layer["layers"]:
                    height = lLayer["height"]
                    width = lLayer["width"]
                    twidth = tilesets[0][0]
                    theight = tilesets[0][1]
                    tileIndexes = lLayer["data"]
                    tiles = list()
                    emptyTile = Image.new("RGBA",(twidth,theight),(0,0,0,0))
                    for i in range(len(tileIndexes)):
                        if(tileIndexes[i] != 0):
                            tiles.insert(i,tilesets[0][2][tileIndexes[i]-1])
                        else:
                            tiles.insert(i,emptyTile)
                    newMap = Image.new("RGBA",(width*twidth,height*theight),(0,0,0,0))

                    for y in range(height):
                        for x in range(width):
                            #this shit runs right to left
                            newMap.paste(tiles[(y*width)+(x)],(((x)*twidth),(y*theight),((x+1)*twidth),((y+1)*theight)))#assume default tileset, since it's not looking like any use more than 1
                    lLayers.append(newMap)
                for i in range(len(lLayers)):
                    if i == 0:
                        outputMap = lLayers[i]
                    else:
                        outputMap.paste(lLayers[i],(0,0),lLayers[i])
                    #lLayer.show()
                    #print(len(lLayer["data"]), tilemap["width"], tilemap["height"])
                outputMaps.append([Map["name"],outputMap])

    #now main map is done, generate derivative maps

    if "encount" in Map:
        encount = json.load(open(packageDir+Map["encount"]+".json",'r'))
        twidth = int(outputMap.width / encount["width"])
        theight = int(outputMap.height / encount["height"])
        width = encount["width"]
        height = encount["height"]
        colors = dict()
        for encounterGroup in encount["unique_grid_number"]:
            colors[encounterGroup] = random.choices(range(256), k=3)
            colors[encounterGroup].append(255)
            colors[encounterGroup] = tuple(colors[encounterGroup])
        tiles = list()
        for tile in encount["cells"]:
            tiles.append(Image.new("RGBA",(twidth,theight),colors[tile]))
        encountMap = outputMap.copy()
        for y in range(height):
            for x in range(width):
                encountMap.paste(tiles[(y*width)+(x)],(((x)*twidth),(y*theight),((x+1)*twidth),((y+1)*theight)),tiles[(y*width)+(x)])
        outputMaps.append([Map["name"]+"-encounter",encountMap])

    if "collision" in Map:
        collision = json.load(open(packageDir+Map["collision"]+".json",'r'))
        twidth = int(outputMap.width / 16)
        theight = int(outputMap.height / 16) #not fantastic but collision doesn't store width/height
        width = outputMap.width
        height = outputMap.height
        colors = dict()
        colors[0] = {0,0,0,0}
        colors[1] = {1,0,1,1}
        tiles = list()
        for tile in collision["cells"]:
            tiles.append(Image.new("RGBA",(twidth,theight),colors[tile]))
        collisionMap = outputMap.copy()
        for y in range(height):
            for x in range(width):
                collisionMap.paste(tiles[(y*width)+(x)],(((x)*twidth),(y*theight),((x+1)*twidth),((y+1)*theight)),tiles[(y*width)+(x)])
        outputMaps.append([Map["name"]+"-collision",collisionMap])

    for output in outputMaps:
        os.makedirs(packageDir + "/maps/",exist_ok=True)
        output[1].save(open(packageDir + "/maps/" + output[0] + ".png",'wb'))

FINAL FANTASY PIXEL REMASTERS/FFPR_GenerateMaps.py