import numpy as np
from itertools import combinations
from tqdm import tqdm
import copy
import optuna

from src.general_utils import util_general

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

def FID(mu0, sigma0, mu1, sigma1):
    """Compute the Frechet Inception Distance."""

    m = np.square(mu1 - mu0).sum()
    s, _ = scipy.linalg.sqrtm(np.dot(sigma1, sigma0), disp=False)  # pylint: disable=no-member
    fid = np.real(m + np.trace(sigma1 + sigma0 - s * 2))
    return fid

def compute_pairwise_distance(data_x, data_y=None):
    if data_y is None:
        data_y = data_x
    dists = sklearn.metrics.pairwise_distances(data_x, data_y, metric='euclidean', n_jobs=8)
    return dists

def get_kth_value(unsorted, k, axis=-1):
    indices = np.argpartition(unsorted, k, axis=axis)[..., :k]
    k_smallests = np.take_along_axis(unsorted, indices, axis=axis)
    kth_values = k_smallests.max(axis=axis)
    return kth_values
def compute_nearest_neighbour_distances(input_features, nearest_k):

    distances = compute_pairwise_distance(input_features)
    radii = get_kth_value(distances, k=nearest_k + 1, axis=-1)
    return radii
def compute_pr(real_features, fake_features, nearest_k=5):

    real_nearest_neighbour_distances = compute_nearest_neighbour_distances(real_features, nearest_k)
    fake_nearest_neighbour_distances = compute_nearest_neighbour_distances(fake_features, nearest_k)
    distance_real_fake = compute_pairwise_distance(real_features, fake_features)

    precision = (distance_real_fake < np.expand_dims(real_nearest_neighbour_distances, axis=1)).any(axis=0).mean()
    recall = (distance_real_fake < np.expand_dims(fake_nearest_neighbour_distances, axis=0)).any(axis=1).mean()

    return precision, recall
def compute_dc(real_features, fake_features, nearest_k=5):

    real_nearest_neighbour_distances = compute_nearest_neighbour_distances(real_features, nearest_k)
    distance_real_fake = compute_pairwise_distance(real_features, fake_features)

    density = (1. / float(nearest_k)) * (distance_real_fake < np.expand_dims(real_nearest_neighbour_distances, axis=1)).sum(axis=0).mean()
    coverage = (distance_real_fake.min(axis=1) < real_nearest_neighbour_distances).mean()

    return density, coverage

def compute_statistics(x):

    """Compute the mean and covariance for the ensemble S."""
    mu_s = np.mean(x, axis=0)
    cov_s = np.cov(x, rowvar=False)

    return mu_s, cov_s

def obj(trial, samples_real, samples_naive_list, n_obj=1, name_obj='fid_inter'):
    """Objective function to minimize for ensemble S."""

    samples_real = np.vstack(samples_real)
    samples_naive = np.vstack(samples_naive_list)

    max_ens = len(samples_naive_list)
    sel_ens = [trial.suggest_int(f'G{x}', 0, 1) for x in range(len(samples_naive_list))]

    n_ens = np.sum(sel_ens)
    if n_ens < 1:
        raise optuna.TrialPruned("Number of selected GANs is less than 2.")
    samples_ens = np.vstack([samples_naive_list[i] for i in range(max_ens) if sel_ens[i] == 1])
    mu_ens, cov_ens = compute_statistics(samples_ens)

    if n_obj == 1:
        if name_obj == 'fid_inter':
            mu_real, cov_real = compute_statistics(samples_real)
            fid = FID(mu_ens, cov_ens, mu_real, cov_real)
            return fid
        elif name_obj == 'fid_intra':
            mu_naive, cov_naive = compute_statistics(samples_naive)
            fid = FID(mu_ens, cov_ens, mu_naive, cov_naive)
            return fid
        elif name_obj == 'pr_inter':
            precision, recall = compute_pr(samples_real, samples_ens, nearest_k=5)
            pr = 2 * (precision * recall) / (precision + recall)
            return pr
        elif name_obj == 'pr_intra':
            precision, recall = compute_pr(samples_naive, samples_ens, nearest_k=5)
            pr = 2 * (precision * recall) / (precision + recall)
            return pr
        elif name_obj == 'dc_inter':
            density, coverage = compute_dc(samples_real, samples_ens, nearest_k=5)
            dc = 2 * (density * coverage) / (density + coverage)
            return dc
        elif name_obj == 'dc_intra':
            density, coverage = compute_dc(samples_naive, samples_ens, nearest_k=5)
            dc = 2 * (density * coverage) / (density + coverage)
            return dc
        else:
            raise NotImplementedError

    elif n_obj == 2:
        if name_obj == 'pr_inter__pr_intra':
            precision_inter, recall_inter = compute_pr(samples_real, samples_ens, nearest_k=5)
            precision_intra, recall_intra = compute_pr(samples_naive, samples_ens, nearest_k=5)
            pr_inter = 2 * (precision_inter * recall_inter) / (precision_inter + recall_inter)
            pr_intra = 2 * (precision_intra * recall_intra) / (precision_intra + recall_intra)
            return pr_inter, pr_intra

        if name_obj == 'dc_inter__dc_intra':
            density_inter, coverage_inter = compute_dc(samples_real, samples_ens, nearest_k=5)
            density_intra, coverage_intra = compute_dc(samples_naive, samples_ens, nearest_k=5)
            dc_inter = 2 * (density_inter * coverage_inter) / (density_inter + coverage_inter)
            dc_intra = 2 * (density_intra * coverage_intra) / (density_intra + coverage_intra)
            return dc_inter, dc_intra

        elif name_obj == 'fid_inter__fid_intra':
            mu_real, cov_real = compute_statistics(samples_real)
            mu_naive, cov_naive = compute_statistics(samples_naive)
            fid_inter = FID(mu_ens, cov_ens, mu_real, cov_real)
            fid_intra = FID(mu_ens, cov_ens, mu_naive, cov_naive)
            return fid_inter, fid_intra
    else:
        raise NotImplementedError


'''Turtle graphics, tuples and importing modules'''
import turtle as t
import random

tim=t.Turtle()
t.colormode(255) #we are making changes in the module 'turtle' not the obj Turtle()
tim.shape("turtle")
tim.color("dark violet") # https://www.tcl.tk/man/tcl8.4/TkCmd/colors.html
#Apple lisa one: first comp with GUI, before that we had terminal like eg:MS-DOS
#turtle relies on Tkinter
# color guide: http://cs111.wellesley.edu/archive/cs111_fall14/public_html/labs/lab12/tkintercolor.html

'''Challenge: Draw a Square'''
# for i in range(0,4):
#     tim.forward(100)
#     tim.right(90)

'''Using aliases for module names'''
# import turtle as t
# from turtle import *
# from turtle import Turtle

'''Challenge: Draw a dashed line'''
# for i in range(0,15):
#     tim.forward(10)
#     tim.penup()
#     tim.forward(10)
#     tim.pendown()

'''Challenge: A nested triangle, square, pentagon,...decagon'''
# colors=['dark sea green','dark green','firebrick','medium slate blue','coral']
# for n in range(3,11):
#     tim.color(random.choice(colors))
#     for i in range(0,n):
#         tim.forward(100)
#         tim.right(360/n)

'''Challenge: Random walk'''
# tim.pensize(10)
tim.speed("fastest")
directions=[0,90,180,270]
turtle_colors = ["black","blue","brown","cyan","darkblue","darkcyan","darkgreen","darkmagenta","darkorange","darkred","darkviolet","gold","green","indigo","lightblue","lightgreen","lime","magenta","maroon","navyblue","olive","orange","pink","purple","red",
"salmon","seagreen","sienna","skyblue","slateblue","springgreen","steelblue","tan","teal","turquoise","violet","white","yellow"
]

def random_color():
    r=random.randint(0,255)
    g=random.randint(0,255)
    b=random.randint(0,255)
    color=(r,g,b)
    return color

# for i in range(0,200):
#     #tim.color(random.choice(turtle_colors))
#     tim.color(random_color())
#     #tim.right(random.randint(0,360))
#     tim.setheading(random.choice(directions))
#     tim.forward(30)

'''Tuple: data type in python (1,2,3) each of the item in tuple are ordered'''
my_tuple=(1,2,3)
#tuple is immutable # use it when you don't want to accidently change items in it
#if you want to change: convert to list then change: list(my_tuple)
#my_tuple[2]=6 #error

'''Challenge: Spirograph'''
def draw_spirograph(gap):
    for i in range(int(360/gap)):
        tim.color(random_color())
        tim.circle(100)
        tim.setheading(tim.heading()+gap)

draw_spirograph(5)

screen=t.Screen()
screen.exitonclick()


import cv2
import numpy as np
import json
import math
import os
from _ctypes import PyObj_FromPtr
import re
class NoIndent(object):
    """ Value wrapper. """
    def __init__(self, value):
        self.value = value

class MyEncoder(json.JSONEncoder):
    FORMAT_SPEC = '@@{}@@'
    regex = re.compile(FORMAT_SPEC.format(r'(\d+)'))

    def __init__(self, **kwargs):
        # Save copy of any keyword argument values needed for use here.
        self.__sort_keys = kwargs.get('sort_keys', None)
        super(MyEncoder, self).__init__(**kwargs)

    def default(self, obj):
        return (self.FORMAT_SPEC.format(id(obj)) if isinstance(obj, NoIndent)
                else super(MyEncoder, self).default(obj))

    def encode(self, obj):
        format_spec = self.FORMAT_SPEC  # Local var to expedite access.
        json_repr = super(MyEncoder, self).encode(obj)  # Default JSON.

        # Replace any marked-up object ids in the JSON repr with the
        # value returned from the json.dumps() of the corresponding
        # wrapped Python object.
        for match in self.regex.finditer(json_repr):
            # see https://stackoverflow.com/a/15012814/355230
            id = int(match.group(1))
            no_indent = PyObj_FromPtr(id)
            json_obj_repr = json.dumps(no_indent.value, sort_keys=self.__sort_keys)

            # Replace the matched id string with json formatted representation
            # of the corresponding Python object.
            json_repr = json_repr.replace(
                            '"{}"'.format(format_spec.format(id)), json_obj_repr)

        return json_repr
class KeyPointGenerator():
    def __init__(self, frame_range = range(0, 2805)):
        self.keypoints = {}
        self.frame_range = frame_range
        self.root = "/home/dzc/Data/zed/"
        self.generate3Dkeypoints()

    def keypoint(self, center, rot):
        x, y = center
        # 右为正方向
        # y = Const.grid_height - y
        x1_ori, x2_ori, x3_ori, x4_ori, x6_ori = x+30, x-30, x-30, x+30, x+20
        y1_ori, y2_ori, y3_ori, y4_ori, y6_ori = y+25, y+25, y-25, y-25, y
        # x1_rot, x2_rot, x3_rot, x4_rot, x6_rot = \
        #     int(math.cos(rot) * (x1_ori - x) - math.sin(rot) *
        #             y1_ori - (Const.grid_height - y) + x), \
        #     int(math.cos(rot) * (x2_ori - x) - math.sin(rot) *
        #             y2_ori - (Const.grid_height - y) + x), \
        #     int(math.cos(rot) * (x3_ori - x) - math.sin(rot) *
        #             y3_ori - (Const.grid_height - y) + x), \
        #     int(math.cos(rot) * (x4_ori - x) - math.sin(rot) *
        #             y4_ori - (Const.grid_height - y) + x), \
        #     int(math.cos(rot) * (x6_ori - x) - math.sin(rot) *
        #             y6_ori - (Const.grid_height - y) + x)
        #
        # y1_rot, y2_rot, y3_rot, y4_rot, y6_rot= \
        #     int(math.sin(rot) * (x1_ori - x) + math.cos(rot) * (y1_ori - (Const.grid_height - y)) + (
        #             Const.grid_height - y)), \
        #     int(math.sin(rot) * (x2_ori - x) + math.cos(rot) * (y2_ori - (Const.grid_height - y)) + (
        #             Const.grid_height - y)), \
        #     int(math.sin(rot) * (x3_ori - x) + math.cos(rot) * (y3_ori - (Const.grid_height - y)) + (
        #             Const.grid_height - y)), \
        #     int(math.sin(rot) * (x4_ori - x) + math.cos(rot) * (y4_ori - (Const.grid_height - y)) + (
        #             Const.grid_height - y)), \
        #     int(math.sin(rot) * (x6_ori - x) + math.cos(rot) * (y6_ori - (Const.grid_height - y)) + (
        #             Const.grid_height - y))

        x1_rot, x2_rot, x3_rot, x4_rot, x6_rot = \
            int(math.cos(rot) * (x1_ori - x) - math.sin(rot) *
                    (y1_ori - y) + x), \
            int(math.cos(rot) * (x2_ori - x) - math.sin(rot) *
                    (y2_ori - y) + x), \
            int(math.cos(rot) * (x3_ori - x) - math.sin(rot) *
                    (y3_ori - y) + x), \
            int(math.cos(rot) * (x4_ori - x) - math.sin(rot) *
                    (y4_ori - y) + x), \
            int(math.cos(rot) * (x6_ori - x) - math.sin(rot) *
                    (y6_ori - y) + x)

        y1_rot, y2_rot, y3_rot, y4_rot, y6_rot= \
            int(math.sin(rot) * (x1_ori - x) + math.cos(rot) * (y1_ori - y) + y), \
            int(math.sin(rot) * (x2_ori - x) + math.cos(rot) * (y2_ori - y) + y), \
            int(math.sin(rot) * (x3_ori - x) + math.cos(rot) * (y3_ori - y) + y), \
            int(math.sin(rot) * (x4_ori - x) + math.cos(rot) * (y4_ori - y) + y), \
            int(math.sin(-rot) * (x6_ori - x) + math.cos(-rot) * (y6_ori - y) + y)

        p1 = [x1_rot, y3_rot, 10]
        p2 = [x2_rot, y4_rot, 10]
        p3 = [x3_rot, y1_rot, 10]
        p4 = [x4_rot, y2_rot, 10]
        p5 = [x, y, 35]
        p6 = [x6_rot, y6_rot, 35]

        p1_ori = [x1_ori, y1_ori, 10]
        p2_ori = [x2_ori, y2_ori, 10]
        p3_ori = [x3_ori, y3_ori, 10]
        p4_ori = [x4_ori, y4_ori, 10]
        p5_ori = [x, y, 37]
        p6_ori = [x6_ori, y6_ori, 37]

        # print([p1, p2, p3, p4, p5, p6])
        return [p1, p2, p3, p4, p5, p6]
        # return [p1_ori, p2_ori, p3_ori, p4_ori, p5_ori, p6_ori]

    def generate3Dkeypoints(self):
        cur = 2535
        for fname in sorted(os.listdir("/home/dzc/Data/zed/annotations/")):
            frame = int(fname.split('.')[0])
            frame_keypoints = []
            with open(os.path.join(self.root, 'annotations', fname)) as json_file:
                cars = [json.load(json_file)][0]
            # if frame != cur:
            #     print(fname)
            #     img = cv2.imread("/home/dzc/Data/zed/bevimgs/%d.jpg" % frame)
            for i, car in enumerate(cars):
                wx = int(car["wx"]) // 10
                wy = int(car["wy"]) // 10
                bev_angle = float(car["angle"])
                if frame == cur:
                    print(frame, wx, wy)
                keypoints = self.keypoint([wx, wy], bev_angle)
                frame_keypoints.append(keypoints)
                # if frame == cur:
                #     print(keypoints)
                    # cv2.circle(img, (wx, wy), radius=1, color = (255, 255, 0), thickness=2)
                    # for pts in keypoints:
                    #     x, y, _ = pts
                    #     cv2.circle(img, (x, y), radius=1, color = (255, 255, 0), thickness=2)
                    # cv2.imwrite("/home/dzc/Desktop/Desktop/CASIA/proj/voxelpose-pytorch/data/MVM3D/script/tmp_bevimgs/%d.jpg" % frame, img)
            self.keypoints[str(frame)] = frame_keypoints

    def generateAnnotationJson(self):
        for i in self.frame_range:
            annotation = open("/home/dzc/Desktop/Desktop/CASIA/proj/voxelpose-pytorch/data/MVM3D/data/MVM3D/zed_coco19/%d.json" % (i), 'w')
            data = {}
            bodies = []
            cars = self.keypoints[str(i)]
            if i == 2535:
                print(cars)
            for car_id, car in enumerate(cars):
                per_body_data = {}
                # per_body_data = json.loads(json.dumps(per_body_data))
                per_body_data["id"] = car_id
                per_body_data["joints19"] = list(np.concatenate((np.array(car).reshape(6, -1), np.ones(shape=(6, 1))), axis=1).reshape(-1))
                # print(car)
                if i == 2535:
                    print(per_body_data)
                bodies.append(per_body_data)
            data["bodies"] = bodies
            annotation.write(json.dumps(data, indent=4, cls=MyEncoder))
            annotation.close()

        pass

    def generateCameraJson(self):
        left_intrinsic_matrix, left_extrinsic_matrix, left_coef_matrix = self.get_intrinsic_extrinsic_matrix("left")
        right_intrinsic_matrix, right_extrinsic_matrix, right_coef_matrix = self.get_intrinsic_extrinsic_matrix("right")

        calibration = open("/home/dzc/Desktop/Desktop/CASIA/proj/voxelpose-pytorch/data/MVM3D/data/MVM3D/calibration_ZED.json", 'w')
        data = {}
        data["calibDataSource"] = "ZED"
        left_camera = {}
        left_camera["name"] = "00_00"
        left_camera["type"] = "daheng"
        left_camera["resolution"] = [1280, 720]
        left_camera["K"] = left_intrinsic_matrix.tolist()
        left_camera["distCoef"] = left_coef_matrix.tolist()
        left_camera["R"] = left_extrinsic_matrix[:, :3].tolist()
        left_camera["t"] = left_extrinsic_matrix[:, -1].tolist()
        left_camera["panel"] = 0
        left_camera["node"] = 0

        right_camera = {}
        right_camera["name"] = "00_01"
        right_camera["type"] = "daheng"
        right_camera["resolution"] = [1280, 720]
        right_camera["K"] = right_intrinsic_matrix.tolist()
        right_camera["distCoef"] = right_coef_matrix.tolist()
        right_camera["R"] = right_extrinsic_matrix[:, :3].tolist()
        right_camera["t"] = right_extrinsic_matrix[:, -1].tolist()
        right_camera["panel"] = 0
        right_camera["node"] = 1

        cameras = [left_camera, right_camera]
        data["cameras"] = cameras

        calibration.write(json.dumps(data, indent=4, cls=MyEncoder, ensure_ascii=False))
        calibration.close()

    def get_intrinsic_extrinsic_matrix(self, cam):
        intrinsic_camera_path = os.path.join("/home/dzc/Data/zed/calibration/intrinsic")
        intrinsic_params_file = cv2.FileStorage(os.path.join(intrinsic_camera_path,
                                                             "intri_"+cam+".xml"),
                                                             flags=cv2.FILE_STORAGE_READ)
        intrinsic_matrix = intrinsic_params_file.getNode('intri_matrix').mat()
        intrinsic_params_file.release()

        coef_camera_path = os.path.join("/home/dzc/Data/zed/calibration/coef")
        coef_params_file = cv2.FileStorage(os.path.join(coef_camera_path,
                                                             "coef_"+cam+".xml"),
                                                             flags=cv2.FILE_STORAGE_READ)
        coef_matrix = coef_params_file.getNode('coef_matrix').mat()
        coef_params_file.release()

        extrinsic_camera_path = os.path.join("/home/dzc/Data/zed/calibration/extrinsic")
        extrinsic_params_file = cv2.FileStorage(os.path.join(extrinsic_camera_path,
                                                             "extri_"+cam+".xml"),
                                                             flags=cv2.FILE_STORAGE_READ)
        extrinsic_matrix = extrinsic_params_file.getNode('extri_matrix').mat()
        extrinsic_params_file.release()
        # print(intrinsic_matrix, extrinsic_matrix)
        for i in range(3):
            extrinsic_matrix[i,3] /= 10
        return intrinsic_matrix, extrinsic_matrix, coef_matrix.reshape(5,)

if __name__ == "__main__":
    generator = KeyPointGenerator(range(0,2805))
    generator.generateAnnotationJson()
    # generator.generateCameraJson()


from random import randint

from src.audio import Player
from src.settings import SETTINGS
from src.stt import Recognizer
from translator import gettext as _
from src.tts import SimpleTTSConfig, SileroTTS

def run_simple_tts_stt_scenario():

    tts = SileroTTS(SETTINGS.tts_model_path)

    tts_config = SimpleTTSConfig(sample_rate=48000)

    is_over = False
    stop_words = (_("exit"), _("finish"), _("let's finish"), _("the end"))
    recognizer = Recognizer()
    exclamations = (_("Great"), _("Super"), _("Nice"), _("Awesome"), _("Fine"))

    with Player() as player:
        data = tts.synthesize_into_bytes(
            text=_("Hello! I am your personal assistant. Let's work? If you want to end, say 'exit'."),
            config=tts_config)
        player.play_data(data, fps=tts_config.sample_rate)

        while not is_over:
            result = recognizer.recognize()

            for stop_word in stop_words:
                if stop_word in result:
                    data = tts.synthesize_into_bytes(
                        text=_("I heard that you want to end our communication. Best wishes!"),
                        config=tts_config)
                    is_over = True
                    player.play_data(data, fps=tts_config.sample_rate)
                    break

            if is_over:
                break

            data = tts.synthesize_into_bytes(
                text="{question}: {result}".format(question=_("Did you say it?"), result=result),
                config=tts_config)

            player.play_data(data, fps=tts_config.sample_rate)

            exclamation = exclamations[randint(0, len(exclamations) - 1)]

            data = tts.synthesize_into_bytes(
                text="{exclamation}! {phrase}".format(exclamation=exclamation,
                                                      phrase=_("Do you want to say me something else?")),
                config=tts_config)

            player.play_data(data, fps=tts_config.sample_rate)

if __name__ == '__main__':
    run_simple_tts_stt_scenario()


import importlib
import logging
import sys
from typing import Optional
from pathlib import Path

# Ensure all modules are reloaded from new files,
# when the addon is removed and a new version is installed in the same session,
# or when Blender's 'Reload Scripts' operator has been called.

PACKAGE_PATH = Path(__file__).parent.parent.parent
PACKAGE_NAME = PACKAGE_PATH.name

def import_module(module):
    importlib.import_module(f"{PACKAGE_NAME}{module}")

def reload_module(module):
    importlib.reload(sys.modules[f"{PACKAGE_NAME}{module}"])

def get_reload_list(sub_dirs):
    reload_list = []

    for sub_dir in sub_dirs:
        files = [p for p in sub_dir.rglob(
            "*.py") if not p.stem.startswith('_')]
        for file in files:
            parents = get_parents(file, [])
            imp_path = ""
            for parent in reversed(parents):
                imp_path += f".{parent}"
            imp_path += f".{file.stem}"
            reload_list.append(imp_path)
    return reload_list

def get_parents(file: Path, parents: list):
    if file.parent.name != PACKAGE_NAME:
        parents.append(file.parent.name)
        get_parents(file.parent, parents)
    return parents

def manage_imports(dirs: Optional[list] = None):
    if dirs is None:
        s = [PACKAGE_PATH / 'src']
    else:
        s = [PACKAGE_PATH / d for d in dirs]

    reload_list = get_reload_list(s)
    for module in reload_list:
        reload = True
        try:
            import_module(module)
        except (ModuleNotFoundError, ImportError) as e:
            reload = False
            logging.error(f"Import {module} failed: {e}")

        if reload:
            reload_module(module)


# -*- coding:UTF-8 -*-

import time
import logging
from Car import Car
from Servo import Servo
from Ultrasound import Ultrasound

logger = logging.getLogger()

def probe(ultrasound, font_servo):
    font_servo.set_servo('2%')
    d1 = ultrasound.test()
    font_servo.set_servo('25%')
    d2 = ultrasound.test()
    font_servo.set_servo('75%')
    d3 = ultrasound.test()
    font_servo.set_servo('98%')
    d4 = ultrasound.test()
    font_servo.set_servo('50%')

    return d1, d2, d3, d4

def main():
    car = Car()
    ultrasound = Ultrasound()
    font_servo = Servo(0)

    time.sleep(2)
    safe_distance = 70
    while True:

        # 1. 是否符合前进条件
        dis = ultrasound.test()
        if dis < safe_distance:
            # 移动
            d1, d2, d3, d4 = probe(ultrasound, font_servo)
            if max(d1, d2, d3, d4) < 100:
                car.back(0.2)
            if d1 == max(d1, d2, d3, d4):
                car.right(0.5)
            if d2 == max(d1, d2, d3, d4):
                car.right(0.25)
            if d3 == max(d1, d2, d3, d4):
                car.left(0.25)
            if d4 == max(d1, d2, d3, d4):
                car.left(0.5)

        time.sleep(1)
        # 向前移动
        # 重新获取距离
        distance = ultrasound.test()
        while distance > safe_distance:
            car.run()
            time.sleep(0.1)
            distance = ultrasound.test()
        else:
            car.stop()

if __name__ == '__main__':
    main()


#!/usr/bin/env python

import warnings
import numpy as np
from scipy.sparse import coo_matrix
import pandas as pd

from schpf.util import split_coo_rows

def load_coo(filename):
    """Load a sparse coo matrix

    Assumes first column (dense row ids) are cells, second column (dense
    column ids) are genes, and third column are nonzero counts. Also assumes
    row and column ids are 0-indexed.

    Parameters
    ----------
    filename : str
        file to load

    Returns
    -------
    coo : coo_matrix
    """
    raw = np.loadtxt(filename, delimiter='\t', dtype=int)
    sparse = coo_matrix((raw[:,2], (raw[:,0],raw[:,1])))
    return sparse

def load_loom(filename):
    """Load data from a loom file

    Parameters
    ----------
    filename: str
        file to load

    Returns
    -------
    coo : coo_matrix
        cell x gene sparse count matrix
    genes : Dataframe
        Dataframe of gene attributes.  Attributes are ordered so
        Accession and Gene are the first columns, if those attributs are
        present
    """
    import loompy
    # load the loom file
    with loompy.connect(filename) as ds:
        loom_genes = pd.DataFrame(dict(ds.ra.items()))
        loom_coo = ds.sparse().T

    # order gene attributes so Accession and Gene are the first two columns,
    # if they are present
    first_cols = []
    for colname in ['Accession', 'Gene']:
        if colname in loom_genes.columns:
            first_cols.append(colname)
    rest_cols = loom_genes.columns.difference(first_cols).tolist()
    loom_genes = loom_genes[first_cols + rest_cols]

    return loom_coo,loom_genes

def load_txt(filename,  ngene_cols=2, verbose=True):
    """Load data from a whitespace delimited txt file

    Parameters
    ----------
    filename : str
        file to load.  Expected to be a gene x cell whitespace-delimited file
        without a header where the first `ngene_cols` are gene identifiers,
        names or other metadata.
    ngene_cols : int, optional (default: 2)
        The number of columns that contain row attributes (ie gene id/names)
    verbose : bool, optional (default: True)
        print progress messages

    Returns
    -------
    coo : coo_matrix
        cell x gene sparse count matrix
    genes : pd.DataFrame
        ngenes x ngene_cols array of gene names/attributes
    """
    assert( ngene_cols > 0 )
    gene_cols = list(range(ngene_cols))

    if filename.endswith('.gz') or filename.endswith('.bz2'):
        msg = '.....'
        msg+= 'WARNING: Input file {} is compressed. '.format(filename)
        msg+= 'It may be faster to manually decompress before loading.'
        print(msg)

        df = pd.read_csv(filename, header=None, memory_map=True,
                delim_whitespace=True)

        genes = df[gene_cols]
        dense = df.drop(columns=gene_cols).values.T
        nz = np.nonzero(dense)
        coo = coo_matrix((dense[nz], nz), shape=dense.shape, dtype=np.int32)
    else:
        genes, rows, cols, values = [], [], [], []

        # load row by row to conserve memory + actually often faster
        with open(filename) as f:
            # for each gene/row
            for g, l in enumerate(f):
                llist = l.split()
                genes.append(llist[:ngene_cols])
                r, c, val = [], [], []

                # for each cell/column
                for cell,v in enumerate(llist[ngene_cols:]):
                    if v != '0':
                        r.append(int(cell))
                        c.append(int(g))
                        val.append(int(v))

                rows.extend(r)
                cols.extend(c)
                values.extend(val)

                if verbose and ((g+1)%10000 == 0) and (g!=0):
                    print('\tloaded {} genes for {} cells'.format(
                        g+1, cell+1))

        ncells, ngenes = len(llist[ngene_cols:]), g+1
        coo = coo_matrix((np.array(values), (np.array(rows),np.array(cols))),
                shape=(ncells,ngenes), dtype=np.int32)
        genes = pd.DataFrame(genes)

    return coo, genes

def min_cells_expressing_mask(counts, min_cells, verbose=True):
    """Get a mask for genes expressed by a minimum number of cells

    Parameters
    ----------
    counts : ndarray or coo_matrix
        A cell x gene coo_matrix of counts
    min_cells: numeric
        the minimum number (if int) or proportion (if float between 0 and 1)
        of cells in which we must observe transcripts of the gene for
        inclusion in the dataset.  If `min_cells` is between 0 and 1, sets
        the threshold to round(min_cells * ncells)
    verbose : bool, default True
        if True, print the number of cells when a numbr between 0 and 1 is given

    Returns
    -------
    passing_mask : ndarray
        boolean array of passing genes

    TODO verbose option + return min_cells
    """
    if min_cells < 1 and min_cells > 0:
        min_cells_frac = min_cells
        min_cells = round(min_cells_frac * counts.shape[0])
        msg = '.....requiring {}% of cells = {} cells observed expressing for'
        msg += ' gene inclusion'
        print(msg.format(100 * min_cells_frac, min_cells))
    return counts.astype(bool).sum(axis=0).A[0,:] >= min_cells

def genelist_mask(candidates, genelist, whitelist=True, split_on_dot=True):
    """Get a mask for genes on or off a list

    Parameters
    ----------
    candidates : pd.Series
        Candidate genes (from matrix)
    genelist : pd.Series
        List of genes to filter against
    whitelist : bool, default True
        Is the gene list a whitelist (True), where only genes on it should
        be kept or a blacklist (False) where all genes on it should be
        excluded
    split_on_dot : bool, default True
        If True, remove part of gene identifier after '.'.  We do this by
        default because ENSEMBL IDs contain version numbers after periods.

    Returns
    -------
    passing_mask : ndarray
        boolean array of passing genes
    """
    if split_on_dot:
        candidates = candidates.str.split('.').str[0]
        genelist = genelist.str.split('.').str[0]

    if whitelist:
        mask = candidates.isin(genelist)
    else:
        mask = ~candidates.isin(genelist)

    return mask.values

def subsample_cell_ixs(choices, nselect, group_ids=None, max_group_frac=0.5):
    """Randomly select cells, potentially accounting for groups

    Parameters
    ----------
    choices : ndarray or int
        Indices of cells to choose from.  If int is give, indices assumend
        to be np.arange(`choices`)
    nselect : int
        number of indices to return
    group_ids : ndarray, optional
        Group ids of cells.  len(`group_ids`) must == `choices` if `choices`
        is an int, and == len(`choices`) otherwise.  If `group_ids` is given,
        selected cells will be distributed approximately evenly over the
        labels under the constraint that at most floor(group_size *
        `max_group_frac`) can be selected from a group.
    max_group_frac : float, optional (default: 0.5)
        If `group_ids` given, the maximum fraction of cells in a group that
        can be selected.

    Returns
    -------
    selected_ix : ndarray
        1d array of selected ids (sorted).
    """
    if isinstance(choices, int):
        choices = np.arange(choices)

    if group_ids is None:
        return np.sort(np.random.choice(choices, nselect, replace=False))
    else:
        assert len(group_ids) == len(choices)

        label, remaining = np.unique(group_ids, return_counts=True)
        constraint = np.floor( remaining * max_group_frac ).astype(int)

        selected, n_remain = [], nselect
        # while unconstrained cells left and more requested
        while np.sum(constraint) > 0 and n_remain > 0:
            # calculate goals given remaining cells to select and
            # unconstrained cells left
            weights = (constraint > 0) / (constraint > 0).sum()
            goal_floor = np.floor(weights * n_remain).astype(int)
            remainder = np.sum(np.ceil(weights * n_remain) - goal_floor
                    ).astype(int)
            goal = goal_floor + np.random.multinomial(remainder, weights)
            # for each group
            for i in range(len(remaining)):
                # if there are unconstrained cells left in the group
                if constraint[i] > 0:
                    my_nchoose = min(goal[i], constraint[i])
                    my_choices = np.setdiff1d(choices[group_ids == label[i]],
                            selected)
                    # select the cells
                    chosen = np.random.choice(my_choices, my_nchoose,
                            replace=False)
                    selected.extend(list(chosen))
                    # update constraint
                    constraint[i] -= my_nchoose
                    n_remain -= my_nchoose
        if n_remain > 0:
            msg = "Could not select {} cells".format(nselect)
            msg += " with given group_ids under constraint max_group_frac"
            msg += "={}. {} cells selected.".format(max_group_frac, n_remain)
            warnings.warn(msg, UserWarning)

        return np.sort(selected)

def split_validation_cells(X, nselect, group_id_file='', max_group_frac=0.5,
        verbose=True):
    """ Split train and validation cells, potentially accounting from groups

    Parameters
    ----------
    X : coo_matrix
        Matrix to select validation cells from
    nselect : int
        Number of cells to select
    group_id_file : str, optional
        File containing group ids.  Should be loadable with np.loadtxt
    max_group_frac : float, optional (default: 0.5)
        If `group_id_file` given, the maximum fraction of cells in a group that
        can be selected.
    verbose : bool, optional (default: True)
        Verbose output

    Returns
    -------
    Xtrain : coo_matrix
        X with validation rows removed
    Xvalidation : coo_matrix
        Selected rows from X
    validation_ix : ndarray
        Indexes of selected rows in the intput matrix `X`
    """
    # load groups
    if group_id_file is not None and len(group_id_file):
        group_ids = np.loadtxt(group_id_file)
    else:
        group_ids = None

    # select cells
    selected_ids = subsample_cell_ixs(X.shape[0], nselect, group_ids,
            max_group_frac)

    # write a message
    if verbose:
        ncells = len(selected_ids)
        msg = '.....{} cells selected'.format(ncells)
        if group_ids is not None:
            msg += ' ~~evenly from groups in {}'.format(group_id_file)
            msg += ' under constraint max_group_frac={}'.format(max_group_frac)
            msg += '\n\tGroup counts:'
            ids, id_counts = np.unique(group_ids[selected_ids],
                    return_counts=True)
            for i, c in zip(ids, id_counts):
                msg += '\n\t\t[{}] {}'.format(i, c)
        print(msg)

    # split cells
    Xvalidation, Xtrain =  split_coo_rows(X, selected_ids)
    return Xtrain, Xvalidation, selected_ids

def load_and_filter(infile, min_cells, whitelist='', blacklist='',
        filter_by_gene_name=False, no_split_on_dot=False, verbose=True):
    """ Composite of loading and filtering intended for use by CLI

    Parameters
    ----------
    infile : str
        Input data. Currently accepts either: (1) a whitespace-delimited gene
        by cell UMI count matrix with 2 leading columns of gene attributes
        (ENSEMBL_ID and GENE_NAME respectively), or (2) a loom file with at
        least one of the row attributes `Accession` or `Gene`, where `Accession`
        is an ENSEMBL id and `Gene` is the name.
    min_cells : float or int
        Minimum number of cells in which we must observe at least one transcript
        of a gene for the gene to pass filtering. If 0 <`min_cells`< 1, sets
        threshold to be `min_cells` * ncells, rounded to the nearest integer.
    whitelist : str, optional
        Tab-delimited file where first column contains ENSEMBL gene ids to
        accept, and second column contains corresponding gene names. If given,
        genes not on the whitelist are filtered from the input matrix.
        Superseded by blacklist. Default None.
    blacklist : str, optional
        Tab-delimited file where first column contains ENSEMBL gene ids to
        exclude, and second column is the corresponding gene name. Only
        performed if file given. Genes on the blacklist are excluded even if
        they are also on the whitelist.
    filter_by_gene_name : bool, optional
        Use gene name rather than ENSEMBL id to filter (with whitelist or
        blacklist).  Useful for datasets where only gene symbols are given.
        Applies to both whitelist and blacklist. Used by default when input
        is a loom file. Default False.
    no_split_on_dot : bool, optional
        Don't split gene symbol or name on period before filtering white and
        blacklist. We do this by default for ENSEMBL ids. Default False.
    verbose : bool, optional
        Print progress messages. Default True

    Returns
    -------
    filtered : ndarray
    genes : pd.DataFrame

    Raises
    ------
    ValueError
    """
    if verbose:
        print('Loading data.....')

    if infile.endswith('.loom'):
        umis, genes = load_loom(infile)
        if 'Accession' in genes.columns:
            candidate_names = genes['Accession']
            genelist_col = 0
        elif 'Gene' in genes.columns:
            candidate_names = genes['Gene']
            genelist_col = 1
        else:
            msg = 'loom files must have at least one of the row '
            msg+= 'attributes: `Gene` or `Accession`.'
            raise ValueError(msg)
    else:
        umis, genes = load_txt(infile)
        genelist_col = 1 if filter_by_gene_name else 0
        candidate_names = genes[genelist_col]
    ncells, ngenes = umis.shape
    if verbose:
        print('.....found {} cells and {} genes'.format(ncells, ngenes))
        print('Generating masks for filtering.....')

    if min_cells < 0:
        raise ValueError('min_cells must be >= 0')
    mask = min_cells_expressing_mask(umis, min_cells)
    if whitelist is not None and len(whitelist):
        whitelist = pd.read_csv(whitelist, delim_whitespace=True, header=None)
        mask &= genelist_mask(candidate_names, whitelist[genelist_col],
                              split_on_dot = ~no_split_on_dot)
    if blacklist is not None and len(blacklist):
        blacklist = pd.read_csv(blacklist, delim_whitespace=True, header=None)
        mask &= genelist_mask(candidate_names, blacklist[genelist_col],
                              whitelist=False, split_on_dot = ~no_split_on_dot)

    if verbose:
        print('Filtering data.....')
    genes = genes.loc[mask]
    filtered = umis.tolil()[:,mask].tocoo() # must convert to apply mask

    return filtered, genes

def load_like(infile, reference, by_gene_name=False,
        no_split_on_dot=False):
    """Load expression matrix, selecting genes and ordering like a reference
    gene list

    Parameters
    ----------
    infile : str
        Input data. Currently accepts either: (1) a whitespace-delimited gene
        by cell UMI count matrix with 2 leading columns of gene attributes
        (ENSEMBL_ID and GENE_NAME respectively), or (2) a loom file with at
        least one of the row attributes `Accession` or `Gene`, where `Accession`
        is an ENSEMBL id and `Gene` is the name.
    reference : str
        Tab-delimited file where first column contains ENSEMBL gene ids and
        second column contains corresponding gene names. Returned array
        will contain exactly these genes, in this order, for counts in cells
        in `infile`
    by_gene_name : bool, optional (Default: False)
        match files by gene name (second 1-indexed column)
    no_split_on_dot : bool, optional
        Don't split gene symbol or name on period before filtering white and
        blacklist. We do this by default for ENSEMBL ids. Default False.

    Returns
    -------
    reordered_coo : coo_matrix
        cell x gene sparse count matrix with genes filtered and ordered like
        reference
    reordered_genes : pd.DataFrame
        ngenes x ngene_cols array of gene names/attributes. Should basically by
        a duplicate of reference

    Raises
    ------
    ValueError : if a gene from the reference is not in infile
    """
    if infile.endswith('.loom'):
        umis, genes = load_loom(infile)
        if 'Accession' in genes.columns:
            candidate_names = genes['Accession']
            genelist_col = 0
        elif 'Gene' in genes.columns:
            candidate_names = genes['Gene']
            genelist_col = 1
        else:
            msg = 'loom files must have at least one of the row '
            msg+= 'attributes: `Gene` or `Accession`.'
            raise ValueError(msg)
    else:
        umis, genes = load_txt(infile)
        genelist_col = 1 if by_gene_name else 0
        candidate_names = genes[genelist_col]
    ncells, ngenes = umis.shape

    # load the reference order
    ref = pd.read_csv(reference, delim_whitespace=True, header=None
            )[genelist_col]
    # select input column and process names unless told not to
    if no_split_on_dot:
        ingenes = candidate_names
    else:
        ref = ref.str.split('.').str[0]
        ingenes = candidate_names.str.split('.').str[0]

    perm = []
    try:
        for g in ref:
            perm.append(np.where(ingenes==g)[0][0])
    except IndexError as e:
        msg = 'Reference gene `{}` in reference `{}` not found in infile `{}`'
        msg = msg.format(g, reference, infile)
        raise ValueError(msg)

    reordered_umis = umis.tocsr()[:,perm].tocoo()
    reordered_genes = genes.loc[perm]
    return reordered_umis, reordered_genes


__author__ = "Adrian Dempwolff (phyghtmap@aldw.de)"
__version__ = "2.23"
__copyright__ = "Copyright (c) 2009-2021 Adrian Dempwolff"
__license__ = "GPLv2+"

import numpy
from matplotlib import __version__ as mplversion
import time
import datetime

from phyghtmap.varint import writableString

def makeElevClassifier(majorDivisor, mediumDivisor):
	"""returns a function taking an elevation and returning a
	category specifying whether it's a major, medium or minor contour.
	"""
	def classify(height):
		if height%majorDivisor==0:
			return "elevation_major"
		elif height%mediumDivisor==0:
			return "elevation_medium"
		else:
			return "elevation_minor"
	return classify

def makeUtcTimestamp():
	return datetime.datetime.utcfromtimestamp(
		time.mktime(time.localtime())).isoformat()+"Z"

class Id(object):
	"""a counter, constructed with the first number to return.

	Count using the getId method.
	"""
	def __init__(self, offset):
		self.curId = offset

	def getId(self):
		self.curId += 1
		return self.curId-1

class Output(object):
	"""An OSM output.

	It is constructed with a destination name, the desired OSM API version,
	the version of phyghtmap as string, an already formatted OSM XML bounds tag
	as output by the hgt.makeBoundsString() function,	an integer representing
	the gzip compressionlevel (or 0 if no gzip compression is desired),
	an elevation classifying function as returned by makeElevClassifier()
	and a hint weather to write timestamps to output or not.
	"""
	def __init__(self, fName, osmVersion, phyghtmapVersion, boundsTag, gzip=0,
		elevClassifier=None, timestamp=False):
		if 0 < gzip < 10:
			import gzip as Gzip
			self.outF = Gzip.open(fName, "wb", gzip)
		else:
			self.outF = open(fName, "wb")
		self.osmVersion = "{0:.1f}".format(osmVersion)
		if osmVersion > 0.5:
			self.versionString = ' version="1"'
		else:
			self.versionString = ""
		if timestamp:
			self.timestampString = ' timestamp="{0:s}"'.format(makeUtcTimestamp())
		else:
			self.timestampString = ""
		self.elevClassifier = elevClassifier
		self.phyghtmapVersion= phyghtmapVersion
		self.boundsTag = boundsTag
		self._writePreamble()

	def _writePreamble(self):
		self.write('<?xml version="1.0" encoding="utf-8"?>\n')
		self.write(
			'<osm version="{0:s}" generator="phyghtmap {1:s}">\n'.format(
			self.osmVersion, self.phyghtmapVersion))
		self.write(self.boundsTag+"\n")

	def done(self):
		self.write("</osm>\n")
		self.outF.close()
		return 0

	def write(self, output):
		self.outF.write(writableString(output))

	def flush(self):
		self.outF.flush()

	def writeWays(self, ways, startWayId):
		IDCounter = Id(startWayId)
		for startNodeId, length, isCycle, elevation in ways:
			IDCounter.curId += 1
			nodeIds = list(range(startNodeId, startNodeId+length))
			if isCycle:
				nodeIds.append(nodeIds[0])
			nodeRefs = ('<nd ref="{:d}"/>\n'*len(nodeIds)).format(*nodeIds)
			self.write('<way id="{0:d}"{1:s}{2:s}>{3:s}'
				'<tag k="ele" v="{4:d}"/>'
				'<tag k="contour" v="elevation"/>'
				'<tag k="contour_ext" v="{5:s}"/>'
				'</way>\n'.format(
					IDCounter.curId-1,
					self.versionString,
					self.timestampString,
					nodeRefs,
					elevation,
					self.elevClassifier(elevation)))

def _makePoints(output, path, IDCounter, versionString, timestampString):
	"""writes OSM representations of the points making up a path to
	output.

	It returns a list of the node ids included in this path.
	"""
	ids, content = [], []
	for lon, lat in path:
		IDCounter.curId += 1
		content.append('<node id="{0:d}" lat="{1:.7f}" lon="{2:.7f}"{3:s}{4:s}/>'.format(
			IDCounter.curId-1,
			lat,
			lon,
			versionString,
			timestampString,)
		)
		ids.append(IDCounter.curId-1)
	if numpy.all(path[0]==path[-1]):  # close contour
		del content[-1]  # remove last node
		del ids[-1]
		ids.append(ids[0])
		IDCounter.curId -= 1
	# output is eventually a pipe, so we must pass a string
	output.write("\n".join(content)+"\n")
	return ids

def _writeContourNodes(output, contourList, elevation, IDCounter,
	versionString, timestampString):
	"""calls _makePoints() to write nodes to <output> and collects information
	about the paths in contourList, namely the node ids for each path, which is
	the returned.
	"""
	ways = []
	for path in contourList:
		nodeRefs = _makePoints(output, path, IDCounter, versionString,
			timestampString)
		if nodeRefs[0] == nodeRefs[-1]:
			ways.append((nodeRefs[0], len(nodeRefs)-1, True, elevation))
		else:
			ways.append((nodeRefs[0], len(nodeRefs), False, elevation))
	return ways

def writeXML(output, contourData, elevations, timestampString, opts):
	"""emits node OSM XML to <output> and collects path information.

	<output> may be anything having a write method.  For now, its used with
	Output instance or an open pipe to the parent process, if running in parallel.

	<contourData> is a phyghtmap.hgt.ContourObject instance, <elevations> a list
	of elevations to generate contour lines for.

	<opts> are the options coming from phyghtmap.
	"""
	IDCounter = Id(opts.startId)
	if opts.osmVersion > 0.5:
		versionString = ' version="1"'
	else:
		versionString = ""
	ways = []
	for elevation in elevations:
		contourList = contourData.trace(elevation)[0]
		if not contourList:
			continue
		ways.extend(_writeContourNodes(output, contourList, elevation,
			IDCounter, versionString, timestampString))
		#output.flush()
	newId = IDCounter.getId()
	return newId, ways


from django.urls import path
from .views import *

urlpatterns = [
    path('', home, name="home"),

    path('iniciarSesion/', iniciarSesion, name="iniciarSesion"),

    path('listaClientes/', listaClientes, name="listaClientes"),

    path('eliminarCliente/<rut>', eliminarCliente, name="eliminarCliente"),

    path('modificarCliente/<rut>', modificarCliente, name="modificarCliente"),

    path('registroProducto/', registroProducto, name="registroProducto"),

    path('listaProductos/', listaProductos, name="listaProductos"),

    path('registroUsuario/', registroUsuario, name="registroUsuario"),

    path('registrarMarca/', registrarMarca, name="registrarMarca"),

    path('listaMarcas/', listaMarcas, name="listaMarcas"),

    path('modificarMarca/<id>/', modificarMarca, name="modificarMarca"),

    path('eliminarMarca/<id>/', eliminarMarca, name="eliminarMarca"),

    path('modificarProducto/<codigo_de_Barras>/', modificarProducto,
    name="modificarProducto"),

    path('eliminarProducto/<codigo_de_Barras>/', eliminarProducto,
    name="eliminarProducto")

]


#!/usr/bin/python3
# coding: utf-8

__all__ = ('backup',
           'chatter_bot',
           'conexao_db',
           'controle_contas',
           'funcoes_uteis',
           'iterar',
           'juros',
           'numeros_primos',
           'numeros_romanos',
           'ordenacao',
           'sequencia_fibonacci',
           )

__author__ = "Paulo C. Silva Jr."


"""
Here we define inputs to the model
"""

import tensorflow as tf
import pandas as pd

def build_vocab(file_name):
    tokens = tf.contrib.lookup.index_table_from_file(
        file_name,
        num_oov_buckets=0,
        default_value=1,
        delimiter='\n',
        name='vocab'
    )

    return tokens

def vectorize(string, vocab, seq_len):
    splitted = tf.string_split([string]).values
    vectorized = vocab.lookup(splitted)
    vectorized = vectorized[:seq_len]
    return vectorized

def input_fn(data_path, params, train_time=True):

    data = pd.read_csv(data_path)
    dataset = tf.data.Dataset.from_tensor_slices(({'tokens': data['text'].values}, data['labels'].values))

    vocab = build_vocab(params['vocab_path'])
    pad_value = vocab.lookup(tf.constant('<PAD>'))
    fake_padding = tf.constant(-1, dtype=tf.int64)

    if train_time:
        dataset = dataset.shuffle(params['train_size'])
        dataset = dataset.repeat(params['num_epochs'])

    dataset = dataset.map(lambda feats, labs: (vectorize(feats['tokens'], vocab, params['seq_len']), labs))

    padded_shapes = (tf.TensorShape([params['seq_len']]), tf.TensorShape([]))
    padding_values = (pad_value, fake_padding)

    dataset = dataset.padded_batch(
        batch_size=params['batch_size'],
        padded_shapes=padded_shapes,
        padding_values=padding_values
    )

    dataset = dataset.map(lambda x, y: ({'x': x, 'y': y}, y))
    dataset = dataset.prefetch(buffer_size=2)

    return dataset


from django.urls import path
from users import views
from rest_framework_simplejwt.views import (
    TokenRefreshView,
)

urlpatterns = [
    path("athnt/", views.AthntCodeCreateView.as_view(), name="athnt_code_create_view"),
    path("signup/", views.SignupView.as_view(), name="signup_view"),
    path("login/", views.LoginView.as_view(), name="login_view"),
    path("<int:user_id>/", views.FollowView.as_view(), name="follow_view"),
    path("api/token/refresh/", TokenRefreshView.as_view(), name="token_refresh"),
    path("mypage/<int:user_id>/", views.MyPageView.as_view(), name="my_page_view"),
]


# !/usr/bin/env python
# -*- coding:utf-8 -*-
# Author:pylarva
# bolg:www.lichengbing.com

import os
import sys

base_dir = os.path.dirname(os.path.dirname(os.path.abspath(__file__)))
sys.path.append(base_dir)

from src import db_conn, views

"""
堡垒机管理员一键初始化数据库函数
"""
if __name__ == '__main__':
    try:
        # 删除表
        db_conn.drop_db()
        # 新建表
        db_conn.init_db()
        # 添加数据
        views.run()
        print('初始化数据库成功...')
        print('新建数据成功...')
    except Exception:
        print('YML配置文件中有错误...')


import requests
import json

#r = requests.get('https://api.github.com/events')
#r.raise_for_status()
#print(r.text)

jar = requests.cookies.RequestsCookieJar()
jar.set('name', 'kim', domain='httpbin.org', path='/cookies')

#r = requests.get('http://httpbin.org/cookies', cookies=jar)
#r.raise_for_status()
#print(r.text)

#r = requests.get('https://github.com', timeout=3)
#print(r.text)

#r = requests.post('http://httpbin.org/post', data={'name':'kim'}, cookies=jar)
#print(r.text)

payload1 = {'key1':'value1', 'key2':'value2'}
payload2 = {'status':'hungry'}

r = requests.post('http://httpbin.org/post', data=payload1)  # form
r = requests.post('http://httpbin.org/post', data=json.dumps(payload1))  # json


from typing import List

def product_sum(input_list: List[int], multiplier: int = 1) -> int:
    """
    Calculate the result by multiply the sum of list with multiplier
    Space Complexity: O(D)
    Time Complexity: O(n)
    :param input_list:
    :param multiplier:
    :return: int
    """
    sum_ = 0
    for n in input_list:
        if isinstance(n, list):
            sum_ += product_sum(n, multiplier + 1)
        else:
            sum_ += n
    return sum_ * multiplier

if __name__ == '__main__':
    print(product_sum([1, 2, 3]))


from setuptools import setup, find_packages

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

PKGS = find_packages()
PKGS.remove('test')

setup(
    name='xviz',
    version='0.1.1',
    description='Python implementation of XVIZ protocol',
    author='Yuanxin Zhong',
    author_email='cmpute@gmail.com',
    url="https://github.com/cmpute/xviz.py",
    long_description=DESCR,
    long_description_content_type='text/markdown',
    packages=PKGS,
    install_requires=['numpy', 'easydict', 'protobuf', 'websockets'],
    classifiers=[
        'Programming Language :: Python :: 3',
        'Operating System :: OS Independent',
        'Development Status :: 2 - Pre-Alpha',
        "Topic :: Scientific/Engineering :: Visualization",
        "Topic :: Database :: Front-Ends",
        "Environment :: Web Environment",
    ],
)


# -*- coding: UTF-8 -*-

from output_class import OutputClass
from google.appengine.ext import db
from comments.comments import Comments
from db_entities.forum.db_forum_category import DBForumCategory
from tools.multipage import Multipage

class forum_category(OutputClass):

    url_handler = '/forum/category/?'

    def get(self):
        self.checkSession(self.request.headers.get('Cookie'), False)
        category = 0
        cat = int(self.request.get('cat')) if self.request.get('cat') else 0#int(self.get_url_part(1))

        cat_name = "Not set"

        try:
            category = DBForumCategory.get_by_id(cat)
            cat_name = category.name.encode("utf-8")
        except:
            self.showMessage("Категория не найдена!")
            return

        _topics = []
        comments = Comments()
        #page = self.request.get(')

        try:
            tops = db.GqlQuery("SELECT * FROM DBForumTopic where category = :category", category = category.key())
            for top in tops:
                #last_message = comments.getLastComment([top.key()])
                _topics.append({'id':int(top.key().id()), 'name':top.name.encode("utf-8"),
                                #'answers' : comments.getCommentsCount([top.key()]) - 1,
                                'answers' : top.comments_count if top.comments_count else 0,
                            'last_message' : top.last_comment,
                            'last_message_date' : top.last_comment.date if top.last_comment else top.date })
        except: pass
        _topics.sort(key=lambda k: k['last_message_date'], reverse=True)
        multipage = Multipage(self.request.get('page'), _topics, '/forum/category&cat=' + str(cat))
        self.insertTemplate('forum/category.html', {
                                                    'tops': multipage.getItems(),
                                                    'pages': multipage.getPages(),
                                                    'cat_name':cat_name,
                                                    'cat_id':cat
                                                    })
        self.drawPage("Форум :: Просмотр категории "+cat_name)


"""
This scripts written for advent of code 2021.

level6 part2
"""
import datetime

def read_file(file_name):
    """Import data to code."""
    with open(file_name, 'r', encoding='utf-8') as file:
        lines = list(map(int, file.readline().split(',')))
        return lines

def get_population(population, target_day):
    """Calculate number of individual at target time."""
    data = {}
    day = 0
    final_population = 0
    for key in range(9):
        data[key] = 0
    for fish in population:
        data[fish] += 1
    print(data)
    while day < target_day:
        zeroes = data[0]
        data[0] = 0
        for index in range(1, len(data)):
            data[index - 1] += data[index]
            data[index] = 0
        data[6] += zeroes
        data[8] += zeroes
        # print(data)
        day += 1
    for _key in data:
        final_population += data[key]
    return final_population

def main():
    """Logic of code."""
    start_time = datetime.datetime.now()
    print(f'The App startted at : {start_time}')
    initial_state = read_file("advent_of_code_l6.txt")
    final_population = get_population(initial_state, 256)
    print(f'Final population is :{final_population}')
    end_time = datetime.datetime.now()
    print(f'The App ended at :{end_time}')
    print(f'Total time of execution is : {end_time - start_time}')

if __name__ == "__main__":
    main()


#!/usr/bin/python
# coding:utf-8
# @software: PyCharm
# @file: 快速排序.py
# @time: 2019/11/29

"""
快速排序（英语：Quicksort），又称划分交换排序（partition-exchange sort），
通过一趟排序将要排序的数据分割成独立的两部分，
其中一部分的所有数据都比另外一部分的所有数据都要小，
然后再按此方法对这两部分数据分别进行快速排序，整个排序过程可以递归进行，
以此达到整个数据变成有序序列。
————————————————
原文链接：https://blog.csdn.net/u014745194/article/details/72783479

分析步骤：
步骤为：
1、从数列中挑出一个元素，称为”基准”（pivot）。

2、重新排序数列，所有元素比基准值小的摆放在基准前面，
    所有元素比基准值大的摆在基准的后面（相同的数可以到任一边）。
    在这个分区结束之后，该基准就处于数列的中间位置。这个称为分区（partition）操作。

3、递归地（recursive）把小于基准值元素的子数列和大于基准值元素的子数列排序。
递归的最底部情形，是数列的大小是零或一，也就是永远都已经被排序好了。
虽然一直递归下去，但是这个算法总会结束，因为在每次的迭代（iteration）中，
它至少会把一个元素摆到它最后的位置去。
"""

def quick_sort(alist, start, end):
    """快速排序"""
    if start >= end:
        return

    # 基准
    mid = alist[start]

    # 左边的游标
    left = start
    # 右边游标
    right = end

    while left < right:
        while left < right and alist[right] >= mid:
            # 右边的游标移动，左边的游标不动
            right -= 1

        alist[left] = alist[right]

        while left < right and alist[left] < mid:
            # 左边的游标移动，右边的游标不动
            left += 1

        alist[right] = alist[left]

    # 退出循环后，left 与 right 重合，即相等
    alist[left] = mid
    # 递归的方式，排左边的序列
    quick_sort(alist, start, left - 1)
    # 递归方式排右边的序列
    quick_sort(alist, left + 1, end)

if __name__ == "__main__":
    alist = [54, 26, 93, 17, 77, 31, 44, 55, 20]
    print(f"原列表为：{alist}")
    quick_sort(alist, 0, len(alist) - 1)
    print(f"新列表为：{alist}")


from game_name.globals import *

from random import randint

from rogue.colors import *
from rogue.sprite import Sprite

from game_name.block import *
from game_name.tools import *

from game_name.menu import Menu, DialogBox
from game_name.land import *
from game_name.bunny import Bunny
from game_name.player import Player
from game_name.entity import *
from game_name.crosshair import Crosshair

for x in range(-250, 250):
    for y in range(-250, 250):
        if not randint(0, 45):
            if not randint(0, 10):
                if not randint(0, 1):
                    screen.append(Bunny(x+randint(-5, 5), y+randint(-5, 5)))
                screen.append(Flower(x, y))
            else:
                screen.append(Grass(x, y))

        if not randint(0, 10000):
            if not randint(0, 3):
                screen.append(Pickaxe(x+5, y+5))

            for x_ in range(0, 10):
                screen.append(Stone(x+x_, y))

            for y_ in range(0, 10):
                screen.append(Stone(x, y+y_))
                screen.append(Stone(x+9, y+y_))

player = Player(0, 0)
screen.append(player)

crosshair = Crosshair()
screen.append(crosshair)

info.start()
info.addText('You awake')
info.addText('in a field')

inventory.start()
h_ = Hand()
h_.hide()
inventory.addOption(h_.name, h_)

def main():
    n = 0
    focus(screen, player)
    while True:

        screen.update()

        key = screen.getKey()

        crosshair.update(key)
        if key in ['w', 'a', 's', 'd', ' ', '\n']:
            player.update(screen, key)

            for sprite in screen:
                if isinstance(sprite, Bunny):
                    sprite.update(screen)

        if key == u"\u0008":
            screen.exit()

        if key in ['[', ']']:
            inventory.update(key)
            info.addSentence('You equip '+inventory.getSelected().name)

        focus(screen, player)

if __name__ == "__main__":
    main()


def solution(weights):
    answer = 0
    visit = [-1 for _ in range(4001)]
    same = [-1 for _ in range(1001)]
    for i in range(len(weights)):
        same[weights[i]] += 1
        answer += same[weights[i]]
        sameCnt = same[weights[i]]

        for j in range(2, 5):
            visit[weights[i] * j] += 1
            answer += (visit[weights[i] * j] - sameCnt)
    return answer


from sqlalchemy import Column, Integer, String, Boolean, Date, Enum

from db.base_class import Base
from db.models.enumeration.service_type import ServiceType

class Service(Base):
    id = Column(Integer, primary_key=True, index=True)
    name = Column(String, nullable=False)
    date = Column(Date)
    is_done = Column(Boolean)
    service_type = Column(Enum(ServiceType))
    price = Column(Integer)


# -*- coding: utf-8 -*-
__author__ = 'Nikitin'
from model.data import Data
import matplotlib.pyplot as plt
from matplotlib.finance import candlestick2_ohlc,candlestick_ohlc
from matplotlib.dates import date2num

class Plotter:
    def __init__(self, data=Data()):
        self.data=data

        print('Запускаем плоттер')
        self._vp_config()
        self._plot()
        plt.show()

    def _vp_config(self):
        f = plt.figure()
        plt.subplots_adjust(hspace=0.001,left=0.05,right=0.99, top=0.96, bottom=0.05)
        num_subplot=len(self.data.viewports)
        self.axises=list()

        ax1 = plt.subplot(num_subplot*100+11)
        self.axises.append(ax1)

        for i in range(num_subplot-1):
            ax = plt.subplot(num_subplot*100+i+12, sharex=ax1)
            self.axises.append(ax)

    def _plot(self):

        self._plot_candles()
        self._plot_graphs()
        self._plot_dots()

        # for item in (self.data.viewports):
        #     print(item.keys())
        # print(self.data.candles)
        # print(self.data.graphs)
        # print(self.data.dots)

    def _plot_candles(self):
        for candle_name in self.data.candles:
            # print(candle_name)
            candles=self.data.candles[candle_name]
            tohlc_list=list()
            for time in sorted(candles):
                t=list()
                t.append(date2num(time))
                t.extend(candles[time])
                tohlc_list.append(t)
                # print(time,candles[time],t)

            vp=self._find_vp(candle_name)
            # print(vp)
            # print(tohlc_list)
            candlestick_ohlc(self.axises[vp],tohlc_list,width=60.0*10/(24.0*3600.0)*0.8)#,alpha=a,colorup=cu,colordown=cd)

    def _plot_graphs(self):
        for graph_name in self.data.graphs:
            # print(graph_name)
            graph=self.data.graphs[graph_name]
            times=list()
            dates=list()
            for time in sorted(graph):
                # print(time,graph[time])
                times.append(time)
                dates.append(graph[time])

            vp=self._find_vp(graph_name)
            self.axises[vp].plot_date(times,dates,ls="-",marker=None)

    def _plot_dots(self):
        for dots_name in self.data.dots:
            # print(dots_name)
            dots=self.data.dots[dots_name]
            times=list()
            dates=list()
            for time in sorted(dots):
                # print(time,dots[time])
                times.append(time)
                dates.append(dots[time])

            vp=self._find_vp(dots_name)
            options=self.data.viewports[vp][dots_name]
            # print(options)
            self.axises[vp].plot_date(times,dates,ls="None",marker=options.get('marker','o'),markersize=options.get('markersize',10))

    def _find_vp(self,name):
        for i in range(len(self.data.viewports)):
            if name in self.data.viewports[i]:
                return i

        raise RuntimeError("Что-то случилось в процедуре Plotter._find_vp")

if __name__ == "__main__":
    pass


import numpy as np
import pandas as pd
import pyfaidx
import argparse

def parse_args():
    parser = argparse.ArgumentParser(
        description="""Runs a number of spaced seeds against specified genomes
                    to determine if seed entropy affects specificity.""")
    parser.add_argument("-g", "--genomes", type=str, help="Paths to the genomes, comma delimited", required=True)
    parser.add_argument("-n", "--num-seeds", type=int, help="Number of spaced seeds to sample", required=True)
    parser.add_argument("-s", "--seeds", type=str,
                        help="Seeds tsv file, output of make_seeds.py and markov_process_seeds.py", required=True)
    # parser.add_argument("-o", "--output", type=str, help="Name of output .tsv file", required=True)
    args = parser.parse_args()
    return args

def sample_seeds(seeds, entropies, sample_size):
    # select_indexes = np.logspace(0, math.log10(len(entropies)-1), sample_size).astype(int)
    select_indexes = np.linspace(0, len(entropies)-1, sample_size, dtype=int)
    sorted_indexes = np.argsort(entropies)
    indexes = np.sort(sorted_indexes[select_indexes])
    return np.array(seeds)[indexes]

def reverse_complement(numpy_sequence):
    complement = {b'A': b'T',
                  b'T': b'A',
                  b'C': b'G',
                  b'G': b'C'}
    rev_seq = np.flipud(numpy_sequence)
    return np.vectorize(lambda nt: complement[nt])(rev_seq)

def determine_word_frequencies(genome_sequence, spaced_seed):
    spaced_seed = str(spaced_seed)
    k = len(spaced_seed)
    weighted_indexes = []
    kmers = {}
    for i in range(k):
        if spaced_seed[i] == '1':
            weighted_indexes.append(i)
    w = len(weighted_indexes)
    for i in range(len(genome_sequence) - k + 1):
        word = np.empty(w, 'S1')
        for j, weighted_index in zip(range(w), weighted_indexes):
            word[j] = genome_sequence[i:i+k][weighted_index]
        word_str = word.tostring()
        reverse_word_str = reverse_complement(word).tostring()
        canonical_word = min(word_str, reverse_word_str)
        kmers[canonical_word] = False if canonical_word in kmers else True
        # kmers[canonical_word] = kmers[canonical_word] + [i] if canonical_word in kmers else [i]
    return kmers

def determine_unique_frames(kmers, num_frames):
    frames_count = np.zeros(num_frames, dtype=np.bool)
    for frames in kmers.values():
        frames_count[frames] = True if len(frames) == 1 else False

    return frames_count

def determine_word_uniqueness(words_dict):
    np_values = np.array(list(words_dict.values()))
    # unique_items_index = np_values == True
    p_uniqueness = len(np_values[np_values]) / len(np_values)
    return p_uniqueness

def main():
    args = parse_args()
    genome = str(pyfaidx.Fasta(args.genomes)[0][0:])
    num_seeds = args.num_seeds
    data = pd.read_csv(args.seeds, sep='\t', index_col=0)
    seeds = data.index.values
    seed_sample = sample_seeds(seeds, data['3bit'].values, num_seeds)
    determine_words_vect = np.vectorize(determine_word_frequencies, excluded=['genome_sequence'])
    kmers_list = determine_words_vect(genome, seed_sample)
    deter_uniqueness_vect = np.vectorize(determine_word_uniqueness)
    uniquenesses = deter_uniqueness_vect(kmers_list)
    print("Seed", "Uniqueness", "2bit", sep='\t')
    for seed, uniqueness in zip(seed_sample, uniquenesses):
        print(seed, uniqueness, sep='\t')

if __name__ == "__main__":
    main()


'''
2
<<BP<A>>Cd-
ThIsIsS3Cr3t
ABC<<DE>F<--
'''
# - : 백스페이스, <, >
T = int(input())
for tc in range(T):
    data = list(input())
    L = len(data)
    word = []
    cursor = []

    for i in range(L):
        if data[i] == '<':
            if len(word) :
                cursor.append(word.pop())

        elif data[i] == '>':
            if len(cursor) :
                word.append(cursor.pop())

        elif data[i] == '-':
            if len(word):
                word.pop()
        else:       # 단어일때
            word.append(data[i])

    cursor.reverse()

    print(*word+cursor, sep="")


import logging

#
# Uses standard Python logging service to
# manage logging of the bot
#

def getlogger(lgfileName):
    # logger
    logger = logging.getLogger(__name__)
    logger.setLevel(logging.INFO)
    ch = logging.FileHandler(lgfileName)
    ch.setLevel(logging.INFO)
    # create formatter
    formatter = logging.Formatter('%(asctime)s - %(module)s - %(levelname)s - %(message)s')
    # add formatter to ch
    ch.setFormatter(formatter)
    # add ch to logger
    logger.addHandler(ch)
    # create console handler and set level to debug
    stream_ch = logging.StreamHandler()
    stream_ch.setLevel(logging.INFO)
    stream_ch.setFormatter(formatter)
    logger.addHandler(stream_ch)
    return logger


import sys#for taking input
import math#for taking log

class LH:

    def __init__(self):
        """
        Initialise the linear hash data structure
        """

        self.hash=[[],[]]#hash table
        self.n=2#number of buckets
        self.i=1#number of bits to check
        self.limit=2#records in each bucket
        self.splitptr=0#which bucket to split

    def findlh(self,val):
        """
        Return true if val present in LH
        """

        bucket=self.findbucket(val)

        for i in self.hash[bucket]:
            if(i==val):
                return True

        return False

    def insertlh(self,val):
        """
        Insert into LH
        """

        #find pos to insert
        bucket=self.findbucket(val)

        #insert into LH
        self.hash[bucket].append(val)

        #if overflow then split
        if(len(self.hash[bucket])>self.limit):

            self.update()
            self.splitbucket(self.splitptr)
            self.splitptr+=1

        #update split ptr
        if(self.i==math.log(self.n,2)):
            self.splitptr=0

    def splitbucket(self,ptr):
        """
        Rearranges value in the bucket
        """

        temp=self.hash[ptr]
        self.hash[ptr]=[]
        for i in range(len(temp)):
            val=temp[i]
            bucket=val%(2**self.i)
            self.hash[bucket].append(val)

    def update(self):
        """
        Updates values after new bucket is added
        """

        self.hash.append([])
        self.n+=1
        self.i=math.log(self.n,2)
        self.i=math.ceil(self.i)

    def findbucket(self,val):
        """
        Returns bucket to insert/search
        """

        bucket=val%(2**self.i)
        #check if can fit into LH
        if(bucket>=self.n):
            bucket=bucket-(2**(self.i-1))

        return bucket

if __name__=="__main__":
    """
    Runner function
    """

    #if arguments not entered correctly
    if(len(sys.argv)!=2):
        print("USAGE:- python3 q2.py input_file.txt")
        exit(0)

    #create LH list
    lh=LH()

    #initialise query list
    query=[]

    file=sys.argv[1]
    with open(file,'r') as f:
        for line in f:
            query.append(int(line.strip()))

    #process each query
    for q in query:
        if not lh.findlh(q):
            print(q)
            lh.insertlh(q)

    # print(lh.hash)


#!/usr/bin/python3
""" API definition """

from models import storage
from api.v1.views import app_views
from flask import Flask, Blueprint, jsonify, make_response
from os import getenv
from flask_cors import CORS

app = Flask(__name__)
app.register_blueprint(app_views)
cors = CORS(app, resources={"/*": {"origins": "0.0.0.0"}})

@app.teardown_appcontext
def teardown_appcontext(code):
    """ Closes storage """
    storage.close()

@app.errorhandler(404)
def code_404(error):
    """
       Ref: http://flask.pocoo.org/docs/0.12/patterns/errorpages/
       https://kite.com/docs/python;flask.helpers.make_response
    """
    return jsonify({"error": "Not found"}), 404

if __name__ == "__main__":
    host = getenv("HBNB_API_HOST", "0.0.0.0")
    port = int(getenv("HBNB_API_PORT", "5000"))
    app.run(host, port)


# 定义类
class Demo:
    # 定义构造方法
    def __init__(self, obj):
        self.data = obj[:]
    # 重载索引、分片赋值运算方法
    def __setitem__(self, index, value):
        self.data[index] = value
# 创建实例对象，并用列表初始化
x = Demo([1,2,3,4,5])
# 显示对象属性中的列表
print(x.data)
x[0] = 'abc'                # 修改列表第一个元素
print(x.data )               # 显示修改后的列表
x[1:3] = ['a','b','c']    # 把列表中的分片[1:3]替换为列表[‘a’,‘b’,‘c’]
print(x.data)                # 显示修改后的列表


def lengthOflongestArray(array, array_len):

    longest = 0
    stack = []

    if array_len < 2: return

    for Idx in range(1, array_len):
        diff = array[Idx] - array[Idx-1]
        if not stack:
            stack.append(diff)
            currLongest = 2

        else:
            if diff == stack[-1]:
                currLongest += 1
            else:
                stack.pop()
                currLongest = 2
                stack.append(diff)

        longest = max(longest, currLongest)

    return longest

t = int(input())
for i in range(1, t+1):
    length = int(input())
    test_array = [int(item) for item in input().split()]
    ans = lengthOflongestArray(test_array, length)
    print("Case #{}: {}". format(i, ans))


inp = input('Enter a file name: ')

try:
    fhand = open(inp)
except IOError:
    print('File not found!')
    quit()

hours = {}
for line in fhand:
    if not line.startswith('From '):
        continue
    time = line.split()[5]
    hour = time.split(':')[0]
    hours[hour] = hours.get(hour, 0) + 1

lst = sorted([(k, v) for k, v in hours.items()])

for i in lst:
    print(i[0], i[1])


"""Sync command."""
from __future__ import annotations

import sys

import click
from result import Ok

from pyrgo.cli.cmds._utils import ensure_env_exist_in_lock_file, inform_and_run_program
from pyrgo.command_exec import PythonCommandExec
from pyrgo.conf import PyrgoConf

@click.command("sync")
@click.option(
    "-e",
    "--env",
    "env",
    type=click.STRING,
    required=True,
)
@click.option(
    "--editable/--no-editable",
    "editable",
    type=click.BOOL,
    default=True,
    show_default=True,
)
def sync(env: str, *, editable: bool) -> None:
    """Sync current python environment to locked deps."""
    config = PyrgoConf.new()
    ensure_env_exist_in_lock_file(env=env, config=config)

    piptools_command = PythonCommandExec.new(program="piptools").add_args(
        args=[
            "sync",
            config.requirements.joinpath(f"{env}.txt")
            .relative_to(config.cwd)
            .as_posix(),
        ],
    )
    pip_command = PythonCommandExec.new(program="pip").add_args(
        args=["install", "--no-deps"],
    )
    if editable:
        pip_command.add_args(args=["-e"])
    pip_command.add_args(args=["."])

    program_execution = inform_and_run_program(commands=[piptools_command, pip_command])

    if not isinstance(program_execution, Ok):
        sys.exit(1)

    sys.exit(0)


from unittest import TestCase
from square import Square

"""this class tests the Square class' snap method, checking to make sure the vertices snap to the nearest integer
    unless doing so would create a single point rather than a square"""

class TestSquare(TestCase):

    def test_snap(self):
        a = Square(4.1, 4.1, 0, 4.1, 0, 0, 4.1, 0)
        b = Square(4, 4, 0, 4, 0, 0, 4, 0)
        self.assertEqual(a.snap(), b)
        c = Square(0.1, 0.1, 0, 0.1, 0, 0, 0.1, 0)
        self.assertEqual(c.snap(), c)


import logging
import os

from jinja2 import Environment, FileSystemLoader
from jupyterhub.services.auth import HubOAuthenticated
from jupyterhub.utils import url_path_join
from tornado.escape import json_decode
from tornado.web import authenticated, HTTPError, RequestHandler

from jupyterhub_entrypoint import dbi
from jupyterhub_entrypoint.types import (
    EntrypointType, EntrypointValidationError
)

class BaseHandler(RequestHandler):
    """Common behaviors across all handler classes."""

    def initialize(self):
        """Initialize settings common to all handlers."""

        super().initialize()
        self.engine = self.settings["engine"]

    @property
    def log(self):
        """I can't seem to avoid typing self.log"""
        return self.settings.get(
            "log", logging.getLogger("tornado.application")
        )

class EntrypointHandler(HubOAuthenticated, BaseHandler):
    """TBD"""

class WebHandler(EntrypointHandler):
    """TBD"""

    def initialize(self):
        """TBD"""

        super().initialize()
        self.loader = FileSystemLoader(self.settings["template_paths"])
        self.env = Environment(loader=self.loader, enable_async=True)

class AboutHandler(WebHandler):
    """TBD"""

    def initialize(self):
        """TBD"""

        super().initialize()
        self.template_about = self.env.get_template("about.html")
        self.about_text = self.settings["about_text"]

    @authenticated
    async def get(self):
        """TBD"""

        user = self.get_current_user()
        hub_auth = self.hub_auth
        base_url = hub_auth.hub_prefix

        chunk = await self.template_about.render_async(
            about_text=self.about_text,
            base_url=base_url,
            login_url=hub_auth.login_url,
            logout_url=url_path_join(base_url, "logout"),
            no_spawner_check=True,
            service_prefix=self.settings["service_prefix"],
            static_url=self.static_url,
            user=user,
        )
        self.write(chunk)

class ViewHandler(WebHandler):
    """TBD"""

    def initialize(self):
        """TBD"""

        super().initialize()
        self.entrypoint_types = self.settings["entrypoint_types"]
        self.template_index = self.env.get_template("index.html")

    @authenticated
    async def get(self, context_name):
        """TBD"""

        user = self.get_current_user()
        username = user["name"]

        async with self.engine.begin() as conn:
            entrypoints = await dbi.retrieve_many_entrypoints(
                conn, username, None, context_name
            )

        entrypoints = entrypoints.get(context_name, {})

        selection = None
        for entrypoint_type_name in self.entrypoint_types:
            for entrypoint in entrypoints.get(entrypoint_type_name, []):
                if entrypoint["selected"]:
                    selection = entrypoint
                    break

        hub_auth = self.hub_auth
        base_url = hub_auth.hub_prefix
        chunk = await self.template_index.render_async(
            base_url=base_url,
            entrypoint_types=self.entrypoint_types,
            entrypoints=entrypoints,
            login_url=hub_auth.login_url,
            logout_url=url_path_join(base_url, "logout"),
            no_spawner_check=True,
            selection=selection,
            service_prefix=self.settings["service_prefix"],
            static_url=self.static_url,
            context_name=context_name,
            contexts=self.settings["contexts"],
            user=user,
        )
        self.write(chunk)

class NewHandler(WebHandler):

    def initialize(self):
        """TBD"""

        super().initialize()
        self.entrypoint_types = self.settings["entrypoint_types"]
        self.template_manage = self.env.get_template("manage.html")

    @authenticated
    async def get(self, entrypoint_type_name):
        user = self.get_current_user()

        try:
            cls, args = self.entrypoint_types[entrypoint_type_name]
            entrypoint_type = cls(*args, username=user["name"])
        except KeyError:
            raise WebError(404)

        context_name = self.get_query_argument("context")

        hub_auth = self.hub_auth
        base_url = hub_auth.hub_prefix
        chunk = await self.template_manage.render_async(
            base_url=base_url,
            login_url=hub_auth.login_url,
            logout_url=url_path_join(base_url, "logout"),
            no_spawner_check=True,
            service_prefix=self.settings["service_prefix"],
            static_url=self.static_url,
            user=user,
            entrypoint_type=entrypoint_type,
            context_name=context_name,
            checked_context_names=[context_name],
            contexts=self.settings["contexts"],
            entrypoint_data=None
        )
        self.write(chunk)

class UpdateHandler(WebHandler):

    def initialize(self):
        """TBD"""

        super().initialize()
        self.entrypoint_types = self.settings["entrypoint_types"]
        self.template_manage = self.env.get_template("manage.html")

    @authenticated
    async def get(self, uuid):

        context_name = self.get_query_argument("context")

        user = self.get_current_user()
        username = user["name"]
        hub_auth = self.hub_auth
        base_url = hub_auth.hub_prefix

        async with self.engine.begin() as conn:
            result = await dbi.retrieve_one_entrypoint(
                conn, username, uuid=uuid
            )
        entrypoint_type_name = result["entrypoint_type_name"]
        entrypoint_data = result["entrypoint_data"]
        context_names = result["context_names"]

        try:
            cls, args = self.entrypoint_types[entrypoint_type_name]
            entrypoint_type = cls(*args, username=username)
        except KeyError:
            raise WebError(404)

        chunk = await self.template_manage.render_async(
            base_url=base_url,
            login_url=hub_auth.login_url,
            logout_url=url_path_join(base_url, "logout"),
            no_spawner_check=True,
            service_prefix=self.settings["service_prefix"],
            static_url=self.static_url,
            user=user,
            entrypoint_type=entrypoint_type,
            context_name=context_name,
            checked_context_names=context_names,
            contexts=self.settings["contexts"],
            entrypoint_data=entrypoint_data,
            uuid=uuid
        )
        self.write(chunk)

class EntrypointAPIHandler(EntrypointHandler):
    """TBD"""

    def initialize(self):
        """TBD"""

        super().initialize()
        self.entrypoint_types = self.settings["entrypoint_types"]
        self.context_names = [
            context["context_name"] for context in self.settings["contexts"]
        ]

    @authenticated
    async def post(self):
        """TBD"""

        user = self.get_current_user().get("name")

        try:
            payload = json_decode(self.request.body)
            entrypoint_type_name = payload["entrypoint_type"]
            entrypoint_data = payload["entrypoint_data"]
            await self.validate_entrypoint_data(user, entrypoint_type_name, entrypoint_data)
            context_names = payload["context_names"] or self.context_names
            self.validate_context_names(context_names)
            async with self.engine.begin() as conn:
                await dbi.create_entrypoint(
                    conn,
                    user,
                    entrypoint_data["entrypoint_name"],
                    entrypoint_type_name,
                    entrypoint_data,
                    context_names
                )
            self.write({"result": True, "message": "Entrypoint added"})
        except EntrypointValidationError:
            self.log.error(f"Validation error: {entrypoint_data}")
            self.write({"result": False, "message": "Validation error"})
        except Exception as e:
            self.log.error(f"Error ({e}): {entrypoint_data}")
            self.write({"result": False, "message": "Error"})

    @authenticated
    async def put(self, uuid):
        """TBD"""

        user = self.get_current_user().get("name")

        async with self.engine.begin() as conn:
            result = await dbi.retrieve_one_entrypoint(
                conn, user, uuid=uuid
            )
        entrypoint_type_name = result["entrypoint_type_name"]
        current_context_names = result["context_names"]

        try:
            payload = json_decode(self.request.body)
            entrypoint_data = payload["entrypoint_data"]
            await self.validate_entrypoint_data(user, entrypoint_type_name, entrypoint_data)
            context_names = payload["context_names"] or self.context_names
            self.validate_context_names(context_names)
            to_tag = list(
                set(context_names).difference(
                    set(current_context_names)
                )
            )
            to_untag = list(
                set(current_context_names).difference(
                    set(context_names)
                )
            )
            async with self.engine.begin() as conn:
                await dbi.update_entrypoint_uuid(
                    conn,
                    user,
                    uuid,
                    entrypoint_data["entrypoint_name"],
                    entrypoint_data
                )
                for context_name in to_tag:
                    await dbi.tag_entrypoint(
                        conn,
                        user,
                        entrypoint_data["entrypoint_name"],
                        context_name
                    )
                for context_name in to_untag:
                    await dbi.untag_entrypoint(
                        conn,
                        user,
                        entrypoint_data["entrypoint_name"],
                        context_name
                    )
            self.write({"result": True, "message": "Entrypoint updated"})
        except EntrypointValidationError:
            self.log.error(f"Validation error: {entrypoint_data}")
            self.write({"result": False, "message": "Validation error"})
        except Exception as e:
            self.log.error(f"Error ({e}): {entrypoint_data}")
            self.write({"result": False, "message": "Error"})

    async def validate_entrypoint_data(
        self,
        user,
        entrypoint_type_name,
        entrypoint_data
    ):
        """Validate request and run appropriate validator on entrypoint data.

        Raises:
            EntrypointValidationError: If the user field doesn't match the
            authenticated user, or the entrypoint type cannot be identified.

        """

        # FIXME: Actually check user

        try:
            cls, args = self.entrypoint_types[entrypoint_type_name]
            entrypoint_type = cls(*args, username=user)
        except:
            raise EntrypointValidationError

        await entrypoint_type.validate(entrypoint_data)

    def validate_context_names(self, context_names):
        for name in context_names:
            if name not in self.context_names:
                raise EntrypointValidationError

    @authenticated
    async def delete(self, entrypoint_name):
        """TBD"""

        user = self.get_current_user().get("name")

        async with self.engine.begin() as conn:
            await dbi.delete_entrypoint(conn, user, entrypoint_name)
        self.write({})

class SelectionAPIHandler(EntrypointHandler):
    """Updates user entrypoint selections."""

    @authenticated
    async def put(self, entrypoint_name, context_name):
        """TBD"""

        user = self.get_current_user().get("name")

        async with self.engine.begin() as conn:
            await dbi.update_selection(conn, user, entrypoint_name, context_name)
        self.write({})

    @authenticated
    async def delete(self, entrypoint_name, context_name):
        """TBD"""

        user = self.get_current_user().get("name")

        # FIXME entrypoint_name isn't doing anything here, maybe don't need it
        async with self.engine.begin() as conn:
            await dbi.delete_selection(conn, user, context_name)
        self.write({})

class HubAPIHandler(BaseHandler):

    def initialize(self):
        """TBD"""

        super().initialize()
        self.entrypoint_api_token = os.environ["ENTRYPOINT_API_TOKEN"]

    def validate_token(self):
        """TBD"""

        return (
            self.request.headers["Authorization"] ==
            f"token {self.entrypoint_api_token}"
        )

    def parse_query_arguments(self):
        """TBD"""

        kwargs = dict()

        batchspawner = self.get_query_argument("batchspawner", "false").lower()
        kwargs["batchspawner"] = batchspawner in ["true", "yes", "1"]

        return kwargs

class HubSelectionAPIHandler(HubAPIHandler):
    """Gives the hub and endpoint to contact to find out a user's selection."""

    def initialize(self):
        """TBD"""

        super().initialize()
        self.entrypoint_types = self.settings["entrypoint_types"]

    async def get(self, user, context_name):
        """TBD"""

        if not self.validate_token():
            raise HTTPError(403)

        try:
            async with self.engine.begin() as conn:
                result = await dbi.retrieve_selection(
                    conn,
                    user,
                    context_name
                )
        except ValueError:
            raise HTTPError(404)
        entrypoint_type_name, entrypoint_data = result

        try:
            cls, args = self.entrypoint_types[entrypoint_type_name]
            entrypoint_type = cls(*args, user=user)
        except KeyError:
            raise WebError(404)

        spawner_args = dict()
        if isinstance(entrypoint_type, EntrypointType):
            kwargs = self.parse_query_arguments()
            spawner_args = entrypoint_type.spawner_args(
                entrypoint_data,
                **kwargs
            )
        self.write(spawner_args)

class HubEntrypointAPIHandler(HubAPIHandler):
    """TBD"""

    def initialize(self):
        """TBD"""

        super().initialize()
        self.entrypoint_types = self.settings["entrypoint_types"]

    async def get(self, user, context_name):
        """TBD"""

        if not self.validate_token():
            raise HTTPError(403)

        async with self.engine.begin() as conn:
            entrypoints = await dbi.retrieve_many_entrypoints(
                conn, user, None, context_name
            )

        entrypoints = entrypoints.get(context_name, {})

        result = list()
        for entrypoint_type_name, entrypoint_list in entrypoints.items():
            try:
                cls, args = self.entrypoint_types[entrypoint_type_name]
                entrypoint_type = cls(*args, username=user)
            except KeyError:
                raise WebError(404)
            for entrypoint in entrypoint_list:
                entrypoint_data = entrypoint["entrypoint_data"]
                entrypoint_name = entrypoint_data["entrypoint_name"]
                kwargs = self.parse_query_arguments()
                spawner_args = entrypoint_type.spawner_args(
                    entrypoint_data,
                    **kwargs
                )
                result.append({
                    "entrypoint_name": entrypoint_name,
                    "entrypoint_type": entrypoint_type_name,
                    "selected": entrypoint["selected"] is True,
                    "spawner_args": spawner_args
                })
        self.write(dict(entrypoints=result))

"""
{
    'shifter': [{
        'uuid': 'bf170fbc-940c-472e-a831-b7329ace4822',
        'entrypoint_data': {
            'entrypoint_name': 'wewet',
            'image': 'ubuntu:latest'
        },
        'selected': None
    }],
    'trusted_script': [{
        'uuid': 'b8350e5f-89aa-4914-9046-6128186ed39a',
        'entrypoint_data': {
            'entrypoint_name': 'sdtwerq',
            'script': '/usr/local/bin/example-entrypoint.sh'
        },
        'selected': None
    }]
}
"""

#       selection = None
#       for entrypoint_type_name in self.entrypoint_types:
#           for entrypoint in entrypoints.get(entrypoint_type_name, []):
#               if entrypoint["selected"]:
#                   selection = entrypoint
#                   break

#       hub_auth = self.hub_auth
#       base_url = hub_auth.hub_prefix
#       chunk = await self.template_index.render_async(
#           base_url=base_url,
#           entrypoint_types=self.entrypoint_types,
#           entrypoints=entrypoints,
#           login_url=hub_auth.login_url,
#           logout_url=url_path_join(base_url, "logout"),
#           no_spawner_check=True,
#           selection=selection,
#           service_prefix=self.settings["service_prefix"],
#           static_url=self.static_url,
#           context_name=context_name,
#           contexts=self.settings["contexts"],
#           user=user,
#       )
#       self.write(chunk)