import socket
import select
import threading
import time
import rsa
import pickle
from stegano import lsb
import random

ss = socket.socket(
            socket.AF_INET, socket.SOCK_STREAM)
host=socket.gethostname()
port=9999
addr=(host,port)
ss.bind(addr)
ss.listen(5)
print('runing server')

fd_name={}
SL=[]
SL.append(ss)

while True:
    r,w,e=select.select(SL,[],[])
    for temp in r:
        if temp is ss:  #name
                connection,address = temp.accept()
                print('new connection address:',address)
                SL.append(connection)

                (p,te)=pickle.loads(connection.recv(1024))
                (bob_pub,bob_priv,info)=te
                #name=connection.recv(1024).decode('utf-8')
                #(bob_pub,bob_priv,info)=pickle.loads(connection.recv(1024))
                name= rsa.decrypt(info, bob_priv)

                fd_name[connection]=name.decode('utf8')
                print(name.decode('utf8'))
                #print(SL)
                ###
        else:
            disconnect=False
            try:
                #
                #thetime=time.asctime( time.localtime(time.time()) )
                #data=temp.recv(1024).decode('utf-8')
                data=temp.recv(100000000)

                #data=thetime+'\n'+fd_name[temp]+':'+data+'\n\n'
            except socket.error:
                    data=fd_name[temp]+' leave the room\n'
                    disconnect=True
#禁止离开
            if disconnect:#leave
                    SL.remove(temp)
                    print(data)
                    for other in SL:
                        if other!=ss and other!=temp:
                            try:
                                other.send(data.encode('utf-8'))
                            except Exception(e):
                                print(e)
                    del fd_name[temp]

            else:
                #print(data)

                (p,te)=pickle.loads(data)
                print(p)
                if p!=3 and p!=8:
                    for other in SL:
                        if other!=ss:
                            try:
                                other.send(data)
                                #other.send(data.encode('utf-8'))
                            except Exception(e):
                                print(e)
                elif p==3:
                    ran=random.randrange(1,len(SL),1)
                    other=SL[ran]
                    try:
                        other.send(data)
                        #other.send(data.encode('utf-8'))
                    except Exception(e):
                        print(e)
                elif p==8:
                    ran=random.randrange(1,len(SL),1)
                    other=SL[ran]
                    try:
                        other.send(data)
                        #other.send(data.encode('utf-8'))
                    except Exception(e):
                        print(e)


import sys

import pygame

from settings import Settings
from ship import Ship

class AlienInvansion:
    """class for managing resources and game behavior"""
    def __init__(self):
        """initializes the game and creates game resources"""
        pygame.init()
        self.settings = Settings()

        self.screen = pygame.display.set_mode((self.settings.screen_width, self.settings.screen_height))

        self.screen = pygame.display.set_mode((1200,800))
        pygame.display.set_caption("Alien Invansion")
        self.ship = Ship(screen)
        # background assignment
        self.bg_color = (220, 230, 240)

    def run_game(self):
        """Starting the basic game cycle"""
        while True:
            self._check_ivents()
            self._update_screen()

    def _check_ivents(self):
        """обробляє нажаття клавіш та події мишки"""
        for event in pygame.event.get():
            if event.type == pygame.QUIT:
                sys.exit()

    def _update_screen(self):
        """Обновлює зображення на екрані та відображає новий екран"""
        self.screen.fill(self.settings.bg_color)
        self.ship.blitme()

        # display of the last registered screen
        pygame.display.flip()

if __name__ == '__main__':
    # Creating an exemplar and running the game
    ai = AlienInvansion
    ai.run_game()


class Solution(object):
    def searchMatrix(self, matrix, target):
        """
        :type matrix: List[List[int]]
        :type target: int
        :rtype: bool
        """
        if len(matrix) == 1:
            return (target in matrix[0])
        for i in range(len(matrix)):
            if matrix[i][0] <= target <= matrix[i][-1]:
                left, right = 0, len(matrix[0])-1
                while left <= right:
                    mid = (left + right) // 2
                    if target < matrix[i][mid]:
                        right = mid - 1
                    elif target > matrix[i][mid]:
                        left = mid + 1
                    else:
                        return True
        return False


def check(numb1, numb2):
    try:
        numb1 = int(numb1)
        numb2 = int(numb2)
    except:
        main()

def plus(numb1, numb2):
    print(int(numb1) + int(numb2))

def Xplus(numb1, numb2):
    print(int(numb1) - int(numb2))

def doublee(numb1, numb2):
    print(int(numb1) * int(numb2))

def Xdouble(numb1, numb2):
    print(int(numb1) / int(numb2))

def main():
    played = True
    while played:
        num1 = input("num 1: ")
        num2 = input("num 2: ")
        check(num1, num2)
        print("Дейсвия: ")
        print("""1. сложение
2. вычитание
3. умножение
4. деление""")
        todo = int(input("todo:  "))
        if todo not in "1 2 3 4".split():
            played = False

        if todo == 1:
            plus(num1, num2)

        if todo == 2:
            Xplus(num1, num2)

        if todo == 3:
            doublee(num1, num2)

        if todo == 4:
            Xdouble(num1, num2)

    else:
        print("Again?(y or yes)")
        again = input()
        if again != "y" or again != "yes":
            played = False
        if again == "yes" or again == "y":
            main()

main()


from pymongo import *

mng_client = MongoClient('localhost', 27017)
db = mng_client.arjun

# <------------------------------------- Artificial Intelligence Quiz ----------------------------------->

question = {"question_number": 1,
            "level": 1,
            "question": "Which of the following is true related to ‘Satisfiable’ property?",
            "question_type": 'mcq',
            "options": ["A statement is satisfiable if there is some interpretation for which it is false",
                        "A statement is satisfiable if there is some interpretation for which it is true",
                        "A statement is satisfiable if there is no interpretation for which it is true",
                        "A statement is satisfiable if there is no interpretation for which it is false"
            ]
            ,"correct_answer": "A statement is satisfiable if there is some interpretation for which it is true",
            "domain": 'artificial intelligence'
}

db['quiz'].insert_one(question)

question = {"question_number": 2,
            "level": 1,
            "question": "Third component of a planning system is to",
            "question_type": 'mcq',
            "options": ["Detect when a solution has been found",
                        "Detect when solution will be found",
                        "Detect whether solution exists or not",
                        "Detect whether multiple solutions exist"
            ]
            ,"correct_answer": "Detect when a solution has been found",
            "domain": 'artificial intelligence'
}

db['quiz'].insert_one(question)

question = {"question_number": 3,
            "level": 1,
            "question": "Which of the following is true in Statistical reasoning?",
            "question_type": 'mcq',
            "options": ["The representation is extended to allow some kind of numeric measure of certainty to be associated with each statement",
                        "The representation is extended to allow ‘TRUE or FALSE’ to be associated with each statement",
                        "The representation is extended to allow some kind of numeric measure of certainty to be associated common to all statements",
                        "The representation is extended to allow ‘TRUE or FALSE’ to be associated common to all statements"
            ]
            ,"correct_answer": "The representation is extended to allow some kind of numeric measure of certainty to be associated with each statement",
            "domain": 'artificial intelligence'
}

db['quiz'].insert_one(question)

question = {"question_number": 4,
            "level": 2,
            "question": "What is rational at any given time depends on",
            "question_type": 'mcq',
            "options": ["The performance measure that defines the criterion of success",
                        "The agent’s prior knowledge of the environment",
                        "The actions that the agent can perform",
                        "All of the above mentioned"
            ]
            ,"correct_answer": "All of the above mentioned",
            "domain": 'artificial intelligence'
}

db['quiz'].insert_one(question)

question = {"question_number": 5,
            "level": 2,
            "question": "The Task Environment of an agent consists of",
            "question_type": 'mcq',
            "options": ["Sensors",
                        "Actuators",
                        "Performance Measures",
                        "All of the mentioned"
            ]
            ,"correct_answer": "All of the mentioned",
            "domain": 'artificial intelligence'
}

db['quiz'].insert_one(question)

question = {"question_number": 6,
            "level": 2,
            "question": "What among the following constitutes to the incremental formulation of CSP?",
            "question_type": 'mcq',
            "options": ["Path cost",
                        "Goal cost",
                        "Successor function",
                        "All of the mentioned"
            ]
            ,"correct_answer": "All of the mentioned",
            "domain": 'artificial intelligence'
}

db['quiz'].insert_one(question)

question = {"question_number": 7,
            "level": 3,
            "question": "____________ is/are useful when the original formulation of a problem is altered in some way, typically because the set of constraints to consider evolves because of the environment.",
            "question_type": 'mcq',
            "options": ["Static CSPs",
                        "Dynamic CSPs",
                        "Flexible CSPs",
                        "None of the above"
            ]
            ,"correct_answer": "Dynamic CSPs",
            "domain": 'artificial intelligence'
}

db['quiz'].insert_one(question)

question = {"question_number": 8,
            "level": 3,
            "question": "The main components of the expert systems is/are,",
            "question_type": 'mcq',
            "options": ["Inference Engine",
                        "Knowledge Base",
                        "Inference Engine & Knowledge Base",
                        "None of the above"
            ]
            ,"correct_answer": "Inference Engine & Knowledge Base",
            "domain": 'artificial intelligence'
}

db['quiz'].insert_one(question)

question = {"question_number": 9,
            "level": 3,
            "question": "The CAI (Computer-Assisted Instruction) technique based on programmed instruction is:",
            "question_type": 'mcq',
            "options": ["frame-based CAI",
                        "generative CAI",
                        "problem-solving CAI",
                        "intelligent CAI"
            ]
            ,"correct_answer": "frame-based CAI",
            "domain": 'artificial intelligence'
}

db['quiz'].insert_one(question)

# <------------------------------------- Big Data Quiz ----------------------------------->

question = {"question_number": 1,
           "level": 1,
           "question": "__________ can best be described as a programming model used to develop Hadoop-based applications that can process massive amounts of data.",
           "question_type": 'mcq',
           "options": ["MapReduce",
                       "Mahout",
                       "Oozie",
                       "All of the mentioned"
           ]
           ,"correct_answer": "MapReduce",
           "domain": 'big data analytics'
}

db['quiz'].insert_one(question)

question = {"question_number": 2,
           "level": 1,
           "question": "Which of these is the main component of Big Data?",
           "question_type": 'mcq',
           "options": ["YARN",
                       "MapReduce",
                       "HDFS",
                       "All of the above"
           ]
           ,"correct_answer": "YARN",
           "domain": 'big data analytics'
}

db['quiz'].insert_one(question)

question = {"question_number": 3,
           "level": 1,
           "question": "Which of these is best suited for assigning resources to a highly parallel application?",
           "question_type": 'mcq',
           "options": ["HDFS",
                       "Hadoop",
                       "Spark",
                       "YARN"
           ]
           ,"correct_answer": "MapR",
           "domain": 'big data analytics'
}

db['quiz'].insert_one(question)

question = {"question_number": 4,
           "level": 2,
           "question": "Hadoop can run in the following modes except",
           "question_type": 'mcq',
           "options": ["Pseuo-Distributed Mode",
                       "Standalone Mode",
                       "Multiple Cluster Node",
                       "Separate mode"
           ]
           ,"correct_answer": "Separate mode",
           "domain": 'big data analytics'
}

db['quiz'].insert_one(question)

question = {"question_number": 5,
           "level": 2,
           "question": "According to analysts, for what can traditional IT systems provide a foundation when they're integrated with big data technologies like Hadoop ?",
           "question_type": 'mcq',
           "options": ["Data Warehousing and business intelligence",
                       "Collecting and Storing unstructured data",
                       "Management of hadoop clusters",
                       "Big Data management and data mining"
           ]
           ,"correct_answer": "Big Data management and data mining",
           "domain": 'big data analytics'
}

db['quiz'].insert_one(question)

question = {"question_number": 6,
           "level": 2,
           "question": "What is a unit of data that flows through a Flume agent?",
           "question_type": 'mcq',
           "options": ["Log",
                       "Event",
                       "Row",
                       "None of the above"
           ]
           ,"correct_answer": "Event",
           "domain": 'big data analytics'
}

db['quiz'].insert_one(question)

question = {"question_number": 7,
           "level": 3,
           "question": "What makes Big Data analysis difficult to optimize?",
           "question_type": 'mcq',
           "options": ["Not difficult to optimize",
                       "Both data and cost effective ways to mine data to make business sense out of it",
                       "The technology to mine Data",
                       "all of the above"
           ]
           ,"correct_answer": "Both data and cost effective ways to mine data to make business sense out of it",
           "domain": 'big data analytics'
}

db['quiz'].insert_one(question)

question = {"question_number": 8,
           "level": 3,
           "question": "Which of the following hides the limitations of Java behind a powerful and concise Clojure API for Cascading.",
           "question_type": 'mcq',
           "options": ["Hcatalog",
                       "Hcalding",
                       "Scaldng",
                       "Cascalog"
           ]
           ,"correct_answer": "Cascalog",
           "domain": 'big data analytics'
}

db['quiz'].insert_one(question)

question = {"question_number": 9,
           "level": 3,
           "question": "Listed below are the three steps that are followed to deploy a Big Data Solution except",
           "question_type": 'mcq',
           "options": ["Data Ingestion",
                       "Data Processing",
                       "Data dissemination",
                       "Data Storage"
           ]
           ,"correct_answer": "Data dissemination",
           "domain": 'big data analytics'
}

db['quiz'].insert_one(question)


'''

Test Case Generation

Test Case 1

Input :

C0D3C43F

Output :

3943

Explanation :

Changing the character 'C' to the character '9' thus giving the string "C0D3943F" gives the maximum age of the universe.

Test Case 2

Input :

C0D3C45F

Output :

3945

Explanation :

Changing the character 'C' to the character '9' thus giving the string "C0D3945F" gives the maximum age of the universe.

'''

from itertools import combinations

s = input()

def wrong(s):
    for i in range(len(s)):
        temp = list(s)
        for j in range(10):
            temp[i] = str(j)
            for k in range(26):
                temp[i] = chr(65+k)
                yield "".join(temp)

def check(s):
    return all(i in "0123456789" for i in s)

print(max(int(i) for i in wrong(s) if check(i)))


"""
    App Handler Module

    Flask app is loaded here in order to avoid repetition. Other handler should
    import this module.

    Other handler modules must have unique function names for their endpoints
    (e.g. journals_index rather than just index). If not, Flask will raise the
    following error:

    AssertionError: View function mapping is overwriting an existing endpoint function
"""
from datetime import date, datetime
from os.path import dirname, join

from flask import Flask, request, render_template
from flask.json import JSONEncoder

from config import secrets

#
# Constants
#
APP_PATH = dirname(dirname(__file__))
TEMPLATE_PATH = join(APP_PATH, 'templates')

#
# Flask App
#
app = Flask(__name__, template_folder=TEMPLATE_PATH)
app.secret_key = secrets.FLASK_SECRET_KEY

#
# Custom JSON Encode for date objects
# See https://github.com/jeffknupp/sandman/issues/22#issuecomment-35677606
#
class CustomJSONEncoder(JSONEncoder):
    def default(self, obj):
        try:
            if isinstance(obj, date):
                return obj.isoformat()
            iterable = iter(obj)
        except TypeError:
            pass
        else:
            return list(iterable)
        return JSONEncoder.default(self, obj)
app.json_encoder = CustomJSONEncoder

#
# Template Globals
# http://stackoverflow.com/a/29978965/1093087
#
@app.context_processor
def common_variables():
    return dict(
        current_year = date.today().year,
    )

@app.context_processor
def template_helpers():
    def date_now(format="%Y-%m-%d %H:%M:%S"):
        """ returns the formated datetime """
        return datetime.now().strftime(format)

    def navbar_class(tab):
        # Use request.path. request.url_rule.rule does not exist for errorhandler.
        route = request.path
        if tab in route:
            return 'active'
        else:
            return 'inactive'

    def format_amount(value, default=None):
        if not value:
            return default
        else:
            return '%.2f' % (value)

    return dict(
        date_now=date_now,
        navbar_class=navbar_class,
        format_amount=format_amount
    )

#
# Exception Handlers
#
@app.errorhandler(404)
def page_not_found(e):
    """Return a custom 404 error."""
    return render_template('404.html'), 404

@app.errorhandler(500)
def application_error(e):
    """Return a custom 500 error."""
    return render_template('500.html', error=e), 500


import io
import sys

_INPUT = """\
6
2 2 180
5 0 120
0 0 11
15 5 360
-505 191 278
"""

sys.stdin = io.StringIO(_INPUT)
case_no=int(input())
for __ in range(case_no):
  import math
  a,b,d=map(int,input().split())
  x=(math.degrees(math.atan2(b, a))+d)*math.pi/180
  r=(a**2+b**2)**.5
  print(math.cos(x)*r,math.sin(x)*r)


import argparse
import os

import cv2
import h5py
import matplotlib.pyplot as plt
import numpy as np
from PIL import Image

def plot_image_pair(imgs, dpi=100, size=6, pad=0.5):
    """Plot image pairs with plt figure."""
    n = len(imgs)
    assert n == 2, 'number of images must be two'
    figsize = (size * n, size * 3 / 4) if size is not None else None
    _, ax = plt.subplots(1, n, figsize=figsize, dpi=dpi)
    for i in range(n):
        ax[i].imshow(imgs[i].astype('uint8'),
                     cmap=plt.get_cmap('gray'),
                     vmin=0,
                     vmax=255)
        ax[i].get_yaxis().set_ticks([])
        ax[i].get_xaxis().set_ticks([])
        for spine in ax[i].spines.values():  # remove frame
            spine.set_visible(False)
    plt.tight_layout(pad=pad)

def visualize_box(image1, bbox1, depth1, image2, bbox2, depth2, output):
    """visualization co-visible bounding box of image pairs."""
    bbox1 = bbox1.numpy().astype(int)
    bbox2 = bbox2.numpy().astype(int)

    left = cv2.rectangle(image1.numpy(), (bbox1[0], bbox1[1]),
                         ((bbox1[2], bbox1[3])), (255, 0, 0), 2)
    right = cv2.rectangle(image2.numpy(), (bbox2[0], bbox2[1]),
                          ((bbox2[2], bbox2[3])), (0, 0, 255), 2)
    viz = cv2.hconcat([left, right])

    depth_viz = cv2.hconcat([
        np.stack([depth1.numpy()] * 3, -1) * 10,
        np.stack([depth2.numpy()] * 3, -1) * 10,
    ])
    all_viz = cv2.vconcat([viz, depth_viz])
    cv2.imwrite('bbox_' + output, all_viz)

def visualize_mask(image1,
                   bbox1,
                   mask1,
                   depth1,
                   image2,
                   bbox2,
                   mask2,
                   depth2,
                   output,
                   fig=False):
    """visulaization co-visible bounding box and mask of image pairs."""
    bbox1 = bbox1.numpy()
    bbox2 = bbox2.numpy()
    mask1 = np.stack([mask1.numpy().astype(float)] * 3, -1) * np.array(
        [255, 0, 0])
    mask2 = np.stack([mask2.numpy().astype(float)] * 3, -1) * np.array(
        [0, 0, 255])
    left = cv2.rectangle(image1.numpy(), tuple(bbox1[0:2]), tuple(bbox1[2:]),
                         (255, 0, 0), 2)
    right = cv2.rectangle(image2.numpy(), tuple(bbox2[0:2]), tuple(bbox2[2:]),
                          (0, 0, 255), 2)

    left = cv2.addWeighted(left, 0.5, mask1, 0.5, 0, dtype=cv2.CV_32F)
    right = cv2.addWeighted(right, 0.5, mask2, 0.5, 0, dtype=cv2.CV_32F)
    if fig:
        plot_image_pair([left[:, :, ::-1], right[:, :, ::-1]])
        plt.savefig(str(output), bbox_inches='tight', pad_inches=0)
        plt.close()
    else:
        viz = cv2.hconcat([left, right])
        depth_viz = cv2.hconcat([
            np.stack([depth1.numpy()] * 3, -1) * 10,
            np.stack([depth2.numpy()] * 3, -1) * 10,
        ])
        all_viz = cv2.vconcat([viz, depth_viz])
        cv2.imwrite('mask_' + output, all_viz)

def resize_dataset(img, image_size, depth=False):
    """resize image with different tyle."""
    if len(img.shape) == 2:
        h, w = img.shape
    else:
        h, w, _ = img.shape
    # resize w*h
    if w > h:
        if depth:
            img1 = cv2.resize(
                img,
                (int(image_size[0] / h * w), image_size[0]),
                interpolation=cv2.INTER_NEAREST,
            )
        else:
            img1 = cv2.resize(img, (int(image_size[0] / h * w), image_size[0]))
        resize_ratio = (int(image_size[0] / h * w) / w, image_size[0] / h)
    else:
        if depth:
            img1 = cv2.resize(
                img,
                (image_size[0], int(image_size[0] * h / w)),
                interpolation=cv2.INTER_NEAREST,
            )
        else:
            img1 = cv2.resize(img, (image_size[0], int(image_size[0] * h / w)))
        resize_ratio = (image_size[0] / w, int(image_size[0] * h / w) / h)
    return img1, resize_ratio

def get_boxes(points):
    """calculate boundary box of point cloud."""
    box = np.array(
        [points[0].min(), points[1].min(), points[0].max(), points[1].max()])
    return box

def get_maskes(points, h, w):
    """calculate the mask mat of point cloud, output binary mask."""
    points = points.astype(int)
    mask = np.zeros((h, w))
    mask[points[1], points[0]] = 1
    return mask

def numpy_overlap_box(K1, depth1, pose1, bbox1, ratio1, K2, depth2, pose2,
                      bbox2, ratio2):
    """calculate numpy array co-visible bounding box."""
    mask1 = np.where(depth1 > 0)
    u1, v1 = mask1[1], mask1[0]
    Z1 = depth1[v1, u1]

    # COLMAP convention
    x1 = (u1 + bbox1[1] + 0.5) / ratio1[1]
    y1 = (v1 + bbox1[0] + 0.5) / ratio1[0]
    X1 = (x1 - K1[0, 2]) * (Z1 / K1[0, 0])
    Y1 = (y1 - K1[1, 2]) * (Z1 / K1[1, 1])
    # Homogeneous coordinates
    XYZ1_hom = np.concatenate(
        [
            X1.reshape(1, -1),
            Y1.reshape(1, -1),
            Z1.reshape(1, -1),
            np.ones_like(Z1.reshape(1, -1)),
        ],
        axis=0,
    )
    # Warp points to camera2
    XYZ2_hom = pose2 @ np.linalg.inv(pose1) @ XYZ1_hom
    XYZ2 = XYZ2_hom[:-1, :] / XYZ2_hom[-1, :].reshape(1, -1)

    uv2_hom = K2 @ XYZ2
    uv2 = uv2_hom[:-1, :] / uv2_hom[-1, :].reshape(1, -1)
    h, w = depth2.shape
    u2 = uv2[0, :] * ratio2[1] - bbox2[1] - 0.5
    v2 = uv2[1, :] * ratio2[0] - bbox2[0] - 0.5
    uv2 = np.concatenate([u2.reshape(1, -1), v2.reshape(1, -1)], axis=0)
    i = uv2[0, :].astype(int)
    j = uv2[1, :].astype(int)

    valid_corners = np.logical_and(np.logical_and(i >= 0, j >= 0),
                                   np.logical_and(i < h, j < w))

    valid_uv1 = np.stack((u1[valid_corners], v1[valid_corners])).astype(int)
    valid_uv2 = uv2[:, valid_corners].astype(int)

    # depth validation
    Z2 = depth2[valid_uv2[1], valid_uv2[0]]
    inlier_mask = np.absolute(XYZ2[2, valid_corners] - Z2) < 0.5

    valid_uv1 = valid_uv1[:, inlier_mask]
    valid_uv2 = valid_uv2[:, inlier_mask]

    if valid_uv1.shape[1] == 0 or valid_uv2.shape[1] == 0:
        return (
            np.array([0] * 4),
            np.zeros((h, w)),
            np.array([0] * 4),
            np.zeros((h, w)),
            False,
        )
    # box with x1, y1, x2, y2
    box1 = get_boxes(valid_uv1)
    box2 = get_boxes(valid_uv2)
    # mask
    mask1 = get_maskes(valid_uv1, h, w)
    mask2 = get_maskes(valid_uv2, h, w)
    return box1, mask1, box2, mask2, True

def crop(image1, image2, central_match, image_size):
    """crop patch from the central match and protect patch, not outside the
    boundary."""
    bbox1_i = max(int(central_match[0]) - image_size[0] // 2, 0)
    if bbox1_i + image_size[0] >= image1.shape[0]:
        bbox1_i = image1.shape[0] - image_size[0]
    bbox1_j = max(int(central_match[1]) - image_size[1] // 2, 0)
    if bbox1_j + image_size[1] >= image1.shape[1]:
        bbox1_j = image1.shape[1] - image_size[1]

    bbox2_i = max(int(central_match[2]) - image_size[1] // 2, 0)
    if bbox2_i + image_size[1] >= image2.shape[0]:
        bbox2_i = image2.shape[0] - image_size[1]
    bbox2_j = max(int(central_match[3]) - image_size[1] // 2, 0)
    if bbox2_j + image_size[1] >= image2.shape[1]:
        bbox2_j = image2.shape[1] - image_size[1]

    return (
        image1[bbox1_i:bbox1_i + image_size[0],
               bbox1_j:bbox1_j + image_size[1], ],
        np.array([bbox1_i, bbox1_j]),
        image2[bbox2_i:bbox2_i + image_size[0],
               bbox2_j:bbox2_j + image_size[1], ],
        np.array([bbox2_i, bbox2_j]),
    )

def recover_pair(base_path,
                 image_size,
                 pair_metadata,
                 with_mask=False,
                 with_gray=False):
    """calculate image pairs information from metadata.

    Args:
        pair_metadata (dict): contains intrinsic, pose, depth and image path
    """
    depth_path1 = os.path.join(base_path, pair_metadata['depth_path1'])
    with h5py.File(depth_path1, 'r') as hdf5_file:
        depth1 = np.array(hdf5_file['/depth'])
    assert np.min(depth1) >= 0
    image_path1 = os.path.join(base_path, pair_metadata['image_path1'])
    if with_gray:
        image1 = cv2.imread(image_path1, cv2.IMREAD_GRAYSCALE)
    else:
        image1 = cv2.imread(image_path1)
    assert image1.shape[0] == depth1.shape[0] and image1.shape[
        1] == depth1.shape[1]
    intrinsics1 = pair_metadata['intrinsics1']
    pose1 = pair_metadata['pose1']

    depth_path2 = os.path.join(base_path, pair_metadata['depth_path2'])
    with h5py.File(depth_path2, 'r') as hdf5_file:
        depth2 = np.array(hdf5_file['/depth'])
    assert np.min(depth2) >= 0
    image_path2 = os.path.join(base_path, pair_metadata['image_path2'])
    if with_gray:
        image2 = cv2.imread(image_path2, cv2.IMREAD_GRAYSCALE)
    else:
        image2 = cv2.imread(image_path2)
    assert image2.shape[0] == depth2.shape[0] and image2.shape[
        1] == depth2.shape[1]
    intrinsics2 = pair_metadata['intrinsics2']
    pose2 = pair_metadata['pose2']

    # Resize data
    image1, resize_ratio1 = resize_dataset(image1, image_size)
    image2, resize_ratio2 = resize_dataset(image2, image_size)

    central_match = pair_metadata['central_match'] * np.concatenate(
        (resize_ratio1, resize_ratio2))
    image1, bbox1, image2, bbox2 = crop(image1, image2, central_match,
                                        image_size)

    depth1, _ = resize_dataset(depth1, image_size, True)
    depth2, _ = resize_dataset(depth2, image_size, True)

    depth1 = depth1[bbox1[0]:bbox1[0] + image_size[0],
                    bbox1[1]:bbox1[1] + image_size[1], ]
    depth2 = depth2[bbox2[0]:bbox2[0] + image_size[0],
                    bbox2[1]:bbox2[1] + image_size[1], ]
    if with_mask:
        mask_path1 = os.path.join(
            base_path,
            pair_metadata['image_path1'].replace('images', 'masks').replace(
                'jpg', 'png').replace('JPG', 'png'),
        )
        mask_path2 = os.path.join(
            base_path,
            pair_metadata['image_path2'].replace('images', 'masks').replace(
                'jpg', 'png').replace('JPG', 'png'),
        )

        mask1 = np.array(Image.open(mask_path1))
        mask2 = np.array(Image.open(mask_path2))
        mask1, _ = resize_dataset(mask1, image_size, True)
        mask2, _ = resize_dataset(mask2, image_size, True)

        mask1 = mask1[bbox1[0]:bbox1[0] + image_size[0],
                      bbox1[1]:bbox1[1] + image_size[1], ]
        mask2 = mask2[bbox2[0]:bbox2[0] + image_size[0],
                      bbox2[1]:bbox2[1] + image_size[1], ]
    else:
        mask1 = np.zeros(1)
        mask2 = np.zeros(1)
    match_file_name = (pair_metadata['image_path1'].split('/')[-1] + '_' +
                       pair_metadata['image_path2'].split('/')[-1])

    return (
        image1,
        depth1,
        intrinsics1,
        pose1,
        bbox1,
        resize_ratio1,
        bbox1,
        mask1,
        image2,
        depth2,
        intrinsics2,
        pose2,
        bbox2,
        resize_ratio2,
        bbox2,
        mask2,
        match_file_name,
        central_match,
    )

# print image width and height
def statistics_image_pairs(pairs_list_path, dataset_path):
    with open(pairs_list_path, 'r') as f:
        for line in f.readlines():
            image_path1 = os.path.join(dataset_path, line.split()[0])
            image1 = cv2.imread(image_path1)
            image_path2 = os.path.join(dataset_path, line.split()[5])
            image2 = cv2.imread(image_path2)
            print(image1.shape, image2.shape)

# Main pipeline
if __name__ == '__main__':
    parser = argparse.ArgumentParser(
        description='Generate megadepth image pairs',
        formatter_class=argparse.ArgumentDefaultsHelpFormatter,
    )

    parser.add_argument(
        '--pairs_list_path',
        type=str,
        default='assets/megadepth_validation.txt',
        help='Path to the list of scenes',
    )
    parser.add_argument('--dataset_path',
                        type=str,
                        default='',
                        help='path to the dataset')
    args = parser.parse_args()

    statistics_image_pairs(**args.__dict__)


import random
import copy

class Conway:

     def __init__ (self,textlistobject,cells=None,livechar='█',deadchar=' ',constitute=True,y_min=0,y_max=None,x_min=0,x_max=None,randomizing=True,changing=True):
          if not y_max:
               self.max_y = len(textlistobject)
          else:
               self.max_y = y_max
          if not x_max:
               self.max_x = min([len(x) for x in textlistobject])
          else:
               self.max_x = x_max
          self.y_min = y_min
          self.x_min = x_min
          print(self.max_y,self.y_min,self.max_x,self.x_min)
          self.cells = {}
          if cells and isinstance(cells,dict):
               self.cells = cells
          self.deadchar = deadchar
          self.random_mode = randomizing
          self.livechar = livechar
          self.old_image = {}

          self.odds = {1:(1000,1000),
                       2:(1000,1000),
                       3:(1000,1000),
                       4:(1000,1000)}
          self.textlistobject = textlistobject
          self.distance = 1
          self.odd_factor = 100
          self.background = copy.deepcopy(self.textlistobject)
          self.changing = changing
          if cells and isinstance(cells,(set,list)):
                    for c in cells:

                         if self.textlistobject[c[0]][c[1]] == livechar:
                              self.cells[c] = True
                         elif self.textlistobject[c[0]][c[1]] == deadchar:
                              self.cells[c] = False

                    self.y_min = min([c[0] for c in cells])
                    self.max_y = max([c[0] for c in cells])
                    self.x_min = min([c[1] for c in cells])
                    self.max_x = max([c[1] for c in cells])

          elif constitute:

               for y in  range(self.y_min,self.max_y):
                    for x in range(self.x_min,self.max_x):

                         if self.textlistobject[y][x]  == livechar:
                              self.cells[(y,x)] = True
                         elif self.textlistobject[y][x] == deadchar:
                              self.cells[(y,x)] = False
          for c in self.cells:
               self.old_image[c] = self.textlistobject[c[0]][c[1]]

     def change_odds (self,odds=(920,1000),key=1):
          if isinstance(odds,tuple) and key in [1,2,3,4]:
               self.odds[key] = odds

     def change_distance (self,distance=1):
          if 0 <= distance < 5:
               self.distance = distance

     def get_properties (self):
          return self.odds,self.distance

     def burst (self):

          y = random.randrange(self.y_min+5,self.max_y-5)
          x = random.randrange(self.x_min+5,self.max_x-5)

          if self.surrounding_count(self.surrounding_coords((y,x),distance=3)) == 0:

               for c in self.surrounding_coords((y,x),distance=5):
                    self.cells[c] = self.randomize(random.choice([False,True]),(95-int(((abs(c[0]-y))+(abs(c[1]-x)))/2)*20,100))

     def randomize (self,boolean,odds=None):
          if self.random_mode:

               if not odds:
                    odds = self.odds
               if random.randint(0,odds[1]+1) <= odds[0]:
                    return boolean
               else:
                    return not boolean
          else:
               return boolean

     def surrounding_coords (self,coord,distance=1):
          y = coord[0]
          x = coord[1]

          surround = []
          for y_off in range(-distance,distance+1):
               for x_off in range(-distance,distance+1):
                    if abs(y_off) + abs(x_off) != 0:
                         if self.y_min <= y+y_off < self.max_y and self.x_min <= x+x_off < self.max_x:
                              surround.append((y+y_off,x+x_off))
          return surround

     def surrounding_count (self,surround=None):

          if not surround:
               surround = []
          count = 0
          for s in surround:
               if s in self.cells:
                    if self.cells[s]:
                         count += 1
          return count

     def get_surrounding (self,coord):
          return self.surrounding_count(self.surrounding_coords(coord,distance=self.distance))

     def cycle_through_cells (self):

          if self.changing:
               if random.choice(range(50)) == 25:
                    self.random_mode = not self.random_mode

          new_cells = {}

          for cell in self.cells:

               if self.cells[cell]:

                    if self.get_surrounding(cell) in [2,3]:
                         new_cells[cell] = self.randomize(True,odds=self.odds[1])

                    elif self.get_surrounding(cell) in [0,1,4,5,6]:
                         new_cells[cell] = self.randomize(False,odds=self.odds[2])

               else:
                    if self.get_surrounding(cell) == 3:
                         new_cells[cell] = self.randomize(True,odds=self.odds[3])

                    else:
                         new_cells[cell] = self.randomize(False,odds=self.odds[4])

          self.cells = new_cells

     def generate (self):

          self.cycle_through_cells()

          for y in range(self.y_min,self.max_y):
               segment = ''
               for x in range(self.x_min,self.max_x):
                    if (y,x) in self.cells:
                         segment += {False:self.deadchar,True:self.livechar}[self.cells[(y,x)]]
                    else:
                         segment += self.background[y][x]
               self.textlistobject[y] = self.textlistobject[y][0:self.x_min] + segment +  self.textlistobject[y][self.max_x+1:]

          return self.textlistobject

if __name__ == '__main__':

     textlistobject =['                    '*10,
                      '                    '*10,
                      '                    '*10,
                      '                    '*10,
                      '                    '*10,
                      '                    '*10,
                      '                    '*10]*5

     x = Conway(textlistobject)
     print('\n'.join(textlistobject))

     while True:

          textlistobject = x.generate()
          x.burst()
          print('\n'.join(x.textlistobject))

          input('?')


"""10816 숫자 카드 2"""
import sys

input = sys.stdin.readline

def binary_search(element, some_list, start, end):
    """이진 탐색 함수"""
    if start > end:  # 다 탐색하면 종료
        return 0

    mid = (start + end) // 2  # 중간 인덱스
    if some_list[mid] == element:  # 값을 찾았다면
        return some_list[start : end + 1].count(
            element
        )  # 지금 구한 리스트에서 같은 값을 가지는 인덱스의 개수를 구함
    elif some_list[mid] > element:  # 중간값보다 찾는 값이 작으면 앞부분만 확인
        return binary_search(element, some_list, start, mid - 1)
    elif some_list[mid] < element:  # 중간값보다 찾는 값이 크다면 뒷부분만 확인
        return binary_search(element, some_list, mid + 1, end)

n_len = int(input())
n_list = sorted(map(int, input().split()))

m_len = int(input())
m_list = list(map(int, input().split()))
m_dict = {}  # 값: 개수를 저장할 사전

for m in m_list:
    if m not in m_dict:
        m_dict[m] = binary_search(m, n_list, 0, n_len - 1)

print(" ".join(str(m_dict[x]) if x in m_dict else "0" for x in m_list))

# ------------------------------------------------------------------------------------------------------------------------
"""내장 함수 이용"""
"""훨씬 빠름"""
import sys
from collections import Counter

n_len = int(input())
n_list = sys.stdin.readline().split()

m_len = int(input())
m_list = sys.stdin.readline().split()

C = Counter(n_list)  # '값: 들어있는 개수'로 사전 정의(자세한 건 '여러 기능들/collections.py' 참고)

for m in m_list:
    if m in C:
        print(C[m], end=" ")
    else:
        print(0, end=" ")

# comprehension을 쓸 때는 문자열을 써야함
# print(" ".join(f"{C[m]}" if m in C else "0" for m in m_list))

Baekjoon/solve_step_by_step/27_binary_search/02. 숫자 카드 2.py


def get_stroke_freq(Ax, Az, fs_a, nperseg, peak_thresh, stroke_ratio=None):
    """Determine stroke frequency to use as a cutoff for filtering

    Args
    ----
    Ax: numpy.ndarray, shape (n,)
        x-axis accelermeter data (longitudinal)
    Ay: numpy.ndarray, shape (n,)
        x-axis accelermeter data (lateral)
    Az: numpy.ndarray, shape (n,)
        z-axis accelermeter data (dorso-ventral)
    fs_a: float
        sampling frequency (i.e. number of samples per second)
    nperseg: int
        length of each segment (i.e. number of samples per frq. band in PSD
        calculation. Default to 512 (scipy.signal.welch() default is 256)
    peak_thresh: float
        PSD power level threshold. Only peaks over this threshold are returned.

    Returns
    -------
    cutoff_frq: float
        cutoff frequency of signal (Hz) to be used for low/high-pass filtering
    stroke_frq: float
        frequency of dominant wavelength in signal
    stroke_ratio: float

    Notes
    -----
    During all descents and ascents phases where mainly steady swimming occurs.
    When calculated for the whole dive it may be difficult to differentiate the
    peak at which stroking rate occurs as there are movements than
    only steady swimming

    Here the power spectra is calculated of the longitudinal and dorso-ventral
    accelerometer signals during descents and ascents to determine the dominant
    stroke frequency for each animal in each phase

    This numpy samples per f segment 512 and a sampling rate of fs_a.

    Output: S is the amount of power in each particular frequency (f)
    """

    import numpy

    from . import dsp
    from . import utils
    from .plots import plotdsp

    # Axes to be used for determining `stroke_frq`
    stroke_axes = [(0, "x", "dorsa-ventral", Ax), (2, "z", "lateral", Az)]

    # Lists for appending values from each axis
    cutoff_frqs = list()
    stroke_frqs = list()
    stroke_ratios = list()

    # Iterate over axes in `stroke_axes` list appending output to above lists
    for i, i_alph, name, data in stroke_axes:

        frqs, S, _, _ = dsp.calc_PSD_welch(data, fs_a, nperseg)

        # Find index positions of local maxima and minima in PSD
        delta = S.max() / 1000
        max_ind, min_ind = dsp.simple_peakfinder(range(len(S)), S, delta)

        max0 = max_ind[0]

        # TODO hack fix, improve later
        try:
            min_ind[0]
        except Exception:
            stroke_ratio = 0.4

        stroke_frq = frqs[max0]

        # Prompt user for `cutoff_frq` value after inspecting PSD plot
        title = "PSD - {} axis (n={}), {}".format(i_alph, i, name)
        # Plot power spectrum against frequency distribution
        plotdsp.plot_welch_peaks(frqs, S, max_ind, title=title)

        # Get user input of cutoff frequency identified off plots
        cutoff_frq = utils.recursive_input("cutoff frequency", float)

        # Append values for axis to list
        cutoff_frqs.append(cutoff_frq)
        stroke_frqs.append(stroke_frq)
        stroke_ratios.append(stroke_ratio)

    # Average values for all axes
    cutoff_frq = float(numpy.mean(cutoff_frqs))
    stroke_frq = float(numpy.mean(stroke_frqs))

    # Handle exception of manual selection when `stroke_ratio == None`
    # TODO with fix
    try:
        stroke_ratio = float(numpy.mean(stroke_ratios))
    except Exception:
        stroke_ratio = None

    return cutoff_frq, stroke_frq, stroke_ratio

def get_stroke_glide_indices(A_g_hf, fs_a, J, t_max):
    """Get stroke and glide indices from high-pass accelerometer data

    Args
    ----
    A_g_hf: 1-D ndarray
        Animal frame triaxial accelerometer matrix at sampling rate fs_a.

    fs_a: int
        Number of accelerometer samples per second

    J: float
        Frequency threshold for detecting a fluke stroke in m/s^2.  If J is not
        given, fluke strokes will not be located but the rotations signal (pry)
        will be computed.

    t_max: int
        Maximum duration allowable for a fluke stroke in seconds.  A fluke
        stroke is counted whenever there is a cyclic variation in the pitch
        deviation with peak-to-peak magnitude greater than +/-J and consistent
        with a fluke stroke duration of less than t_max seconds, e.g., for
        Mesoplodon choose t_max=4.

    Returns
    -------
    GL: 1-D ndarray
        Matrix containing the start time (first column) and end time (2nd
        column) of any glides (i.e., no zero crossings in t_max or more
        seconds). Times are in seconds.

    Note
    ----
    If no J or t_max is given, J=[], or t_max=[], GL returned as None
    """
    import numpy

    from . import dsp

    # Check if input array is 1-D
    if A_g_hf.ndim > 1:
        raise IndexError(
            "A_g_hf multidimensional: Glide index determination "
            "requires 1-D acceleration array as input"
        )

    # Convert t_max to number of samples
    n_max = t_max * fs_a

    # Find zero-crossing start/stops in pry(:,n), rotations around n axis.
    zc = dsp.findzc(A_g_hf, J, n_max / 2)

    # find glides - any interval between zeros crossings greater than `t_max`
    ind = numpy.where(zc[1:, 0] - zc[0:-1, 1] > n_max)[0]
    gl_ind = numpy.vstack([zc[ind, 0] - 1, zc[ind + 1, 1] + 1]).T

    # Compute mean index position of glide, Only include sections with jerk < J
    gl_mean_idx = numpy.round(numpy.mean(gl_ind, 1)).astype(int)
    gl_ind = numpy.round(gl_ind).astype(int)

    for i in range(len(gl_mean_idx)):
        col = range(gl_mean_idx[i], gl_ind[i, 0], -1)
        test = numpy.where(numpy.isnan(A_g_hf[col]))[0]
        if test.size != 0:
            gl_mean_idx[i] = numpy.nan
            gl_ind[i, 0] = numpy.nan
            gl_ind[i, 1] = numpy.nan
        else:
            over_J1 = numpy.where(abs(A_g_hf[col]) >= J)[0][0]

            gl_ind[i, 0] = gl_mean_idx[i] - over_J1 + 1

            col = range(gl_mean_idx[i], gl_ind[i, 1])

            over_J2 = numpy.where(abs(A_g_hf[col]) >= J)[0][0]

            gl_ind[i, 1] = gl_mean_idx[i] + over_J2 - 1

    GL = gl_ind
    GL = GL[numpy.where(GL[:, 1] - GL[:, 0] > n_max / 2)[0], :]

    return GL

def split_glides(n_samples, dur, fs_a, GL, min_dur=None):
    """Get start/stop indices of each `dur` length sub-glide for glides in GL

    Args
    ----
    dur: int
        Desired duration of glides
    GL: ndarray, (n, 2)
        Matrix containing the start time (first column) and end time
        (2nd column) of any glides.Times are in seconds.
    min_dur: int, default (bool False)
        Minimum number of seconds for sub-glide. Default value is `False`, which
        makes `min_dur` equal to `dur`, ignoring sub-glides smaller than `dur`.

    Attributes
    ----------
    gl_ind_diff: ndarray, (n,3)
        GL, with additional column of difference between the first two columns

    Returns
    -------
    SGL: ndarray, (n, 2)
        Matrix containing the start time (first column) and end time (2nd
        column) of the generated sub-glides. All glides must have duration equal
        to the given dur value.Times are in seconds.
    """
    import numpy

    # Convert `dur` in seconds to duration in number of samples `ndur`
    ndur = dur * fs_a

    # If minimum duration not passed, set to `min_dur` to skip slices < `dur`
    if not min_dur:
        min_ndur = dur * fs_a
    else:
        min_ndur = min_dur * fs_a

    # `GL` plus column for total duration of glide, seconds
    gl_ind_diff = numpy.vstack((GL.T, GL[:, 1] - GL[:, 0])).T

    # Split all glides in `GL`
    SGL_started = False
    for i in range(len(GL)):
        gl_ndur = gl_ind_diff[i, 2]

        # Split into sub glides if longer than duration
        if abs(gl_ndur) > ndur:

            # Make list of index lengths to start of each sub-glide
            n_sgl = int(gl_ndur // ndur)
            sgl_ndur = numpy.ones(n_sgl) * ndur
            sgl_start = numpy.arange(n_sgl) * (ndur + 1)

            # Add remainder as a sub-glide, skips if `min_ndur` not passed
            if gl_ndur % ndur > min_ndur:
                last_ndur = numpy.floor(gl_ndur % ndur)
                sgl_ndur = numpy.hstack([sgl_ndur, last_ndur])

                last_start = (len(sgl_start) * ndur) + ndur
                sgl_start = numpy.hstack([sgl_start, last_start])

            # Get start and end index positions for each sub-glide
            for k in range(len(sgl_start)):

                # starting at original glide start...
                # sgl_start_ind: add index increments of ndur+1 for next start idx
                next_start_ind = (gl_ind_diff[i, 0] + sgl_start[k]).astype(int)

                # end_glide: add `ndur` to that to get ending idx
                next_end_ind = (next_start_ind + sgl_ndur[k]).astype(int)

                # If first iteration, set equal to first set of indices
                if SGL_started is False:
                    sgl_start_ind = next_start_ind
                    sgl_end_ind = next_end_ind
                    SGL_started = True
                else:
                    # Concatenate 1D arrays together, shape (n,)
                    sgl_start_ind = numpy.hstack((sgl_start_ind, next_start_ind))
                    sgl_end_ind = numpy.hstack((sgl_end_ind, next_end_ind))

    # Stack and transpose indices into shape (n, 2)
    SGL = numpy.vstack((sgl_start_ind, sgl_end_ind)).T

    # Filter out sub-glides that fall outside of sensor data indices
    SGL = SGL[(SGL[:, 0] >= 0) & (SGL[:, 1] < n_samples)]

    # check that all sub-glides have a duration of `ndur` seconds
    sgl_ndur = SGL[:, 1] - SGL[:, 0]

    # If sub-glide `min_ndur` set, make sure all above `min_ndur`, below `ndur`
    if min_dur:
        assert numpy.all((sgl_ndur <= ndur) & (sgl_ndur >= min_ndur))
    # Else make sure all sample number durations equal to `ndur`
    else:
        assert numpy.all(sgl_ndur == ndur)

    # Create `data_sgl_mask`
    data_sgl_mask = numpy.zeros(n_samples, dtype=bool)
    for start, stop in SGL.astype(int):
        data_sgl_mask[start:stop] = True

    return SGL, data_sgl_mask

def calc_glide_des_asc(
    depths,
    pitch_lf,
    roll_lf,
    heading_lf,
    swim_speed,
    dives,
    SGL,
    pitch_lf_deg,
    temperature,
    Dsw,
):
    """Calculate glide ascent and descent summary data

    Args
    ----
    SGL: numpy.ndarray, shape (n,2)
        start and end index positions for sub-glides

    Returns
    -------
    sgls: pandas.DataFrame
        Sub-glide summary information defined by `SGL` start/stop indices

        *Columns*:

        * dive_phase
        * dive_id
        * dive_min_depth
        * dive_max_depth
        * dive_duration
        * start_idx
        * stop_idx
        * duration
        * mean_depth
        * total_depth_change
        * abs_depth_change
        * mean_speed
        * total_speed_change
        * mean_pitch
        * mean_sin_pitch
        * SD_pitch
        * mean_temp
        * mean_swdensity
        * mean_a
        * R2_speed_vs_time
        * SE_speed_vs_time
        * mean_pitch_circ
        * pitch_concentration
        * mean_roll_circ
        * roll_concentration
        * mean_heading_circ
        * heading_concentration

    """
    import scipy.stats
    import numpy
    import pandas

    keys = [
        "dive_phase",
        "dive_id",
        "dive_min_depth",
        "dive_max_depth",
        "dive_duration",
        "start_idx",
        "stop_idx",
        "duration",
        "mean_depth",
        "total_depth_change",
        "abs_depth_change",
        "mean_speed",
        "total_speed_change",
        "mean_pitch",
        "mean_sin_pitch",
        "SD_pitch",
        "mean_temp",
        "mean_swdensity",
        "mean_a",
        "R2_speed_vs_time",
        "SE_speed_vs_time",
        "mean_pitch_circ",
        "pitch_concentration",
        "mean_roll_circ",
        "roll_concentration",
        "mean_heading_circ",
        "heading_concentration",
    ]

    # Create empty pandas dataframe for summary values
    sgls = pandas.DataFrame(index=range(len(SGL)), columns=keys)

    for i in range(len(SGL)):
        start_idx = SGL[i, 0]
        stop_idx = SGL[i, 1]

        # sub-glide start point in seconds
        sgls["start_idx"][i] = start_idx

        # sub-glide end point in seconds
        sgls["stop_idx"][i] = stop_idx

        # sub-glide duration
        sgls["duration"][i] = SGL[i, 1] - SGL[i, 0]

        # mean depth(m)during sub-glide
        sgls["mean_depth"][i] = numpy.mean(depths[start_idx:stop_idx])

        # total depth(m)change during sub-glide
        sgl_depth_diffs = numpy.diff(depths[start_idx:stop_idx])
        sgls["total_depth_change"][i] = numpy.sum(abs(sgl_depth_diffs))

        # depth(m)change from start to end of sub-glide
        sgls["abs_depth_change"][i] = abs(depths[start_idx] - depths[stop_idx])

        # mean swim speed during the sub-glide, only given if pitch>30 degrees
        sgls["mean_speed"][i] = numpy.nanmean(swim_speed[start_idx:stop_idx])

        # total speed change during sub-glide
        sgl_speed_diffs = numpy.diff(swim_speed[start_idx:stop_idx])
        sgls["total_speed_change"][i] = numpy.nansum(abs(sgl_speed_diffs))

        # mean pitch during the sub-glide
        sgls["mean_pitch"][i] = numpy.mean(pitch_lf_deg[start_idx:stop_idx])

        # mean sin pitch during the sub-glide
        sin_pitch = numpy.sin(numpy.mean(pitch_lf_deg[start_idx:stop_idx]))
        sgls["mean_sin_pitch"][i] = sin_pitch

        # SD of pitch during the sub-glide
        # TODO just use original radian array, not deg
        #      make sure "original" is radians ;)
        sd_pitch = numpy.std(pitch_lf_deg[start_idx:stop_idx]) * 180 / numpy.pi
        sgls["SD_pitch"][i] = sd_pitch

        # mean temperature during the sub-glide
        sgls["mean_temp"][i] = numpy.mean(temperature[start_idx:stop_idx])

        # mean seawater density (kg/m^3) during the sub-glide
        sgls["mean_swdensity"][i] = numpy.mean(Dsw[start_idx:stop_idx])

        try:
            # Perform linear regression on sub-glide data subset
            xpoly = numpy.arange(start_idx, stop_idx).astype(int)
            ypoly = swim_speed[start_idx:stop_idx]

            # slope, intercept, r-value, p-value, standard error
            m, c, r, p, std_err = scipy.stats.linregress(xpoly, ypoly)

            # mean acceleration during the sub-glide
            sgls["mean_a"][i] = m

            # R2-value for the regression swim speed vs. time during the
            # sub-glide
            sgls["R2_speed_vs_time"][i] = r ** 2

            # SE of the gradient for the regression swim speed vs. time during
            # the sub-glide
            sgls["SE_speed_vs_time"][i] = std_err

        except Exception:
            # mean acceleration during the sub-glide
            sgls["mean_a"][i] = numpy.nan

            # R2-value for the regression swim speed vs. time during the
            # sub-glide
            sgls["R2_speed_vs_time"][i] = numpy.nan

            # SE of the gradient for the regression swim speed vs. time during
            # the sub-glide
            sgls["SE_speed_vs_time"][i] = numpy.nan

        # TODO this does not take into account the positive depths, flipping
        # descents to ascents
        sgl_signs = numpy.sign(sgl_depth_diffs)
        if all(sgl_signs == -1):
            sgls["dive_phase"][i] = "descent"
        elif all(sgl_signs == 1):
            sgls["dive_phase"][i] = "ascent"
        elif any(sgl_signs == -1) & any(sgl_signs == 1):
            sgls["dive_phase"][i] = "mixed"

        # Get indices of dive in which glide occurred
        dive_ind = numpy.where(
            (dives["start_idx"] < start_idx) & (dives["stop_idx"] > stop_idx)
        )[0]

        # TODO Hack way of pulling the information from first column of dives
        if dive_ind.size == 0:
            dive_inf = pandas.DataFrame.copy(dives.iloc[0])
            dive_inf[:] = numpy.nan
        else:
            dive_inf = dives.iloc[dive_ind].iloc[0]

        # Dive number in which the sub-glide recorded
        sgls["dive_id"][i] = dive_inf["dive_id"]

        # Minimum dive depth (m) of the dive
        sgls["dive_min_depth"][i] = dive_inf["depth_min"]

        # Maximum dive depth (m) of the dive
        sgls["dive_max_depth"][i] = dive_inf["depth_max"]

        # Dive duration (s) of the dive
        sgls["dive_duration"][i] = dive_inf["dive_dur"]

        # Mean pitch(deg) calculated using circular statistics
        pitch_circmean = scipy.stats.circmean(pitch_lf[start_idx:stop_idx])
        sgls["mean_pitch_circ"][i] = pitch_circmean

        # Measure of concentration (r) of pitch during the sub-glide (i.e. 0
        # for random direction, 1 for unidirectional)
        pitch_circvar = scipy.stats.circvar(pitch_lf[start_idx:stop_idx])
        sgls["pitch_concentration"][i] = 1 - pitch_circvar

        # Mean roll (deg) calculated using circular statistics
        roll_circmean = scipy.stats.circmean(roll_lf[start_idx:stop_idx])
        sgls["mean_roll_circ"][i] = roll_circmean

        # Measure of concentration (r) of roll during the sub-glide
        roll_circvar = scipy.stats.circvar(roll_lf[start_idx:stop_idx])
        sgls["roll_concentration"][i] = 1 - roll_circvar

        # Mean heading (deg) calculated using circular statistics
        heading_circmean = scipy.stats.circmean(heading_lf[start_idx:stop_idx])
        sgls["mean_heading_circ"][i] = heading_circmean

        # Measure of concentration (r) of heading during the sub-glide
        heading_circvar = scipy.stats.circvar(heading_lf[start_idx:stop_idx])
        sgls["heading_concentration"][i] = 1 - heading_circvar

    return sgls

def calc_glide_ratios(dives, des, asc, glide_mask, depths, pitch_lf):
    """Calculate summary information on glides during dive ascent/descents

    Args
    ----
    dives: (n,10)
        Numpy record array with summary information of dives in sensor data
    des: ndarray
        Boolean mask of descents over sensor data
    asc: ndarray
        Boolean mask of descents over sensor data
    glid_mask: ndarray
        Boolean mask of glides over sensor data
    depths: ndarray
        Depth values at each sensor sampling
    pitch_lf: ndarray
        Pitch in radians over the low frequency signals of acceleration

    Returns
    -------
    gl_ratio: pandas.DataFrame
        Dataframe of summary information of glides during dive descent/ascents

        *Columns*:

        * des_duration
        * des_gl_duration
        * des_gl_ratio
        * des_mean_pitch
        * des_rate
        * asc_duration
        * asc_gl_duration
        * asc_gl_ratio
        * asc_mean_pitch
        * asc_rate
    """
    import numpy
    import pandas

    # Create empty `pandas.DataFrame` for storing data, init with `nan`s
    cols = [
        "des_duration",
        "des_gl_duration",
        "des_gl_ratio",
        "des_mean_pitch",
        "des_rate",
        "asc_duration",
        "asc_gl_duration",
        "asc_gl_ratio",
        "asc_mean_pitch",
        "asc_rate",
    ]

    gl_ratio = pandas.DataFrame(index=range(len(dives)), columns=cols)

    # For each dive with start/stop indices in `dives`
    for i in range(len(dives)):
        # Get indices for descent and ascent phase of dive `i`
        start_idx = dives["start_idx"][i]
        stop_idx = dives["stop_idx"][i]
        des_ind = numpy.where(des[start_idx:stop_idx])[0]
        asc_ind = numpy.where(asc[start_idx:stop_idx])[0]

        # DESCENT
        # total duration of the descent phase (s)
        gl_ratio["des_duration"][i] = len(des_ind)

        # total glide duration during the descent phase (s)
        des_glides = numpy.where(glide_mask[des_ind])[0]
        gl_ratio["des_gl_duration"][i] = len(des_glides)

        if len(des_ind) == 0:
            gl_ratio["des_gl_ratio"][i] = 0
            gl_ratio["des_rate"][i] = 0
        else:
            # glide ratio during the descent phase
            des_gl_ratio = gl_ratio["des_gl_duration"][i] / len(des_ind)
            gl_ratio["des_gl_ratio"][i] = des_gl_ratio

            # descent rate (m/sample)
            max_depth_des = depths[des_ind].max()
            gl_ratio["des_rate"][i] = max_depth_des / len(des_ind)

        # mean pitch during the descent phase(degrees)
        des_mean_pitch = numpy.mean(numpy.rad2deg(pitch_lf[des_ind]))
        gl_ratio["des_mean_pitch"][i] = des_mean_pitch

        # ASCENT
        # total duration of the ascent phase (s)
        gl_ratio["asc_duration"][i] = len(asc_ind)

        # total glide duration during the ascent phase (s)
        asc_glides = numpy.where(glide_mask[asc_ind])[0]
        gl_ratio["asc_gl_duration"][i] = len(asc_glides)

        if len(asc_ind) == 0:
            gl_ratio["asc_gl_ratio"][i] = 0
            gl_ratio["asc_rate"][i] = 0
        else:
            # glide ratio during the ascent phase
            asc_gl_ratio = gl_ratio["asc_gl_duration"][i] / len(asc_ind)
            gl_ratio["asc_gl_ratio"][i] = asc_gl_ratio

            # ascent rate (m/sample)
            max_depth_asc = depths[asc_ind].max()
            gl_ratio["asc_rate"][i] = max_depth_asc / len(asc_ind)

        # mean pitch during the ascent phase(degrees)
        asc_mean_pitch = numpy.mean(numpy.rad2deg(pitch_lf[asc_ind]))
        gl_ratio["asc_mean_pitch"][i] = asc_mean_pitch

    return gl_ratio


class UniqueGB_model:
	def __init__(self):
		self.res = []
		self.path = False
	def checkm4add1pt(self, m4gbnumber, m5gbnumber, m1_number, m2_number):
		m4gbnumber = str(m4gbnumber)
		m5gbnumber = str(m5gbnumber)
		with open('p2n4.txt') as f: content = f.readlines()
		#print(content[:100])
		newcontent = []
		for i in range(len(content)): newcontent.append(content[i].split(';')[:2])
		total = []
		for i in range(len(newcontent)):
			string2 = ''
			string3 = []

			if newcontent[i][0] == m4gbnumber:
				string2 = newcontent[i][1]
				string3 = string2.split('},')
				list1 = []
				if len(string3) == m1_number:
					for i in range(len(string3)):
						newlist = []
						for j in range(len(string3[0])):
							if string3[i][j] in ['0','1']:
								newlist.append(int(string3[i][j]))
						list1.append(newlist)

					total.append(list1)
		m4gb6 = total
		newcontent = []
		for i in range(len(content)): newcontent.append(content[i].split(';')[:2])
		total = []
		for i in range(len(newcontent)):
			string2 = ''
			string3 = []

			if newcontent[i][0] == m5gbnumber:
				string2 = newcontent[i][1]
				string3 = string2.split('},')
				list1 = []
				if len(string3) == m2_number:
					for i in range(len(string3)):
						newlist = []
						for j in range(len(string3[0])):
							if string3[i][j] in ['0','1']:
								newlist.append(int(string3[i][j]))
						list1.append(newlist)

					total.append(list1)
		m5gb1 = total
		for set1 in m4gb6:
			for set2 in m5gb1:
				flag = 0
				for set11 in set1:
					if set11 in set2:
						flag += 1
				if flag == m1_number:
					self.path = True
					#print( str(m4gbnumber) + ' Gbs for ' + str(m1_number) +' points to ' + str(m5gbnumber) + ' Gbs for ' + str(m2_number) +' points')
					#print( str(m1_number ) + ' points',set1, 'to ' + str(m2_number)+ ' points ', set2)
					self.res.append((set1, set2))
		print('end of the test')

	def checkaddone(self, m4gbnumber, m5gbnumber, m1_number, m2_number):
		self.checkm4add1pt(m4gbnumber, m5gbnumber, m1_number, m2_number)

		if not self.path :
			print(self.path)
			print('There is no add one point path for '+ str(m4gbnumber) +' Gbs ' + str(m1_number) + ' points to ' +  str(m5gbnumber) +' Gbs ' + str(m2_number) + ' points' )
		else:# write result to file:
			print(self.path)
			print( str(m4gbnumber) + ' Gbs for ' + str(m1_number) +' points to ' + str(m5gbnumber) + ' Gbs for ' + str(m2_number) +' points')
			#print( str(m1_number ) + ' points',set1, 'to ' + str(m2_number)+ ' points ', set2)
			file = open(str(m4gbnumber)+'gb'+str(m1_number)+'pts'+str(m5gbnumber)+'gb'+str(m2_number)+'pts'+'.txt','w')
			file.write(str(self.res))
			print('file has been created in your folder')


import sys
sys.path.extend([
    "./",
])
import numpy as np
import os
import optuna
import seaborn as sns
import matplotlib.pyplot as plt
from sklearn.model_selection import train_test_split
from sklearn.tree import DecisionTreeClassifier
import copy
import random

import pandas as pd
from itertools import product
from src.general_utils import util_path
from src.general_utils import util_toy

# For aspect ratio 4:3.
sns.set_context("paper")
sns.set_theme(style="ticks")

if __name__ == '__main__':

    report_dir = './reports/'
    exp_name = 'toy_gans_num_real_samples__100000-grid_size__5-step__2-std_dev__0.05'
    report_dir = os.path.join(report_dir, exp_name)
    util_path.create_dir(report_dir)

    # Parameters for the data
    grid_size = 5
    min_mux =4
    max_mux = min_mux + 2 * (grid_size - 1)
    min_muy = 4
    max_muy = min_muy + 2 * (grid_size - 1)
    num_real_tot = 10000
    num_synth_gan = 500
    mu_real = [(min_mux + 2 * i, min_muy + 2 * j) for i in range(grid_size) for j in range(grid_size)]

    std_real = 0.05
    n_trials = 300

    # Create real datasets.
    data_real_list, data_real = util_toy.generate_data(num_real_tot, mu_real, std_real)
    fig = plt.figure()
    plt.scatter(data_real[:, 0], data_real[:, 1], alpha=0.5, s=1, color='blue')
    plt.grid(True)
    plt.tight_layout()
    fig.savefig(os.path.join(report_dir, 'real_data.png'))
    #plt.show()

    # Load all the toy GANs on the disk.
    epoch_to_load = 'final'
    folders_list =  os.listdir(report_dir)
    data_synthetic_list = []
    for fname in folders_list:
        samples_dir = os.path.join(report_dir, fname)
        # Check if directory.
        if not os.path.isdir(samples_dir):
            continue
        if 'ensemble_search' in samples_dir:
            continue
         # Load final samples.
        samples = np.load(os.path.join(samples_dir, f'generated_samples_epoch_{epoch_to_load}.npy'))
        # Shuffle
        np.random.shuffle(samples)
        # Select the first num_synth_gan samples.
        samples = samples[:num_synth_gan]
        data_synthetic_list.append(samples)

    # Flatten the list.
    data_synthetic = np.vstack(data_synthetic_list)

    # Plot synthetic data.
    fig = plt.figure()
    plt.scatter(data_synthetic[:, 0], data_synthetic[:, 1], alpha=0.5, s=1, color='blue')
    plt.grid(True)
    plt.tight_layout()
    fig.savefig(os.path.join(report_dir, 'synthetic_data.png'))
    #plt.show()
    for idx, samples_synth in enumerate(data_synthetic_list):
        fig = plt.figure()
        plt.scatter(samples_synth[:, 0], samples_synth[:, 1], alpha=0.5, s=1, color='blue')
        plt.grid(True)
        plt.tight_layout()
        fig.savefig(os.path.join(report_dir, f'synthetic_data_{idx}.png'))
        #plt.show()

    n_classes = 10
    seed_class = 42
    class_choice = 'random'  # 'random' or 'kmeans'
    os.path.join(report_dir, f'toy-seed_class__{seed_class}-n_classes__{n_classes}/')
    util_path.create_dir(report_dir)

    # Generate classes.
    if class_choice == 'random':
        np.random.seed(seed_class)
        random.seed(seed_class)
        random_class = np.array([[np.random.uniform(min_mux, max_mux), np.random.uniform(min_muy, max_muy)] for _ in range(n_classes)])
    elif class_choice == 'kmeans':
        from sklearn.cluster import KMeans
        kmeans = KMeans(n_clusters=n_classes, random_state=seed_class, n_init='auto').fit(data_real)
        centroids = kmeans.cluster_centers_
        random_class = copy.deepcopy(centroids)
    else:
        raise NotImplementedError

    # Assign label to each point according to its vicinity to a class.
    # Real.
    distances_real = np.linalg.norm(data_real[:, np.newaxis] - random_class, axis=2)
    labels_real = np.argmin(distances_real, axis=1)

    # Synthetic.
    distances_synth = np.linalg.norm(data_synthetic[:, np.newaxis] - random_class, axis=2)
    labels_synth = np.argmin(distances_synth, axis=1)

    # Visualize the space according to the label.
    fig = plt.figure()
    plt.scatter(data_real[:, 0], data_real[:, 1], c=labels_real, marker='o', s=1, alpha=0.4, label='Points')
    plt.scatter(random_class[:, 0], random_class[:, 1], c=np.unique(labels_real), marker='*', s=50, label='Classes')
    plt.grid(True)
    plt.tight_layout()
    fig.savefig(os.path.join(report_dir, 'real_data_label.png'))
    #plt.show()

    fig = plt.figure()
    plt.scatter(data_synthetic[:, 0], data_synthetic[:, 1], c=labels_synth, marker='o', s=1, alpha=0.4, label='Points')
    plt.scatter(random_class[:, 0], random_class[:, 1], c=np.unique(labels_synth), marker='*', s=50, label='Classes')
    plt.grid(True)
    plt.tight_layout()
    fig.savefig(os.path.join(report_dir, 'synthetic_data_label.png'))
    #plt.show()

    # Create dataset.
    X_real = copy.deepcopy(data_real.reshape(-1, 2))
    y_real = copy.deepcopy(labels_real.reshape(-1, 1))
    X_naive = copy.deepcopy(data_synthetic)
    y_naive = copy.deepcopy(labels_synth.reshape(-1, 1))
    # Create y_gauss.
    y_gauss = []
    for center_idx, samples_real in enumerate(data_real_list):
        y_gauss.append(np.repeat(center_idx, len(samples_real)))
    y_gauss = np.hstack(y_gauss)
    y_gauss = y_gauss.reshape(-1, 1)

    # Concate y_real and y_gauss and save to xlsx.
    y_strat = np.hstack([y_real, y_gauss])
    df_strat = pd.DataFrame(y_strat)
    df_strat['strat'] = df_strat[0].astype(str) + '-' + df_strat[1].astype(str)

    # Split the training set.
    X_train_real, X_test_real, y_train_real, y_test_real = train_test_split(X_real, y_real, test_size=0.2,  stratify=df_strat, random_state=42, shuffle=True)

    # Create a dataframe for the results.
    if os.path.exists(os.path.join(report_dir, 'history.xlsx')):
        history = pd.read_excel(os.path.join(report_dir, 'history.xlsx'))
    else:
        history = pd.DataFrame(columns=['seed_class', 'n_classes', 'n_obj', 'obj_name', 'aggregation', 'exp_name', 'n_gan_ens', 'accuracy', 'precision', 'recall', 'specificity', 'f1-score', 'g-mean',  'rec_modes', 'high_quality_samples'])

    # Real.
    clf = DecisionTreeClassifier()
    clf.fit(X_train_real, y_train_real)
    y_pred = clf.predict(X_test_real)
    clf_acc, clf_prec, clf_rec, clf_spec, clf_f1, clf_gmean = compute_metrics(y_test_real, y_pred, aggregation='mean')
    history = history.append({
        'seed_class': seed_class,
        'n_classes': n_classes,
        'n_obj': 'NA',
        'obj_name': 'NA',
        'aggregation': 'NA',
        'exp_name': 'baseline',
        'n_gan_ens': 'NA',
        'accuracy': clf_acc,
        'precision': clf_prec,
        'recall': clf_rec,
        'specificity': clf_spec,
        'f1-score': clf_f1,
        'g-mean': clf_gmean,
        'rec_modes': 'NA',
        'high_quality_samples': 'NA'
    }, ignore_index=True)

    # Naive.
    clf = DecisionTreeClassifier()
    clf.fit(X_naive, y_naive)
    y_pred = clf.predict(X_test_real)
    clf_acc, clf_prec, clf_rec, clf_spec, clf_f1, clf_gmean = util_toy.compute_metrics(y_test_real, y_pred, aggregation='mean')
    rec_modes = util_toy.recovered_mode(data=X_naive, mu_ref=mu_real, thres= 3 * std_real)
    high_quality_samples = util_toy.frac_points(data=X_naive, mu_ref=mu_real, thres=3 * std_real)
    history = history.append({
        'seed_class': seed_class,
        'n_classes': n_classes,
        'n_obj': 'NA',
        'obj_name': 'NA',
        'aggregation': 'NA',
        'exp_name': 'naive',
        'n_gan_ens': len(data_synthetic_list),
        'accuracy': clf_acc,
        'precision': clf_prec,
        'recall': clf_rec,
        'specificity': clf_spec,
        'f1-score': clf_f1,
        'g-mean': clf_gmean,
        'rec_modes': rec_modes,
        'high_quality_samples': high_quality_samples
    }, ignore_index=True)

    # Single Gaussians.
    mean_acc = []
    mean_precision = []
    mean_recall = []
    mean_specificity = []
    mean_f1_score = []
    mean_gmean = []

    mean_rec_modes = []
    mean_high_quality_samples = []
    for idx in range(len(data_synthetic_list)):
        X = X_naive[idx * num_synth_gan: (idx + 1) * num_synth_gan]
        y = y_naive[idx * num_synth_gan: (idx + 1) * num_synth_gan]
        clf = DecisionTreeClassifier()
        clf.fit(X, y)
        y_pred = clf.predict(X_test_real)
        clf_acc, clf_prec, clf_rec, clf_spec, clf_f1, clf_gmean = util_toy.compute_metrics(y_test_real, y_pred, aggregation='mean')
        mean_acc.append(clf_acc)
        mean_precision.append(clf_prec)
        mean_recall.append(clf_rec)
        mean_specificity.append(clf_spec)
        mean_f1_score.append(clf_f1)
        mean_gmean.append(clf_gmean)
        mean_rec_modes.append(util_toy.recovered_mode(data=X, mu_ref=mu_real, thres=3 * std_real))
        mean_high_quality_samples.append(util_toy.frac_points(data=X, mu_ref=mu_real, thres=3 * std_real))

    history = history.append({
        'seed_class': seed_class,
        'n_classes': n_classes,
        'n_obj': 'NA',
        'obj_name': 'NA',
        'aggregation': 'NA',
        'exp_name': 'mean gan',
        'n_gan_ens': 'NA',
        'accuracy': np.mean(mean_acc),
        'precision': np.mean(mean_precision),
        'recall': np.mean(mean_recall),
        'specificity': np.mean(mean_specificity),
        'f1-score': np.mean(mean_f1_score),
        'g-mean': np.mean(mean_gmean),
        'rec_modes': np.mean(mean_rec_modes),
        'high_quality_samples': np.mean(mean_high_quality_samples)

    }, ignore_index=True)

    # Ensemble search.
    name_obj_list =   ['pr_inter', 'pr_intra', 'dc_inter', 'dc_intra', 'fid_inter', 'fid_intra', 'pr_inter__pr_intra', 'dc_inter__dc_intra', 'fid_inter__fid_intra'] # ['pr_inter', 'pr_intra', 'pr_inter__pr_intra', 'dc_inter', 'dc_intra', 'dc_inter__dc_intra', 'fid_inter', 'fid_intra', 'fid_inter__fid_intra']
    aggregation = ['inter', 'intra', 'ratio', 'NA']

    opts = list(product(name_obj_list, aggregation))

    for name_obj, aggregation in opts:

        n_obj = len(name_obj.split('__'))
        if n_obj > 1:
            obj_first_position = name_obj.split('___')[0]
            assert 'inter' in obj_first_position
            if aggregation == 'NA':
                continue
        else:
            if aggregation != 'NA':
                continue

        directions = []
        for i in range(n_obj):
            if 'pr_inter' in name_obj:
                directions.append('maximize')
            elif 'pr_intra' in name_obj:
                directions.append('minimize')
            elif 'dc_inter' in name_obj:
                directions.append('maximize')
            elif 'dc_intra' in name_obj:
                directions.append('minimize')
            elif 'fid_inter' in name_obj:
                directions.append('minimize')
            elif 'fid_intra' in name_obj:
                directions.append('maximize')
            elif 'size' in name_obj:
                directions.append('minimize')
            else:
                raise NotImplementedError

        ensemble_dir = os.path.join(report_dir,f'ensemble_search-n_obj__{n_obj}-name_obj__{name_obj}-aggregation__{aggregation}-n_trials__{n_trials}')
        util_path.create_dir(ensemble_dir)

        study = optuna.create_study(directions=directions, sampler=optuna.samplers.TPESampler(multivariate=True))

        func = lambda trial: util_toy.obj_optuna(
            trial=trial,
            samples_real=data_real_list,
            samples_naive_list=data_synthetic_list,
            n_obj=n_obj,
            name_obj=name_obj,
        )
        study.optimize(func, n_trials=n_trials)
        df = study.trials_dataframe(attrs=('number', 'value', 'params', 'state'))

        # Drop not complete trials and save to disk.
        df = df[df['state'] == "COMPLETE"]
        df.reset_index(inplace=True, drop=True)
        df.to_excel(os.path.join(ensemble_dir, 'optuna_study.xlsx'), index=False)

        if n_obj==1:
            # Best trials analysis.
            if name_obj == 'pr_inter':
                best_trials = max(study.best_trials, key=lambda t: t.values[0])
            elif name_obj == 'pr_intra':
                best_trials = min(study.best_trials, key=lambda t: t.values[0])
            elif name_obj == 'dc_inter':
                best_trials = max(study.best_trials, key=lambda t: t.values[0])
            elif name_obj == 'dc_intra':
                best_trials = min(study.best_trials, key=lambda t: t.values[0])
            elif name_obj == 'fid_inter':
                best_trials = min(study.best_trials, key=lambda t: t.values[0])
            elif name_obj == 'fid_intra':
                best_trials = max(study.best_trials, key=lambda t: t.values[0])
            else:
                raise NotImplementedError

            with open(os.path.join(ensemble_dir, f"best_trials.txt"), 'w') as f:
                f.write(f"\nNumber: {best_trials.number}")
                f.write(f"\nParams: {best_trials.params}")
                f.write(f"\nValues: {best_trials.values}")

            best_trials_gans = [x for x in best_trials.params if best_trials.params[x] == 1]

            best_trials_gans_indexes = sorted([int(x.split('G')[-1]) for x in best_trials_gans])
            best_trials_gans = [f'G{x}' for x in best_trials_gans_indexes]
            sel_idx = [0] * len(data_synthetic_list)
            for idx in best_trials_gans_indexes:
                sel_idx[idx] = 1

        elif n_obj > 1:
            best_trials = copy.deepcopy(study.best_trials)
            # Selet only best trials.
            best_trials_number = [trial.number for trial in best_trials]
            best_trials_df = df[df['number'].isin(best_trials_number)]

            if aggregation == 'inter':
                best_trials_df['cost'] = copy.deepcopy(best_trials_df['values_0'])
            elif aggregation == 'intra':
                best_trials_df['cost'] = copy.deepcopy(best_trials_df['values_1'])
            elif aggregation == 'ratio':
                best_trials_df['cost'] = best_trials_df['values_0'] / best_trials_df['values_1']

            if 'pr' in name_obj or 'dc' in name_obj:
                best_trials_cost = best_trials_df[best_trials_df['cost'] == best_trials_df['cost'].max()].iloc[0]
            elif 'fid' in name_obj:
                best_trials_cost = best_trials_df[best_trials_df['cost'] == best_trials_df['cost'].min()].iloc[0]
            else:
                raise NotImplementedError

            # Save to disk.
            best_trials_df.reset_index(inplace=True, drop=True)
            best_trials_df.to_excel(os.path.join(ensemble_dir, 'optuna_study_best.xlsx'), index=False)

            best_trials_gans = best_trials_cost[best_trials_cost == 1]
            best_trials_gans = list(best_trials_gans.index)
            # Remove 'number' from the list.
            best_trials_gans = [x for x in best_trials_gans if x != 'number']
            with open(os.path.join(ensemble_dir, f"best_gans.txt"), 'w') as f:
                f.write(f"\n{best_trials_gans}")

            best_trials_gans_indexes = sorted([int(x.split('G')[-1]) for x in best_trials_gans])
            best_trials_gans = [f'G{x}' for x in best_trials_gans_indexes]
            sel_idx = [0] * len(data_synthetic_list)
            for idx in best_trials_gans_indexes:
                sel_idx[idx] = 1
        else:
            raise NotImplementedError

        # Create ensemble dataset.
        data_ensemble_list = [data_synthetic_list[i] for i in range(len(data_synthetic_list)) if sel_idx[i] == 1]
        data_ensemble = np.vstack(data_ensemble_list)

        # Label the data.
        distances_ensemble = np.linalg.norm(data_ensemble[:, np.newaxis] - random_class, axis=2)
        labels_ensemble = np.argmin(distances_ensemble, axis=1)

        # Create the training dataset.
        X_ens = copy.deepcopy(data_ensemble.reshape(-1, 2))
        y_ens = copy.deepcopy(labels_ensemble.reshape(-1, 1))

        # Ensemble.
        clf = DecisionTreeClassifier()
        clf.fit(X_ens, y_ens)
        y_pred = clf.predict(X_test_real)
        clf_acc, clf_prec, clf_rec, clf_spec, clf_f1, clf_gmean = util_toy.compute_metrics(y_test_real, y_pred, aggregation='mean')
        rec_modes = util_toy.recovered_mode(data=X_ens, mu_ref=mu_real, thres=3 * std_real)
        high_quality_samples = util_toy.frac_points(data=X_ens, mu_ref=mu_real, thres=3 * std_real)
        history = history.append({
            'seed_class': seed_class,
            'n_classes': n_classes,
            'n_obj': n_obj,
            'obj_name': name_obj,
            'aggregation': aggregation,
            'exp_name': 'ensemble',
            'n_gan_ens': len(data_ensemble_list),
            'accuracy': clf_acc,
            'precision': clf_prec,
            'recall': clf_rec,
            'specificity': clf_spec,
            'f1-score': clf_f1,
            'g-mean': clf_gmean,
            'rec_modes': rec_modes,
            'high_quality_samples': high_quality_samples
        }, ignore_index=True)

        # Save to the disk.
        history.to_excel(os.path.join(report_dir, 'history.xlsx'), index=False)

    print('May the force be with you.')


import logging
import json

from django.views.generic import TemplateView  # noqa

from heat.api.hotui import hotui_api
from heat.common.region import get_endpoint
from heat.common.region import get_regions

logger = logging.getLogger(__name__)

class IndexView(TemplateView):
    template_name = 'hotui/hotui_base.html'

    def get_context_data(self, **kwargs):
        context = {}
        request = self.request
        region_value = get_regions(request)[0].get('value')
        heat_endpoint = get_endpoint(request, region_value)
        resource_names = [t.resource_type for t in
                          hotui_api.resource_type_list(request, heat_endpoint)]

        context['region_value'] = region_value
        context['stack_endpoint'] = heat_endpoint
        context['resource_names'] = json.dumps(resource_names)

        return context


import unittest

from src.domain.entity.dimension import Dimension
from src.domain.entity.freight import Freight
from src.domain.entity.item import Item

class FreightTestCase(unittest.TestCase):
    def test_deve_calcular_frete_de_um_item(self):
        item = Item(1, 'Instrumentos musicais', 'Guitarra', 1000, Dimension(100, 30, 10), 3)
        freight = Freight()
        freight.add_item(item, 2)
        self.assertEqual(60, freight.get_total())

    def test_deve_calcular_frete_minimo_de_um_item(self):
        item = Item(3, 'Instrumentos musicais', 'Cabo', 30, Dimension(10, 10, 10), 0.9)
        freight = Freight()
        freight.add_item(item, 1)
        self.assertEqual(10, freight.get_total())

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


from datetime import datetime
import json
from urllib.request import Request
from rest_framework.decorators import api_view
from bocr.settings import IMG_BB_URL, IMGBB_API_KEY
from django.core.files.uploadedfile import InMemoryUploadedFile
from .models import Recognition as RecognitionModel
from .serializers.recognitionSerializer import RecognizerSerializer, RecognitionSerializer
from rest_framework.status import HTTP_503_SERVICE_UNAVAILABLE
from rest_framework.exceptions import NotFound
from helper.common.decorators import responsify, jwtAuthGuardExcept
from uploads.models import Uploads
from drf_spectacular.utils import extend_schema
from recognition.serializers.paramsSerializer import RecognitionParamsSerializer, RecognitionImageUploadSerializer
from helper.common.requestSerializer import JWTAuthGuard
from uauth.models import User
from rest_framework import serializers
import requests
import base64

@extend_schema(parameters=[RecognitionParamsSerializer],
               methods=['GET'],
               responses={200: RecognitionSerializer},
               tags=['Recognition'])
@extend_schema(
    parameters=[
        JWTAuthGuard(required=False),
    ],
    request=serializers.ListSerializer(child = RecognitionImageUploadSerializer()),
    methods=['PUT'],
    responses={200: serializers.ListSerializer(child=RecognitionSerializer())},
    tags=['Recognition'])
@api_view(["GET", "PUT"])
@jwtAuthGuardExcept
@responsify
def recognition(request: Request, user=None):
    if request.method.lower() == 'put':
        finalResult = []
        images: list[InMemoryUploadedFile] = request.FILES.getlist('images')
        for img in images:
            data = {
                "image": base64.b64encode(img.read()).decode(),
            }
            response = requests.post(IMG_BB_URL,
                                     params={"key": IMGBB_API_KEY},
                                     data=data)
            response = json.loads(response.content)

            if 'status' in response and response[
                    'status'] == 200 and 'success' in response and response[
                        'success'] == True:
                url = response['data']['image']['url']

                result = RecognizerSerializer(data={"uri": url}).getResult()
                result['cAt'] = datetime.now().timestamp()

                recognitionModel = RecognitionModel.objects.filter(uri=url).first()

                recognitionModel.update_or_create(**result)

                if user:
                    userUploadModel = Uploads.objects.create(
                        uid=User.objects.filter(id = user['id']).first(), recid=recognitionModel)
                    userUploadModel.save()

                finalResult.append(result)
            else:
                return {
                    "status_code": HTTP_503_SERVICE_UNAVAILABLE,
                    "message": response['message']
                }
        return finalResult

    else:
        id = request.GET['id']
        recognition: RecognitionModel = RecognitionModel.objects.filter(
            id=id).first()

        if not recognition:
            raise NotFound('Image not found')
        result = RecognizerSerializer(data={"uri": url}).getResult()
        result = RecognitionModel.objects.filter(id=id).update(
            **result).__dict__()
        return result


# -*- coding: utf-8 -*-
"""
Created on Fri Aug 19 15:31:01 2022

@author: Arman
"""

import pandas as pd
class Cpe_perser:
    def sort_by_vend(self,df): # here df will be a touple consist of (vendor, value)
        return len(df[1])*-1
    def sort_by_prod(self,df): # here df will be a touple consist of (vendor, value)
        return df[1]*-1
    def sort_dict_df(self , dict_ , srt_fn):
        sorted_dict = {}
        for key, value in sorted(dict_.items(), key=srt_fn):
            sorted_dict[key] = value
        return sorted_dict

    def perse_cpe(self,datafm): # assumin cveId as index
        '''
        vendor1{
            ids    product1     product2    producn
            cve1    versions     versions    versions
            cve2    versions     versions    versions
            }

        vendor2{
            ids    product1     product2    producn
            cve1    versions     versions    versions
            }

        '''
        vendors = {}
        for id in datafm.index:
            # print(id)
            # print(datafm[id])
            if(not isinstance(datafm[id],str)):
                continue
            cpe_lst = datafm[id].split('#arman#')
            tempVendors = {}
            for a_cpe in cpe_lst:
                a_cpe_sp = a_cpe.split(':')
                tvendor = a_cpe_sp[3]
                product = a_cpe_sp[4]
                version = a_cpe_sp[5]
                if tvendor not in tempVendors.keys():
                    tempVendors[tvendor] = {"ID":id}
                if product not in tempVendors[tvendor].keys():
                    tempVendors[tvendor][product] = [version]
                elif version not in tempVendors[tvendor][product]:
                    tempVendors[tvendor][product].append(version)
            # print(tempVendors)

            for prod in tempVendors.keys():
                if prod not in vendors.keys():
                    vendors[prod] = pd.DataFrame()

                for key in tempVendors[prod]:
                    if key!="ID":
                        # print(prod)
                        # tempVendors[prod][key+"_len"] = len(tempVendors[prod][key])
                        tempVendors[prod][key] = ",".join(tempVendors[prod][key])
                vendors[prod] = vendors[prod].append(tempVendors[prod],ignore_index = True)

        return self.sort_dict_df(vendors, self.sort_by_vend)

    def get_top_products(self,sort_dic_df,n_vends,n_prods):
        keys = list(sort_dic_df.keys())
        prodlst = []
        ven_lst = []
        prod_lst = []
        for indx in range(n_vends):
            vendor_df = sort_dic_df[keys[indx]]
            vendor_dict = {}
            ven_lst.append(len(vendor_df))
            for col in vendor_df:

                if col=="ID":
                    continue
                ven_prod = keys[indx]+"_"+col
                vendor_dict[ven_prod] = len(vendor_df)-vendor_df[col].isna().sum()
            vendor_dict = self.sort_dict_df(vendor_dict,self.sort_by_prod)

            temp_prod = list(vendor_dict.values())

            keys_prod = list(vendor_dict.keys())
            if len(keys_prod)<n_prods:
                prodlst = prodlst + keys_prod
                prod_lst = prod_lst + temp_prod
            else:
                prodlst = prodlst + keys_prod[:n_prods]
                prod_lst = prod_lst+ temp_prod[:n_prods]

        if len(prodlst) < n_vends * n_prods:
            return (keys[:n_vends],prodlst,ven_lst[:n_vends],prod_lst)
        else:
            return (keys[:n_vends],prodlst[:n_vends * n_prods],ven_lst[:n_vends],prod_lst[:n_vends * n_prods])

#%%

def generate_top_vendor_prod():

    data = pd.read_csv('./data/2016_22m_nvd.csv',index_col="ID")
    cpe_perser = Cpe_perser()
    sort_data = cpe_perser.perse_cpe(data["cpe23Uri"])

    (top_vend,top_prod,ven_value,prod_value) = cpe_perser.get_top_products(sort_data, 50, 5)

    top_v = pd.DataFrame()
    top_v['top_vend'] = top_vend
    top_v['count'] = ven_value
    top_v.to_csv("./data/top_vendors.csv",index=False)
    top_p = pd.DataFrame()
    top_p['top_prod'] = top_prod
    top_p['count'] = prod_value
    top_p.to_csv("./data/top_products.csv",index=False)

    # data saving
    if False:

        import pickle

        with open('top_vendor_prods.pickle', 'wb') as f:
            pickle.dump(sort_data, f)

        vedors_pickle = {}
        with open('../data/output/top_vendor_prods.pickle', 'rb') as f:
            vedors_pickle = pickle.load(f)


def find_lowest_cost_node(costs: dict, processed: set) -> str:
    lowest_cost = float('inf')
    lowest_cost_node = None
    '''
    for node in costs:
        cost = costs[node]
        # 如果当前节点的开销更低且未处理过
        if cost < lowest_cost and node not in processed:
            lowest_cost = cost
            lowest_cost_node = node
    '''
    # 优化循环 这个优化其实应该在这个函数外面做，这样就不用反复创建q了，这里只做演示用途，正确的做法是创建一个空的q之后，添加元素到costs同时添加到q，添加元素到processed时同时从q删除
    q = set(costs.keys())
    q = q - processed

    for node in q:
        cost = costs[node]
        # 如果当前节点的开销更低且未处理过
        if cost < lowest_cost:
            lowest_cost = cost
            lowest_cost_node = node
    return lowest_cost_node

def find_lowest_path(graph: dict, start: str, end):
    parents = dict()
    costs = dict()
    '''
    infinity = float('inf')
    for k, v in graph[start].items():
        costs[k] = v
        parents[k] = start
    parents[end] = None
    costs['fin'] = infinity
    '''
    # 上面的代码优化为如下
    costs[start] = 0
    processed = set()
    while True:
        # 在未处理的节点中找出开销最小的节点
        node = find_lowest_cost_node(costs, processed)
        # 这个while循环在所有节点都被处理过后结束
        if node is None:
            break
        # 如果只在start和end之间查找一条最短路径的话，可以提前返回，因为如果node被加入到processed就代表已经确定了它的最短路径
        if node == end:
            break
        processed.add(node)
        cost = costs[node]
        neighbors = graph[node]
        # 遍历邻居节点
        for n in neighbors.keys():
            new_cost = cost + neighbors[n]
            # 如果经过当前节点前往邻居比之前的costs记录更近
            if n not in costs or costs[n] > new_cost:
                costs[n] = new_cost
                parents[n] = node
    print(costs)
    parent = end
    path = [end]
    while parent != start:
        parent = parents[parent]
        path.append(parent)
    path.reverse()
    print(path)

def test1():
    graph = dict()
    graph['start'] = {'a': 6, 'b': 2}
    graph['a'] = {'fin': 1}
    graph['b'] = {'a': 3, 'fin': 5}
    graph['fin'] = {}
    find_lowest_path(graph, 'start', 'find')

def test1():
    graph = dict()
    graph['start'] = {'a': 6, 'b': 2}
    graph['a'] = {'fin': 1}
    graph['b'] = {'a': 3, 'fin': 5}
    graph['fin'] = {}
    print('------ test1 ------')
    find_lowest_path(graph, 'start', 'fin')

def test_a():
    graph = dict()
    graph['start'] = {'A': 5, 'C': 2}
    graph['A'] = {'B': 4, 'D': 2}
    graph['B'] = {'D': 6, 'fin': 3}
    graph['C'] = {'A': 8, 'D': 7}
    graph['D'] = {'fin': 1}
    graph['fin'] = {}
    print('------ test_a ------')
    find_lowest_path(graph, 'start', 'fin')

def test_b():
    # 带环的图
    graph = dict()
    graph['start'] = {'A': 10}
    graph['A'] = {'B': 20}
    graph['B'] = {'fin': 30, 'C': 1}
    graph['C'] = {'A': 1}
    graph['fin'] = {}
    print('------ test_b ------')
    find_lowest_path(graph, 'start', 'fin')

if __name__ == '__main__':
    test1()
    test_a()
    test_b()