__all__ = ["interactive_threshold"]

import matplotlib.pyplot as plt
import mpl_interactions.ipyplot as iplt
import numpy as np
import scipy.ndimage as ndi
import scipy
from scipy.optimize import linear_sum_assignment
from skimage.segmentation import watershed
from skimage.feature import peak_local_max

try:
    import napari
except ImportError:
    pass

def interactive_threshold(image, bins="auto", figsize=(12, 5)):
    """
    Use sliders to interactively determine the best threshold for an image.

    Parameters
    ----------
    image : (M, N) array
    bins : int or sequence of scalars or str
        The number of bins to use. Passed through to numpy.histogram
    figsize : tuple of numbers
        The size in inches of the figure

    Returns
    -------
    controls : mpl_interactions.controls
        Access the parameters using `controls.params`
    axes : list of matplotlib axes
        In case you want to modify the plot further.

    Notes
    -----
    This is based on the example from: https://mpl-interactions.readthedocs.io/en/stable/examples/range-sliders.html#Using-a-RangeSlider-for-Scalar-arguments---Thresholding-an-Image
    """
    fig, axs = plt.subplots(1, 2, figsize=(12, 5))

    # plot histogram of pixel intensities
    axs[1].hist(image.flatten(), bins=bins)
    axs[1].set_title("Histogram of Pixel Intensities")

    # create interactive controls
    ctrls = iplt.imshow(image, vmin_vmax=("r", image.min(), image.max()), ax=axs[0])
    iplt.axvline(ctrls["vmin"], ax=axs[1], c="k")
    _ = iplt.axvline(ctrls["vmax"], ax=axs[1], c="k")
    return ctrls, axs

def individualize_single_frame(mask, min_distance=10):
    """
    Perform a watershed segmentation on a single frame.

    Parameters
    ----------
    mask : (M, N) arraylike of bool

    Returns
    -------
    labels : (M, N) array
    peaks : (M, N) array
    """
    distance = ndi.distance_transform_edt(mask)
    coords = peak_local_max(distance, min_distance=min_distance)
    peaks = np.zeros(distance.shape, dtype=bool)
    peaks[tuple(coords.T)] = True
    markers, _ = ndi.label(peaks)
    labels = watershed(-distance, markers, mask=mask, connectivity=2)
    return labels, peaks

def get_segment_cmap(labels, alpha=.75):
    """
    Create a colormap that useful for overlaying segmentation labels onto an image.
    The 0 label will be transparent.

    Parameters
    ----------
    labels : int, or (M, N) array of int
        The number of unique labels, or the array of labels from which the number of colors will
        be automatically determined.
    alpha : float, default: 0.75
        The alpha value of the colormap

    Returns
    -------
    matplotlib.colormap
    """
    from matplotlib.colors import LinearSegmentedColormap
    if isinstance(labels, int):
        N = labels
    else:
        N = len(np.unique(labels))
    colors = np.random.rand(N, 4)
    colors[:,-1] = alpha
    colors[0,-1] = 0
    cmap = LinearSegmentedColormap.from_list('segment_cmap', colors, N=N)
    return cmap

###############################
# The rest of this file is a slightly modified version of:
# https://github.com/Hekstra-Lab/microutil/blob/4683c72644dc51c6e6da2608db97aa58f10028c9/microutil/track_utils.py

def construct_cost_matrix(
    prev,
    curr,
    weights=[1, 1, 1 / 20],
    pad=1e4,
    debug_info="",
    normalize=False,
    distance_cutoff=0.5,
    compute_overlap=True,
):
    """
    prev : (X, Y) array of int
        The previous time point's labels
    curr : (X, Y) array of int
        The current time point's labels.
    weights : (3,) array-like, default: [1, 1, 1/5]
        The weighting of features to use for the minkowski distance.
        The current order is [X, Y, area]
    pad : number or None, default: 1e4
        The value to use when padding the cost matrix to be square. Set to *None*
        to not pad.
    normalize : bool, default: False
        Whether to normalize the each frames features. Optional as it sometimes seems
        to cause issues.
    distance_cutoff : float, default: .5
        Float between [0,1] the maximum distance relative to the frame size
        for which cells can be considered to be tracked. Cell pairs with a distance
        geater than the computed maximum will be given an entry into the cost matrix of
        1e6
    compute_overlap : bool, default: True
        Whether to to weight the assignments by how much the cells overlap between the
        two timesteps. This may be a slow step.
    Returns
    -------
    C : (N, N) array
        The cost matrix. Where *N* is the larger of the number of cells of the two
        time points
    M : int
        The number of cells in the previous time point.
    """
    prev_features = frame_to_features(prev)
    curr_features = frame_to_features(curr)
    min_areas = np.minimum.outer(prev_features[:, -1], curr_features[:, -1])
    xy_dist = scipy.spatial.distance.cdist(prev_features[:, :2], curr_features[:, :2])
    if normalize:
        norm(prev_features, curr_features)

    C = scipy.spatial.distance.cdist(
        prev_features, curr_features, metric="minkowski", w=weights
    )

    max_dist = np.sqrt(prev.shape[0] ** 2 + prev.shape[1] ** 2)
    too_far_idx = xy_dist > distance_cutoff * max_dist
    C[too_far_idx] = 1e6

    # figure out if masks overlap and make those ones more likely
    if compute_overlap:
        overlaps = overlap(prev, curr, (C.shape[0] + 1, C.shape[1] + 1))[1:, 1:].astype(
            float
        )
        overlaps /= min_areas
        C *= 1 - overlaps

    if np.any(np.isnan(C)):
        print(prev_features)
        print(curr_features)
        print(C)

    M, N = C.shape
    if pad is not None:
        if M < N:
            # maybe these should be low cost connections?
            row_pad = N - M
            C = np.pad(C, ((0, row_pad), (0, 0)), constant_values=pad)
        elif M > N:
            print("Fewer cells in the current frame than the last frame")
            print("for best results run `correct_watershed` again")
            print(debug_info + f" - {M} {N}")
        return C, M
    return C, M

def _process_seeds(seeds, idxs=None):
    if idxs is None:
        Ss, Ts, Ys, Xs = np.nonzero(seeds)
    else:
        idxs = np.asarray(idxs).astype(np.int)
        Ss, Ts = idxs.T
        Ys, Xs = seeds[:, -2], seeds[:, -1]
    # get the maximum number of cells in any frame so we know what to pad to
    # probs could make this part speedier
    max_N = 0
    for s in np.unique(Ss):
        N = np.unique(Ts[Ss == s], return_counts=True)[1].max()
        if N > max_N:
            max_N = N

    T = Ts.max() + 1
    S = Ss.max() + 1
    _seeds = np.zeros([S, T, max_N, 2], np.float32)
    _seeds[...] = np.nan
    for s in range(S):
        s_idx = Ss == s
        for t in range(T):
            t_idx = Ts[s_idx] == t

            _seeds[s, t, : np.sum(t_idx)] = np.hstack(
                [Ys[s_idx][t_idx][:, None], Xs[s_idx][t_idx][:, None]]
            )
    return _seeds

def peak_mask_to_napari_points(peak_mask):
    """
    Convert a peak mask array into the points format that napari expects
    Parameters
    ----------
    peak_mask : (S, T, Y, X) array of bool
    Returns
    -------
    points : (N, 4) array of int
    """
    points = _process_seeds(peak_mask)
    s = points.shape[:-1]
    N = np.cumprod(s)[-1]
    points_transformed = np.hstack(
        [
            a.ravel()[:, None]
            for a in np.meshgrid(
                *[np.arange(s) for s in points.shape[:-1]], indexing="ij"
            )
        ]
        + [points.reshape((N, 2))]
    )[:, [0, 1, 3, 4]]
    return points_transformed[~np.isnan(points_transformed).any(axis=1)]

def napari_points_to_peak_mask(points, shape, S, T):
    """
    Parameters
    ----------
    points : (N, d) array
        The *data* attribute of a napari points layer
    shape : tuple
        The shape of the output mask
    S, T : int
    Returns
    -------
    peak_mask : array of bool
    """
    new_seeds = _process_seeds(points[:, -2:], points[:, :2])[S, T]
    new_seeds = new_seeds[~np.any(np.isnan(new_seeds), axis=1)]
    peak_mask = np.zeros(shape, dtype=bool)
    peak_mask[tuple(new_seeds.astype(int).T)] = True
    return peak_mask

def watershed_single_frame_preseeded(mask, peak_mask):
    """
    Perform a watershed on a single frame of a dataset. This will
    not populate the watershed labels. They must already exist.
    You probably don't want to use this function when scripting. This is primarily
    provided for usage inside of correct_watershed.
    Parameters
    ----------
    ds : Dataset
    S, T : int
    """
    print(mask.shape)
    print(peak_mask.shape)
    topology = -ndi.distance_transform_edt(mask)
    return watershed(topology, ndi.label(peak_mask)[0], mask=mask)

def scroll_time(viewer, time_axis=1):
    def scroll_callback(layer, event):
        if "Shift" in event.modifiers:
            new = list(viewer.dims.current_step)

            # get the max time
            max_time = viewer.dims.range[time_axis][1]

            # event.delta is (float, float) for horizontal and vertical scroll
            # on linux shift-scroll gives vertical
            # but on mac it gives horizontal. So just take the max and hope
            # for the best
            if max(event.delta) > 0:
                if new[time_axis] < max_time:
                    new[time_axis] += 1
            else:
                if new[time_axis] > 0:
                    new[time_axis] -= 1
            viewer.dims.current_step = new

    viewer.mouse_wheel_callbacks.append(scroll_callback)

def apply_label_keybinds(labels):
    @labels.bind_key("q")
    def paint_mode(viewer):
        labels.mode = "erase"

    @labels.bind_key("w")
    def paint_mode(viewer):
        labels.mode = "fill"

    @labels.bind_key("s")
    def paint_mode(viewer):
        labels.selected_label = 0
        labels.mode = "fill"

    @labels.bind_key("e")
    def paint_mode(viewer):
        labels.mode = "paint"

    @labels.bind_key("r")
    def paint_mode(viewer):
        labels.mode = "pick"

    @labels.bind_key("t")
    def new_cell(viewer):
        labels.selected_label = labels.data.max() + 1

    # scrolling in paint mode changes the brush size
    # shift-scroll changes the time point
    time_axis = 1

    def scroll_callback(layer, event):
        if len(event.modifiers) == 0 and labels.mode in ["paint", "erase"]:
            if event.delta[1] > 0:
                labels.brush_size += 1
            else:
                labels.brush_size = max(labels.brush_size - 1, 1)

    labels.mouse_wheel_callbacks.append(scroll_callback)

def apply_points_keybinds(points):
    @points.bind_key("q")
    def remove_selected(layer):
        points.remove_selected()

    @points.bind_key("w")
    def add_mode(layer):
        points.mode = "add"

    @points.bind_key("e")
    def select_mode(layer):
        points.mode = "select"

def correct_watershed(images, labels_arr, peak_mask):
    """
    Manually correct parts of an image with a bad watershed.
    This will modify the 'peak_mask' and 'labels' variables of the Dataset inplace.
    Keybindings:
    2 : toggle between mask and labels
    3 : toggle between controlling mask/labels or points
    4 : Toggle visibility of mask+labels on and off
    5 : Toggle whether painting paints through all time points
    Control-l : rereun current frame's watershed
    Control-Shift-l : rereun watershed for all the frames
    Shift + Scroll : scrub through time points
    Point Layer Keybindings:
    q : delete selected points
    w : Switch to `Add Points` mode
    e : Switch to `Select` mode
    Mask/Labels layer Keybindngs:
    q : erase
    w : fill
    e : paint
    r : pick
    t : create new label
    s : fill with background
    Scroll : modify brush size when in paint mode
    Parameters
    ----------
    ds : (S, T, ... , Y, X) xarray dataset
    """

    viewer = napari.view_image(images)
    labels = viewer.add_labels(labels_arr, name="labels", visible=True)
    peak_coords = peak_mask_to_napari_points(peak_mask[None, :, ...])
    points = viewer.add_points(peak_coords, size=5, name="watershed seeds")
    apply_label_keybinds(labels)
    scroll_time(viewer)
    apply_points_keybinds(points)

    through_time = False

    def setup_through_time(layer):
        old_paint = layer.paint
        old_fill = layer.fill

        def paint_through_time(coord, new_label, refresh=True):
            if through_time:
                for i in range(labels.data.shape[1]):
                    c = list(coord)
                    c[1] = i
                    old_paint(c, new_label, refresh)
            else:
                old_paint(coord, new_label, refresh)

        layer.paint = paint_through_time

    setup_through_time(labels)

    def toggle_masks(*args):
        if mask.visible and labels.visible:
            # ugh - I guess set the labels to visible
            labels_and_points()
        elif mask.visible:
            labels_and_points()
        else:
            mask_and_points()
        if viewer.active_layer in [mask, labels]:
            set_correct_active_labels()

    def mask_and_points(*args):
        mask.visible = True
        labels.visible = False

    def labels_and_points(*args):
        mask.visible = False
        labels.visible = True

    def toggle_points_vs_labels(viewer):
        if viewer.active_layer == points:
            set_correct_active_labels()
        else:
            viewer.layers.unselect_all()
            points.selected = True

    def gogogo(viewer):
        T = viewer.dims.current_step[:1]
        peak_mask[T] = napari_points_to_peak_mask(points.data, images.shape[1:], 0, T)
        labels_arr[T] = watershed_single_frame_preseeded(
            labels.data[T] != 0, peak_mask[T]
        )
        labels.data = labels_arr

    def gogogo_all(viewer):
        for T in range(images.shape[0]):
            peak_mask[T] = napari_points_to_peak_mask(
                points.data, images.shape[1:], 0, T
            )
            labels_arr[T] = watershed_single_frame_preseeded(
                labels.data[T] != 0, peak_mask[T]
            )
            labels.data = labels_arr

    def toggle_through_time(*args):
        nonlocal through_time
        through_time = not through_time

    viewer.bind_key("2", toggle_masks)
    viewer.bind_key("3", toggle_points_vs_labels)
    viewer.bind_key("5", toggle_through_time)
    viewer.bind_key("Control-l", gogogo)
    viewer.bind_key("Control-Shift-l", gogogo_all)
    return labels

def _py_overlap(prev, curr, shape):
    p_uniq = np.unique(prev)
    c_uniq = np.unique(curr)
    arr = np.zeros(shape)
    for i in p_uniq:
        for j in c_uniq:
            arr[i, j] = np.sum((prev == i) * (curr == j))
    return arr

def overlap(prev, curr, shape):
    """
    Calculate the pairwise overlap the labels for two arrays.
    This will use `fast_overlap` if that library is available.
    Parameters
    ----------
    prev, curr : 2D array-like of int
        curr will have at least as many unique labels as prev
    shape : tuple of int
        The shape of the output array. This should reflect the maximum
        value of labels.
    Returns
    -------
    arr : (N, M) array of int
        N is the number of unique labels in prev and M the number of unique in curr.
        The ijth entry in the array gives the number of pixels for which label *i* in prev
        overlaps with *j* in curr.
    """

    # figure out if masks overlap and make those ones more likely
    try:
        from fast_overlap import overlap

        return np.asarray(overlap(prev, curr, shape))
    except ImportError:
        return _py_overlap(prev, curr, shape)

def norm(prev, curr):
    for col in range(3):
        r = np.hstack([prev[:, col], curr[:, col]])
        m = np.mean(r)
        s = np.std(r)
        prev[:, col] = (prev[:, col] - m) / s
        curr[:, col] = (curr[:, col] - m) / s

def frame_to_features(frame):
    """
    Parameters
    ----------
    frame : (X, Y) array-like
        The mask of labels to create features from
    Returns
    -------
    features : (N, 3)
        The features array of (com_x, com_y, area)
    """
    labels, areas = np.unique(frame, return_counts=True)
    com = np.asarray(ndi.center_of_mass(frame, frame, labels[1:]))
    return np.hstack([com, areas[1:, None]])

def construct_cost_matrix(
    prev,
    curr,
    weights=[1, 1, 1 / 20],
    pad=1e4,
    debug_info="",
    normalize=False,
    distance_cutoff=0.5,
    compute_overlap=True,
):
    """
    prev : (X, Y) array of int
        The previous time point's labels
    curr : (X, Y) array of int
        The current time point's labels.
    weights : (3,) array-like, default: [1, 1, 1/5]
        The weighting of features to use for the minkowski distance.
        The current order is [X, Y, area]
    pad : number or None, default: 1e4
        The value to use when padding the cost matrix to be square. Set to *None*
        to not pad.
    normalize : bool, default: False
        Whether to normalize the each frames features. Optional as it sometimes seems
        to cause issues.
    distance_cutoff : float, default: .5
        Float between [0,1] the maximum distance relative to the frame size
        for which cells can be considered to be tracked. Cell pairs with a distance
        geater than the computed maximum will be given an entry into the cost matrix of
        1e6
    compute_overlap : bool, default: True
        Whether to to weight the assignments by how much the cells overlap between the
        two timesteps. This may be a slow step.
    Returns
    -------
    C : (N, N) array
        The cost matrix. Where *N* is the larger of the number of cells of the two
        time points
    M : int
        The number of cells in the previous time point.
    """
    prev_features = frame_to_features(prev)
    curr_features = frame_to_features(curr)
    min_areas = np.minimum.outer(prev_features[:, -1], curr_features[:, -1])
    xy_dist = scipy.spatial.distance.cdist(prev_features[:, :2], curr_features[:, :2])
    if normalize:
        norm(prev_features, curr_features)

    C = scipy.spatial.distance.cdist(
        prev_features, curr_features, metric="minkowski", w=weights
    )

    max_dist = np.sqrt(prev.shape[0] ** 2 + prev.shape[1] ** 2)
    too_far_idx = xy_dist > distance_cutoff * max_dist
    C[too_far_idx] = 1e6

    # figure out if masks overlap and make those ones more likely
    if compute_overlap:
        overlaps = overlap(prev, curr, (C.shape[0] + 1, C.shape[1] + 1))[1:, 1:].astype(
            float
        )
        overlaps /= min_areas
        C *= 1 - overlaps

    if np.any(np.isnan(C)):
        print(prev_features)
        print(curr_features)
        print(C)

    M, N = C.shape
    if pad is not None:
        if M < N:
            # maybe these should be low cost connections?
            row_pad = N - M
            C = np.pad(C, ((0, row_pad), (0, 0)), constant_values=pad)
        elif M > N:
            print("More cells in the current frame than the previous frame")
            print('for best results rerun correct_watershed and fix this')
            print(debug_info + f" - {M} {N}")
        return C, M
    return C, M

def track(arr, weights=[1, 1, 1 / 5], pad=1e4):
    """
    Track cells over a time lapse.

    Parameters
    ----------
    arr : (T, M, N) array-like
        The mask of cell labels. Should be integers.
    weights : (3,) array-like, default: [1, 1, 1/5]
        The weighting of features to use for the minkowski distance.
        The current order is [X, Y, area]
    pad : number or None, default: 1e4
        The value to use when padding the cost matrix to be square. Set to *None*
        to not pad.

    Returns
    -------
    tracked : (T, M, N) array
        The labels mask with cells tracked through time. So ideally
        a cell labelled 4 at t0 will also be labelled 4 at t1.
    """
    tracked = np.zeros_like(arr)
    tracked[0] = arr[0]

    for t in range(1, len(arr)):
        C, M = construct_cost_matrix(
            tracked[t - 1], arr[t], weights=weights, debug_info=f"t={t}"
        )
        row_ind, col_ind = linear_sum_assignment(C)
        assignments = np.stack([row_ind, col_ind], axis=1)

        for i in range(len(assignments)):
            prev, curr = assignments[i]
            idx = arr[t] == curr + 1
            tracked[t][idx] = prev + 1
    return tracked


# 把path文件夹下以及其子文件下的所有png图片移动（不是复制）到new_path

import os
import shutil

path = '/home/yong/dataset/Cityscapes/gtFine_trainvaltest/gtFine/train'
# path = '/home/yong/dataset/Cityscapes/leftImg8bit_trainvaltest/leftImg8bit/train'
new_path = '/home/yong/code/TensorFlow-ENet/dataset/Cityscapes_trainannot'

#####image_GT
for root, dirs, files in os.walk(path):
    if len(dirs) == 0:
        for i in range(len(files)):
            if files[i][-12:-4] == 'labelIds':
                file_path = root + '/' + files[i]
                new_file_path = new_path + '/' + files[i][:-19] + 'leftImg8bit.png'
                shutil.copy(file_path, new_file_path)

# ####image
# for root, dirs, files in os.walk(path):
#     if len(dirs) == 0:
#         for i in range(len(files)):
#             # if files[i][-12:-4] == 'labelIds':
#                 file_path = root + '/' + files[i]
#                 new_file_path = new_path + '/' + files[i]
#                 shutil.copy(file_path, new_file_path)

#
# import os
# import shutil
#
# print('输入格式：E:\myprojectnew\jupyter\整理文件夹\示例')
# path = input('请键入需要整理的文件夹地址：')
# new_path = input('请键入要复制到的文件夹地址：')
#
# for root, dirs, files in os.walk(path):
#     for i in range(len(files)):
#         # print(files[i])
#         if (files[i][-3:] == 'jpg') or (files[i][-3:] == 'png') or (files[i][-3:] == 'JPG'):
#             file_path = root + '/' + files[i]
#             new_file_path = new_path + '/' + files[i]
#             shutil.move(file_path, new_file_path)
#
#             # yn_close = input('是否退出？')


# Import pour lecture et utilisation de la mediane
import numpy as np
# Lecture des donnees
t,u = np.loadtxt('ouverture_appareil_photo.txt',unpack=True,skiprows=1)

# Pour que le dessin donne quelque chose
t_propre = [1,2,3]
u_propre = [1,3,1]

# Avant de pouvoir appliquer le meme principe que pour le flash, il faut
# proprifier votre signal (stocker les valeurs correspondantes dans les listes
# t_propre et u_propre).

# Le code suivant vous permet de visualiser si votre procede de nettoyage
# marche correctement. Vous aurez dans le dossier un fichier image
# ouverture_propre.png qui devrait se creer.

import matplotlib.pyplot as plt

plt.plot(t_propre,u_propre)
plt.savefig('ouverture_propre.png')

# Ne reste plus qu'a proceder comme pour le flash pour obtenir le temps total
# d'ouverture

temps_ouverture = 'pas ca...'

# Affichage du resultat
print(temps_ouverture)


import face_recognition
import numpy as np
import cv2
import urllib
import io

def url_to_image(url):
	# download the image, convert it to a NumPy array, and then read
	# it into OpenCV format
	resp = urllib.request.urlopen(url)
	image = np.asarray(bytearray(resp.read()), dtype="uint8")
	image = cv2.imdecode(image, cv2.IMREAD_COLOR)

	# return the image
	return image

def compareFaces(base_photo, target_photo):

    bse_image = face_recognition.load_image_file(base_photo)

    try:
        bse_encoding = face_recognition.face_encodings(bse_image)[0]
        tgt_encoding = face_recognition.face_encodings(url_to_image(target_photo))[0]
    except:
        return (-1)

    known_encodings = [bse_encoding]

    face_distances = face_recognition.face_distance(known_encodings, tgt_encoding)

    return face_distances[0]


import json
import os

def loadjsondata(filename):
    path = os.getcwd()
    with open(filename) as data_file:
        data = json.load(data_file)
    return data

ENV_FILE = os.getcwd()+'/env.json'
env = loadjsondata(ENV_FILE)


#calss header
class _IDENTITY():
	def __init__(self,):
		self.name = "IDENTITY"
		self.definitions = [u'who a person is, or the qualities of a person or group that make them different from others: ']

		self.parents = []
		self.childen = []
		self.properties = []
		self.jsondata = {}

		self.specie = 'nouns'

	def run(self, obj1 = [], obj2 = []):
		return self.jsondata


#!/usr/bin/env python2
import sys
import time

from argparse import ArgumentParser

import yaml
import logging

from certification_tool import fuel_rest_api
from certification_tool.main import login

fuel_rest_api.set_logger(logging.getLogger())
logger = logging.getLogger()
logger.setLevel(logging.DEBUG)

def parse_command_line(argv):
    parser = ArgumentParser("usage: %prog [options]")

    parser.add_argument('-a', '--auth',
                        help='keystone credentials in format '
                             'tenant_name:username:password',
                        dest="auth", default='admin:admin:admin')

    parser.add_argument('-u', '--fuelurl', help="fuel rest url",
                        dest='fuelurl', required=True)

    parser.add_argument('config_file',
                        help='yaml configuration file',
                        metavar="CLUSTER_CONFIG")

    return parser.parse_args(argv)

def match_nodes(conn, cluster):
    controller_count = int(cluster['controller'])
    compute_nodes = int(cluster['compute'])
    cinder = int(cluster.get('cinder', 0))
    ceph_osd = int(cluster.get('ceph_osd', 0))

    min_nodes = ceph_osd + cinder + compute_nodes + controller_count

    while True:
        nodes = [node for node in fuel_rest_api.get_all_nodes(conn)
                 if node.cluster is None]

        if len(nodes) < min_nodes:
            templ = "Waiting till {} nodes will be available"
            logger.info(templ.format(min_nodes))
            time.sleep(10)
            continue

        if len(nodes) <= 1:
            raise ValueError("Nodes amount should be not less, than 2")

        cpu_disk = []
        for node in nodes:
            info = node.get_info()

            cpu_count = int(info['meta']['cpu']['real'])
            disk_size = 0

            for disk in info['meta']['disks']:
                disk_size += int(disk['size'])

            cpu_disk.append((disk_size, cpu_count, node))

        cpu_disk.sort()
        nodes = [tpl[2] for tpl in cpu_disk]

        for i, node in enumerate(nodes[:controller_count]):
            descr = {'roles': ["controller"],
                     'name': "controller_{}".format(i)}
            yield (descr, node)
        nodes = nodes[controller_count:]

        for i, node in enumerate(nodes[:cinder]):
            descr = {'roles': ["cinder"],
                     'name': "cinder_{}".format(i)}
            yield (descr, node)
        nodes = nodes[cinder:]

        for i, node in enumerate(nodes[:ceph_osd]):
            descr = {'roles': ["ceph-osd"],
                     'name': "ceph_{}".format(i)}
            yield (descr, node)
        nodes = nodes[ceph_osd:]

        for i, node in enumerate(nodes):
            descr = {'roles': ["compute"],
                     'name': "compute_{}".format(i)}
            yield (descr, node)

        break

def str2ip_range(ip_str):
    ip1, ip2 = ip_str.split("-")
    return [ip1.strip(), ip2.strip()]

def set_networks_params(cluster, net_settings):
    configuration = cluster.get_networks()
    curr_config = configuration['networking_parameters']

    if 'floating' in net_settings:
        curr_config['floating_ranges'] = \
            [str2ip_range(net_settings['floating'])]

    if 'public' in net_settings:
        pub_settings = net_settings['public']
        for net in configuration['networks']:
            if net['name'] == 'public':

                if 'ip_ranges' in pub_settings:
                    ip_range = str2ip_range(pub_settings['ip_ranges'])
                    net['ip_ranges'] = [ip_range]

                if 'cidr' in pub_settings:
                    net['cidr'] = pub_settings['cidr']

                if 'gateway' in pub_settings:
                    net['gateway'] = pub_settings['gateway']

    cluster.configure_networks(**configuration)

def create_cluster(conn, cluster):

    nodes_iter = match_nodes(conn, cluster['nodes'])

    cluster_obj = fuel_rest_api.create_empty_cluster(conn, cluster)

    if 'network' in cluster:
        set_networks_params(cluster_obj, cluster['network'])

    for node_desc, node in nodes_iter:
        node.set_node_name(node_desc['name'])
        cluster_obj.add_node(node, node_desc['roles'])

def main(argv):
    args = parse_command_line(argv)
    conn = login(args.fuelurl, args.auth)
    cluster = yaml.load(open(args.config_file).read())

    for cluster_obj in fuel_rest_api.get_all_clusters(conn):
        if cluster_obj.name == cluster['name']:
            cluster_obj.delete()
            wd = fuel_rest_api.with_timeout(60, "Wait cluster deleted")
            wd(lambda co: not co.check_exists())(cluster_obj)

    create_cluster(conn, cluster)

if __name__ == "__main__":
    exit(main(sys.argv[1:]))


__author__ = 'd.polkovnikov'
import os
import sys

class EpubBookCreator:
	name = ""
	path = ""
	images = []
	resources = []
	parts = []

	def __init__(self, name, path=os.path.dirname(__file__)):
		self.name = name
		self.path = path
		self.__create_empty_dir()

	def __create_empty_dir(self):
		full_path = os.path.join(self.path, self.name)
		if os.path.exists(full_path):
			raise RuntimeError("directory already exists")
		else:
			os.mkdir(full_path)
			file = open(os.path.join(full_path, "mimetype"), 'w')
			file.write("application/epub+zip")
			file.close()
			os.mkdir(os.path.join(full_path, "META-INF"))
			os.mkdir(os.path.join(full_path, 'OEBPS'))
			file = open(os.path.join(full_path, 'META-INF', 'container.xml'), 'w')
			file.write('''<?xml version="1.0" encoding="utf-8"?>
			<container version="1.0" xmlns="urn:oasis:names:tc:opendocument:xmlns:container"><rootfiles><rootfile full-path="OEBPS/content.opf"
			media-type="application/oebps-package+xml" /></rootfiles></container>''')
			file.close()

	def add_part(self, title, text):
		pass


import operator
import types
import uuid
import warnings
from collections.abc import Iterator
try:
    from cytoolz import curry, concat, unique, merge
except ImportError:
    from toolz import curry, concat, unique, merge
from . import config, threaded
from .base import is_dask_collection, dont_optimize, DaskMethodsMixin
from .base import tokenize as _tokenize
from .compatibility import is_dataclass, dataclass_fields
from .core import quote
from .context import globalmethod
from .optimization import cull
from .utils import funcname, methodcaller, OperatorMethodMixin, ensure_dict, apply
from .highlevelgraph import HighLevelGraph
__all__ = ["Delayed", "delayed"]
def unzip(ls, nout):

    out = list(zip(*ls))
    if not out:
        out = [()] * nout
    return out
def finalize(collection):
    assert is_dask_collection(collection)
    name = "finalize-" + tokenize(collection)
    keys = collection.__dask_keys__()
    finalize, args = collection.__dask_postcompute__()
    layer = {name: (finalize, keys) + args}
    graph = HighLevelGraph.from_collections(name, layer, dependencies=[collection])
    return Delayed(name, graph)
def unpack_collections(expr):

    if isinstance(expr, Delayed):
        return expr._key, (expr,)
    if is_dask_collection(expr):
        finalized = finalize(expr)
        return finalized._key, (finalized,)
    if isinstance(expr, Iterator):
        expr = tuple(expr)
    typ = type(expr)
    if typ in (list, tuple, set):
        args, collections = unzip((unpack_collections(e) for e in expr), 2)
        args = list(args)
        collections = tuple(unique(concat(collections), key=id))
        # Ensure output type matches input type
        if typ is not list:
            args = (typ, args)
        return args, collections
    if typ is dict:
        args, collections = unpack_collections([[k, v] for k, v in expr.items()])
        return (dict, args), collections
    if typ is slice:
        args, collections = unpack_collections([expr.start, expr.stop, expr.step])
        return (slice,) + tuple(args), collections
    if is_dataclass(expr):
        args, collections = unpack_collections(
            [[f.name, getattr(expr, f.name)] for f in dataclass_fields(expr)]
        )
        return (apply, typ, (), (dict, args)), collections
    return expr, ()
def to_task_dask(expr):

    warnings.warn(
        "The dask.delayed.to_dask_dask function has been "
        "Deprecated in favor of unpack_collections",
        stacklevel=2,
    )
    if isinstance(expr, Delayed):
        return expr.key, expr.dask
    if is_dask_collection(expr):
        name = "finalize-" + tokenize(expr, pure=True)
        keys = expr.__dask_keys__()
        opt = getattr(expr, "__dask_optimize__", dont_optimize)
        finalize, args = expr.__dask_postcompute__()
        dsk = {name: (finalize, keys) + args}
        dsk.update(opt(expr.__dask_graph__(), keys))
        return name, dsk
    if isinstance(expr, Iterator):
        expr = list(expr)
    typ = type(expr)
    if typ in (list, tuple, set):
        args, dasks = unzip((to_task_dask(e) for e in expr), 2)
        args = list(args)
        dsk = merge(dasks)
        # Ensure output type matches input type
        return (args, dsk) if typ is list else ((typ, args), dsk)
    if typ is dict:
        args, dsk = to_task_dask([[k, v] for k, v in expr.items()])
        return (dict, args), dsk
    if is_dataclass(expr):
        args, dsk = to_task_dask(
            [[f.name, getattr(expr, f.name)] for f in dataclass_fields(expr)]
        )
        return (apply, typ, (), (dict, args)), dsk
    if typ is slice:
        args, dsk = to_task_dask([expr.start, expr.stop, expr.step])
        return (slice,) + tuple(args), dsk
    return expr, {}
def tokenize(*args, **kwargs):

    pure = kwargs.pop("pure", None)
    if pure is None:
        pure = config.get("delayed_pure", False)
    if pure:
        return _tokenize(*args, **kwargs)
    else:
        return str(uuid.uuid4())
@curry
def delayed(obj, name=None, pure=None, nout=None, traverse=True):

    if isinstance(obj, Delayed):
        return obj
    if is_dask_collection(obj) or traverse:
        task, collections = unpack_collections(obj)
    else:
        task = quote(obj)
        collections = set()
    if task is obj:
        if not (nout is None or (type(nout) is int and nout >= 0)):
            raise ValueError(
                "nout must be None or a non-negative integer, got %s" % nout
            )
        if not name:
            try:
                prefix = obj.__name__
            except AttributeError:
                prefix = type(obj).__name__
            token = tokenize(obj, nout, pure=pure)
            name = "%s-%s" % (prefix, token)
        return DelayedLeaf(obj, name, pure=pure, nout=nout)
    else:
        if not name:
            name = "%s-%s" % (type(obj).__name__, tokenize(task, pure=pure))
        layer = {name: task}
        graph = HighLevelGraph.from_collections(name, layer, dependencies=collections)
        return Delayed(name, graph)
def right(method):

    def _inner(self, other):
        return method(other, self)
    return _inner
def optimize(dsk, keys, **kwargs):
    dsk = ensure_dict(dsk)
    dsk2, _ = cull(dsk, keys)
    return dsk2
def rebuild(dsk, key, length):
    return Delayed(key, dsk, length)
class Delayed(DaskMethodsMixin, OperatorMethodMixin):

    __slots__ = ("_key", "dask", "_length")
    def __init__(self, key, dsk, length=None):
        self._key = key
        self.dask = dsk
        self._length = length
    def __dask_graph__(self):
        return self.dask
    def __dask_keys__(self):
        return [self.key]
    def __dask_layers__(self):
        return (self.key,)
    def __dask_tokenize__(self):
        return self.key
    __dask_scheduler__ = staticmethod(threaded.get)
    __dask_optimize__ = globalmethod(optimize, key="delayed_optimize")
    def __dask_postcompute__(self):
        return single_key, ()
    def __dask_postpersist__(self):
        return rebuild, (self._key, getattr(self, "_length", None))
    def __getstate__(self):
        return tuple(getattr(self, i) for i in self.__slots__)
    def __setstate__(self, state):
        for k, v in zip(self.__slots__, state):
            setattr(self, k, v)
    @property
    def key(self):
        return self._key
    def __repr__(self):
        return "Delayed({0})".format(repr(self.key))
    def __hash__(self):
        return hash(self.key)
    def __dir__(self):
        return dir(type(self))
    def __getattr__(self, attr):
        if attr.startswith("_"):
            raise AttributeError("Attribute {0} not found".format(attr))
        return DelayedAttr(self, attr)
    def __setattr__(self, attr, val):
        if attr in self.__slots__:
            object.__setattr__(self, attr, val)
        else:
            raise TypeError("Delayed objects are immutable")
    def __setitem__(self, index, val):
        raise TypeError("Delayed objects are immutable")
    def __iter__(self):
        if getattr(self, "_length", None) is None:
            raise TypeError("Delayed objects of unspecified length are not iterable")
        for i in range(self._length):
            yield self[i]
    def __len__(self):
        if getattr(self, "_length", None) is None:
            raise TypeError("Delayed objects of unspecified length have no len()")
        return self._length
    def __call__(self, *args, **kwargs):
        pure = kwargs.pop("pure", None)
        name = kwargs.pop("dask_key_name", None)
        func = delayed(apply, pure=pure)
        if name is not None:
            return func(self, args, kwargs, dask_key_name=name)
        return func(self, args, kwargs)
    def __bool__(self):
        raise TypeError("Truth of Delayed objects is not supported")
    __nonzero__ = __bool__
    def __get__(self, instance, cls):
        if instance is None:
            return self
        return types.MethodType(self, instance)
    @classmethod
    def _get_binary_operator(cls, op, inv=False):
        method = delayed(right(op) if inv else op, pure=True)
        return lambda *args, **kwargs: method(*args, **kwargs)
    _get_unary_operator = _get_binary_operator
def call_function(func, func_token, args, kwargs, pure=None, nout=None):
    dask_key_name = kwargs.pop("dask_key_name", None)
    pure = kwargs.pop("pure", pure)
    if dask_key_name is None:
        name = "%s-%s" % (
            funcname(func),
            tokenize(func_token, *args, pure=pure, **kwargs),
        )
    else:
        name = dask_key_name
    args2, collections = unzip(map(unpack_collections, args), 2)
    collections = list(concat(collections))
    if kwargs:
        dask_kwargs, collections2 = unpack_collections(kwargs)
        collections.extend(collections2)
        task = (apply, func, list(args2), dask_kwargs)
    else:
        task = (func,) + args2
    graph = HighLevelGraph.from_collections(
        name, {name: task}, dependencies=collections
    )
    nout = nout if nout is not None else None
    return Delayed(name, graph, length=nout)
class DelayedLeaf(Delayed):
    __slots__ = ("_obj", "_key", "_pure", "_nout")
    def __init__(self, obj, key, pure=None, nout=None):
        self._obj = obj
        self._key = key
        self._pure = pure
        self._nout = nout
    @property
    def dask(self):
        return HighLevelGraph.from_collections(
            self._key, {self._key: self._obj}, dependencies=()
        )
    def __call__(self, *args, **kwargs):
        return call_function(
            self._obj, self._key, args, kwargs, pure=self._pure, nout=self._nout
        )
class DelayedAttr(Delayed):
    __slots__ = ("_obj", "_attr", "_key")
    def __init__(self, obj, attr):
        self._obj = obj
        self._attr = attr
        self._key = "getattr-%s" % tokenize(obj, attr, pure=True)
    def __getattr__(self, attr):
        # Calling np.dtype(dask.delayed(...)) used to result in a segfault, as
        # numpy recursively tries to get `dtype` from the object. This is
        # likely a bug in numpy. For now, we can do a dumb for if
        # `x.dtype().dtype()` is called (which shouldn't ever show up in real
        # code). See https://github.com/dask/dask/pull/4374#issuecomment-454381465
        if attr == "dtype" and self._attr == "dtype":
            raise AttributeError("Attribute %s not found" % attr)
        return super(DelayedAttr, self).__getattr__(attr)
    @property
    def dask(self):
        layer = {self._key: (getattr, self._obj._key, self._attr)}
        return HighLevelGraph.from_collections(
            self._key, layer, dependencies=[self._obj]
        )
    def __call__(self, *args, **kwargs):
        return call_function(
            methodcaller(self._attr), self._attr, (self._obj,) + args, kwargs
        )
for op in [
    operator.abs,
    operator.neg,
    operator.pos,
    operator.invert,
    operator.add,
    operator.sub,
    operator.mul,
    operator.floordiv,
    operator.truediv,
    operator.mod,
    operator.pow,
    operator.and_,
    operator.or_,
    operator.xor,
    operator.lshift,
    operator.rshift,
    operator.eq,
    operator.ge,
    operator.gt,
    operator.ne,
    operator.le,
    operator.lt,
    operator.getitem,
]:
    Delayed._bind_operator(op)
try:
    Delayed._bind_operator(operator.matmul)
except AttributeError:
    pass
def single_key(seq):

    return seq[0]


#!/usr/bin/env python3

import sys

state = [[0, 0, 0] for _ in range(64)]
top_left = (0, 0)

TERM_COLOURS = {
    (0, 0, 0): 40,
    (170, 0, 0): 41,
    (0, 170, 0): 42,
    (170, 85, 0): 43,
    (0, 0, 170): 44,
    (170, 0, 170): 45,
    (0, 170, 170): 46,
    (170, 170, 170): 47,
    (85, 85, 85): 100,
    (255, 85, 85): 101,
    (85, 255, 85): 102,
    (255, 255, 85): 103,
    (85, 85, 255): 104,
    (255, 85, 255): 105,
    (85, 255, 255): 106,
    (255, 255, 255): 107,
}

def _find_closest_colour(r, g, b):
    min_dist = 3 * 255**2
    min_color = (0, 0, 0)
    for (cr, cg, cb) in TERM_COLOURS.keys():
        score = (cr - r)**2 + (cg - g)**2 + (cb - b)**2
        if score < min_dist:
            min_dist = score
            min_color = (cr, cg, cb)
    return min_color

class SenseHat:
    def __init__(self):
        self.low_light = True

    def _print(self):
        for i, pixel in enumerate(self._get()):
            col = _find_closest_colour(*pixel)
            print('\x1b[97;{}m \x1b[39;49m'.format(TERM_COLOURS[col]), end='')
            if i % 8 == 7:
                print()

    def _get(self) -> list:
        """Return state w.r.t. to top_left rotation"""
        if top_left == (0, 0):
            return state[:]
        elif top_left == (8, 0):
            return [state[i * 8 + j] for i in range(8) for j in range(7, -1, -1)]
        elif top_left == (8, 8):
            return state[::-1]
        else:
            return [state[i*8 + j] for i in range(7, -1, -1) for j in range(8)]

    @staticmethod
    def _check_colour(r, g, b):
        if not (0 <= r < 256):
            raise ValueError('Expected r-value of [0, 256), got {}'.format(r))
        elif not (0 <= g < 256):
            raise ValueError('Expected g-value of [0, 256), got {}'.format(g))
        elif not (0 <= b < 256):
            raise ValueError('Expected b-value of [0, 256), got {}'.format(b))

    def set_rotation(self, r: int, redraw: bool = True):
        """If you're using the Pi upside down or sideways
        you can use this function to correct the orientation
        of the image being shown.
        """
        if r not in {0, 90, 180, 270}:
            raise ValueError('Expected 0, 90, 180, or 270 for `r`, got {}'.format(r))

        global top_left
        top_left = (int(r in {0, 270}) * 8, int(r > 100) * 8)
        if redraw:
            self._print()

    def flip_h(self, redraw: bool = True) -> list:
        """Flips the image on the LED matrix horizontally."""
        global top_left
        top_left = (8 - top_left[0], top_left[1])
        self._print()
        return self._get()

    def flip_v(self, redraw: bool = True) -> list:
        """Flips the image on the LED matrix vertically."""
        global top_left
        top_left = (top_left[0], 8 - top_left[1])
        self._print()
        return self._get()

    def set_pixels(self, pixel_list: list):
        """Updates the entire LED matrix based on a 64 length list of pixel values."""
        if len(pixel_list) != 64:
            raise ValueError("Expected {} pixels, only got {}".format(len(pixel_list)))
        for pixel in pixel_list:
            if len(pixel) != 3 or not all(0 <= c < 256 for c in pixel):
                raise ValueError("Expected 3 values of [0, 256), got {}".format(repr(pixel)))

        global state
        state = pixel_list
        self._print()

    def get_pixels(self) -> list:
        """The get_pixels function provides a correct representation of
        how the pixels end up in frame buffer memory
        after you've called set_pixels.
        """
        return self._get()

    def set_pixel(self, x: int, y: int, *args):
        """Sets an individual LED matrix pixel at the specified X-Y
        coordinate to the specified colour.
        """
        global state

        if not (0 <= x <= 7):
            raise ValueError('Expected element of [0, 7], got {}'.format(x))
        if not (0 <= y <= 7):
            raise ValueError('Expected element of [0, 7], got {}'.format(y))

        if len(args) == 3:
            r, g, b = args[0], args[1], args[2]
        elif len(args) == 1:
            r, g, b = args[0]
        else:
            raise ValueError('Invalid number of arguments for set_pixel')

        if not (0 <= r < 256):
            raise ValueError('Expected value of [0, 256), got {}'.format(r))
        elif not (0 <= g < 256):
            raise ValueError('Expected value of [0, 256), got {}'.format(g))
        elif not (0 <= b < 256):
            raise ValueError('Expected value of [0, 256), got {}'.format(b))

        state[x * 8 + y] = [r, g, b]
        self._print()

    def get_pixel(self, x: int, y: int) -> list:
        """Please read the docs of get_pixels"""
        global state

        if not (0 <= x <= 7):
            raise ValueError('Expected element of [0, 7], got {}'.format(x))
        if not (0 <= y <= 7):
            raise ValueError('Expected element of [0, 7], got {}'.format(y))

        return self._get[x * 8 + y]

    def load_image(self, file_path: str, redraw: bool = True) -> list:
        """Loads an image file, converts it to RGB format and displays
        it on the LED matrix. The image must be 8 x 8 pixels in size.
        """
        print('Sorry, load_image(…) is unsupported. Nothing happens …', file=sys.stderr)
        return self._get()

    def clear(self, *args):
        """Sets the entire LED matrix to a single colour, defaults to blank / off."""
        if len(args) == 0:
            r, g, b = 0, 0, 0
        elif len(args) == 1:
            r, g, b = args[0]
        elif len(args) == 3:
            r, g, b = args[0], args[1], args[2]
        else:
            raise ValueError('Invalid number of arguments for clear')

        _check_colour(r, g, b)

        global state
        for i in range(64):
            state[i] = [r, g, b]

        self._print()

    def show_message(self, text_string: str, scroll_speed: float = 0.1, text_colour: list = [255, 255, 255], back_colour: list = [0, 0, 0]):
        """Scrolls a text message from right to left across the LED matrix and
        at the specified speed, in the specified colour and background colour.
        """
        _check_colour(*text_colour)
        _check_colour(*back_colour)
        print('Sorry, show_message(…) is unsupported. Nothing happens …', file=sys.stderr)

    def show_letter(self, s: str, text_colour: list = [255, 255, 255], back_colour: list = [0, 0, 0]):
        """Scrolls a text message from right to left across the LED matrix and
        at the specified speed, in the specified colour and background colour.
        """
        if len(s) != 1:
            raise ValueError("show_letter expected one letter, got {}".format(repr(s)))

        _check_colour(*text_colour)
        _check_colour(*back_colour)

        print('Sorry, show_letter(…) is unsupported. Nothing happens …', file=sys.stderr)

    # TODO gamma


import json
import os
import stripe

from flask import Flask, render_template, jsonify, request
from dotenv import load_dotenv, find_dotenv

load_dotenv(find_dotenv())
stripe.api_key = os.getenv('STRIPE_SECRET_KEY')
stripe.api_version = os.getenv('STRIPE_API_VERSION')

app = Flask(__name__, template_folder='client')

@app.route('/')
def order():
    return render_template('order.html')

@app.route('/order_success')
def success():
    return render_template('order_success.html')

@app.route('/config', methods=['GET'])
def get_public_key():
    return jsonify({
      'publicKey': os.getenv('STRIPE_PUBLIC_KEY'),
      'basePrice': os.getenv('BASE_PRICE'),
      'currency': os.getenv('CURRENCY')
    })

@app.route('/checkout-session', methods=['GET'])
def get_checkout_session():
    id = request.args.get('sessionId')
    checkout_session = stripe.checkout.Session.retrieve(id)
    return jsonify(checkout_session)

@app.route('/create-checkout-session', methods=['POST'])
def create_checkout_session():
    data = json.loads(request.data)
    domain_url = os.getenv('DOMAIN')

    try:
        checkout_session = stripe.checkout.Session.create(
            success_url=domain_url + "/order_success?session_id={CHECKOUT_SESSION_ID}",
            cancel_url=domain_url + "/",
            payment_method_types=["card"],
            line_items=[
                {
                    "name": data['name'],
                    "images": [domain_url + data['img']],
                    "quantity": data['quantity'],
                    "currency": data['currency'],
                    "amount": int(data['amount'])
                }
            ]
        )
        return jsonify({'sessionId': checkout_session['id']})
    except Exception as e:
        return jsonify(e), 40

@app.route('/webhook', methods=['POST'])
def webhook_received():
    webhook_secret = os.getenv('STRIPE_WEBHOOK_SECRET')
    request_data = json.loads(request.data)

    if webhook_secret:
        signature = request.headers.get('stripe-signature')
        try:
            event = stripe.Webhook.construct_event(
                payload=request.data, sig_header=signature, secret=webhook_secret)
            data = event['data']
        except Exception as e:
            return e
        event_type = event['type']
    else:
        data = request_data['data']
        event_type = request_data['type']
    data_object = data['object']

    if event_type == 'payment_intent.failed' or \
        data_object['status'] != 'succeeded':
            return jsonify({
                'status': 'failed',
                'amount_received': None,
            }), 200

    return jsonify({
                'status': 'succeeded',
                'amount_received': data_object['amount_received'],
            }), 200

if __name__ == '__main__':
    app.run()


#!/usr/bin/python
# -*- coding: utf-8 -*-

import os
import keras
from keras.layers import Dense
import pickle
import numpy as np

BASE_DIR = '/data1/ceph/yzchen'

def unpickle(file):
    with open(file, 'rb') as fo:
        dict = pickle.load(fo, encoding='bytes')
    return dict

def load_data(source):
    if source == 'cifar-10':
        heigth = 32
        width = 32
        channels = 3
        raw_data = unpickle(os.path.join(BASE_DIR, 'datasets/cf10/data_batch_1'))
        x_train = np.array(raw_data[b'data'])
        y_train = np.array(raw_data[b'labels'])
        for i in range(2,6):
            raw_data = unpickle(os.path.join(BASE_DIR, 'datasets/cf10/data_batch_'+str(i)))
            x_train = np.concatenate([x_train, np.array(raw_data[b'data'])])
            y_train = np.concatenate([y_train, np.array(raw_data[b'labels'])])
        x_train = x_train.reshape(x_train.shape[0], channels, heigth, width)\
            .transpose([0,2,3,1]).astype('float32') / 255.
        y_train = keras.utils.to_categorical(y_train)

        raw_data = unpickle(os.path.join(BASE_DIR, 'datasets/cf10/test_batch'))
        x_test = np.array(raw_data[b'data'])
        y_test = np.array(raw_data[b'labels'])
        x_test = x_test.reshape(x_test.shape[0], channels, heigth, width)\
                    .transpose([0,2,3,1]).astype('float32') / 255.
        y_test = keras.utils.to_categorical(y_test)

        return x_train, y_train, x_test, y_test

x_train, y_train, x_test, y_test = load_data('cifar-10')

model = keras.models.Sequential()
model.add(Dense(100, activation='relu', input_shape=(32*32*3,)))
model.add(Dense(100, activation='relu'))
model.add(Dense(10, activation='softmax'))
model.summary()

model.compile(loss='categorical_crossentropy',
              optimizer='sgd',
              metrics=['accuracy'])

history = model.fit(x_train.reshape(-1,32*32*3), y_train, validation_split=0.1, batch_size=32, epochs=10)
print(model.evaluate(x_test.reshape(-1,32*32*3), y_test))


class Node():
    def __init__(self,item):
        self.elem=item
        self.lchild=None
        self.rchild=None

class Tree():
    def __init__(self):
        self.root=None

    def add(self,item):
        node=Node(item)
        if self.root is None:
            self.root=node
            return
        queue=[self.root]
        while queue:
            cur_node = queue.pop(0)#pop---删除第一个元素
            if cur_node.lchild is None:
                cur_node.lchild=node
                return
            else:
                queue.append(cur_node.lchild)
            if cur_node.rchild is None:
                cur_node.rchild=node
                return
            else:
                queue.append(cur_node.rchild)

    def breadth_travel(self):
        if self.root is None:
            return
        queue=[self.root]
        while queue:
            cur_node = queue.pop(0)
            print(cur_node.elem, end=" ")
            if cur_node.lchild is not None:
                queue.append(cur_node.lchild)
            if cur_node.rchild is not None:
                queue.append(cur_node.rchild)

    def preorder(self,node):
        if node is None:
            return
        print(node.elem, end=" ")
        self.preorder(node.lchild)
        self.preorder(node.rchild)

    def preorder_iter(self):
        if self.root is None:
            return
        stack=[]
        stack.append(self.root)
        while stack:
            node=stack.pop()
            if node:
                print(node.elem, end=" ")
                stack.append(node.rchild)
                stack.append(node.lchild)

    def inorder(self,node):
        if node is None:
            return
        self.inorder(node.lchild)
        print(node.elem, end=" ")
        self.inorder(node.rchild)

    def inorder_iter(self):
        if self.root is None:
            return
        stack=[]
        root=self.root
        while root or stack:
            if root:
                stack.append(root)
                root = root.lchild
            else:
                root=stack.pop()
                print(root.elem, end=" ")
                root=root.rchild

    def postorder(self,node):
        if node is None:
            return
        self.postorder(node.lchild)
        self.postorder(node.rchild)
        print(node.elem, end=" ")

    def postorder_iter(self):
        if self.root is None:
            return
        stack=[]
        prev=None
        root = self.root
        while root or stack:
            while root:
                stack.append(root)
                root = root.lchild
            root=stack.pop()
            if not root.rchild or root.rchild==prev:
                print(root.elem, end=" ")
                prev=root
                root=None
            else:
                stack.append(root)
                root=root.rchild

    def isSymmetric(self):
        def ismirror(A,B):
            if A is None and B is None : return True
            if A is None or B is None : return False
            if A.elem != B.elem : return False
            return ismirror(A.lchild,B.rchild) and ismirror(A.rchild,B.lchild)
        return ismirror(self.root.lchild,self.root.rchild) if self.root else True
    #     list=self.inord(self.root)
    #     print(list)
    #     n=len(list)
    #     if n % 2 == 0: return False
    #     while len(list)!=1:
    #         pre,post=list.pop(0),list.pop()
    #         if pre!=post:
    #             return False
    #     if len(list)==1:return True
    #
    #
    #
    # def inord(self,root):
    #     if root is None:
    #         return True
    #     stack=[]
    #     list=[]
    #     while root or stack:
    #         if root:
    #             stack.append(root)
    #             root=root.lchild
    #         else:
    #             root=stack.pop()
    #             if root.elem != None:
    #                 list.append(root.elem)
    #             else:
    #                 list.append(-1)
    #             root=root.rchild
    #     return list

if __name__ == "__main__":
    tree = Tree()
    tree.add(1)
    tree.add(2)
    tree.add(2)
    tree.add(2)
    tree.add(None)
    tree.add(2)
    tree.breadth_travel()
    print(" ")
    tree.inorder_iter()
    print(' ')
    print(tree.isSymmetric())


# In the name of God
# -*- coding: utf-8 -*-
# Windows and Panels main Frame File
#! /usr/bin/env python

import wx
import wx.aui as wxaui
from Config.Init import *

import GUI.proman as pro

_ = wx.GetTranslation

class BGPanel(wx.Panel):
	def __init__( self,parent,BGfile ):
		wx.Panel.__init__ ( self, parent=parent, id = wx.ID_ANY, pos = wx.DefaultPosition, size = wx.DefaultSize, style = wx.TAB_TRAVERSAL )

		#bSizer2 = wx.BoxSizer( wx.VERTICAL )

		self.BGfile = BGfile

		self.SetBackgroundStyle(wx.BG_STYLE_ERASE)
		self.Bind(wx.EVT_ERASE_BACKGROUND, self.OnEraseBackground)

		#self.setmenu()

		#bSizer2.Add( self.m_bitmap4, 5, wx.ALIGN_CENTER|wx.ALL, 5 )

		#self.SetSizer( bSizer2 )
		#self.Layout()

		# Connect Events

		#self.Bind( wx.EVT_RIGHT_DOWN, self.m_bitmap4OnContextMenu )
		#self.Bind( wx.EVT_CONTEXT_MENU, self.setmenu)
		self.Bind(wxaui.EVT_AUI_RENDER, self.OnEraseBackground)

	def __del__( self ):
		pass

	# Virtual event handlers, overide them in your derived class

	def m_bitmap4OnContextMenu( self, event ):
		self.PopupMenu(self.m1)

		#print (self.itm3.IsChecked(),self.itm2.IsChecked())
		#print self.itm3.IsChecked(),self.itm4.IsChecked()
	'''
	def setmenu(self,event):
		self.MnuDic = { 1: [_(u'Menu Change'),9999] ,2:[_(u'Toolbar Change'),9998],3:[_(u'Panes Change'),9997],4:[u'',0],
					    5:[_(u'Databases...'),9996],6:[_(u'Programs...'),9995],7:[_(u'Add Tools...'),9994],8:[u'',0],
						9:[_(u'ML Design...'),9990],10:[u'',0],11:[_(u'Settings...'),9992] }
		self.m1 = wx.Menu()

		self.itms = []
		i = 0
		for itm in self.MnuDic :
			self.Bind(wx.EVT_MENU, self.OnPopupOne, id=itm)
			if self.MnuDic[itm][0] == u'':
				self.m1.AppendSeparator()
			else:
				#self.itms.append( wx.MenuItem(self.m1, wx.ID_ANY, MnuDic[itm][0], wx.EmptyString) )
				self.m1.Append(itm, self.MnuDic[itm][0])
				#self.m1.Append(itm, self.itms[i])
				#self.Bind(wx.EVT_MENU, self.OnPopupOne, id=MnuDic[itm][1])
				i = i + 1

		self.PopupMenu(self.m1)
		self.m1.Destroy()

	def OnPopupOne(self, event):
		#print(event,event.GetId())
		pmid = event.GetId()
		a = pro.DoProgram(self.MnuDic[pmid][1],'A')
		s = a.size() if 'size' in dir(a) else ()
		win1 = wx.Frame(self, -1)
		win1.SetSize(s)
		a.main(win1)
    '''
	def OnEraseBackground(self, evt):
		# yanked from ColourDB.py
		#print(evt)
		dc = evt.GetDC()
		if not dc:
			dc = wx.ClientDC(self)
			rect = self.GetUpdateRegion().GetBox()
			#dc.SetClippingRect(rect)
			dc.SetClippingRegion(rect)
		dc.Clear()
		#bmp = wx.Bitmap(PICS_PATH+self.BGfile)
		bmp = wx.Bitmap(self.BGfile)
		img = bmp.ConvertToImage()
		img2 = img.Scale(wx.GetDisplaySize()[0],wx.GetDisplaySize()[1])
		bmp2 = img2.ConvertToBitmap()
		#print(dir(img2))
		#print(bmp2.GetWidth(),bmp2.GetHeight())
		#print(wx.GetDisplaySize())
		dc.DrawBitmap(bmp2, 0, 0)

	def ChangeBackGround(self):
		dc = wx.ClientDC(self)
		rect = self.GetUpdateRegion().GetBox()
		dc.SetClippingRegion(rect)
		dc.Clear()
		bmp = wx.Bitmap(self.BGfile)
		img = bmp.ConvertToImage()
		img2 = img.Scale(wx.GetDisplaySize()[0], wx.GetDisplaySize()[1])
		bmp2 = img2.ConvertToBitmap()
		dc.DrawBitmap(bmp2, 0, 0)
		self.Refresh()


import logging
import os
import torch
from torch.utils.data import DataLoader
from tqdm import tqdm
from transformers import AutoModelForSequenceClassification, AutoTokenizer, Trainer, TrainingArguments

from utils import TextDataset, compute_metrics, move_dict_to_device, separate_labels

def train_classification_model(args, train_data, val_data):
    """Trains classification model."""

    classification_model_path = os.path.join(args.output_dir, args.cls_model_save_name)
    if not args.cls_overwrite_output_dir:
        try:
            logging.info("Trying to load classification model if it exists..")
            device = torch.device("cuda")
            model = AutoModelForSequenceClassification.from_pretrained(classification_model_path).to(device)
            tokenizer = AutoTokenizer.from_pretrained(classification_model_path)
            logging.info(f"Successfully loaded classification model and tokenizer from {classification_model_path}.")
            return {"model": model, "tokenizer": tokenizer}

        except OSError:
            logging.info("Classification model not found. Will need to train new model.")
            pass

    logging.info(f"Loading pretrained model {args.cls_model}...")
    tokenizer = AutoTokenizer.from_pretrained(args.cls_model)
    model = AutoModelForSequenceClassification.from_pretrained(args.cls_model).to('cuda')
    logging.info("Model and tokenizer loaded.")

    logging.info("Tokenizing and creating validation and train dataset..")
    train_texts, train_labels = separate_labels(train_data)
    train_dataset = TextDataset(args, tokenizer, train_texts, train_labels)
    val_texts, val_labels = separate_labels(val_data)
    val_dataset = TextDataset(args, tokenizer, val_texts, val_labels)
    logging.info(f"Created train ({len(train_dataset)} examples) and valid ({len(val_dataset)} examples) dataset.")

    training_args = TrainingArguments(
        output_dir=classification_model_path,
        overwrite_output_dir=True,
        evaluation_strategy="steps",
        eval_steps=500,
        per_device_train_batch_size=args.cls_per_device_train_batch_size,
        per_device_eval_batch_size=args.cls_per_device_eval_batch_size,
        learning_rate=args.cls_learning_rate,
        num_train_epochs=args.cls_num_train_epochs,
        logging_strategy="steps",
        logging_steps=500,
        logging_dir=os.path.join(args.output_dir, "cls_logs", args.exp_name),
        disable_tqdm=False,
        load_best_model_at_end=True,
        metric_for_best_model="f1_score",
        report_to=["tensorboard"],
    )

    trainer = Trainer(
        model=model,
        args=training_args,
        train_dataset=train_dataset,
        eval_dataset=val_dataset,
        tokenizer=tokenizer,
        compute_metrics=compute_metrics,
    )

    logging.info("Training classification model..")
    trainer.train()

    logging.info(f"Saving model to {classification_model_path}")
    trainer.save_model(classification_model_path)

    return {"model": model, "tokenizer": tokenizer}

def run_classification_model(args, classification_model, texts, progress_bar=False):
    """Runs classification model and returns predictions."""

    if len(texts) == 0:
        return []

    model, tokenizer = classification_model["model"], classification_model["tokenizer"]
    model.eval()

    text_dataset = TextDataset(args, tokenizer, texts)
    dataloader = DataLoader(
        text_dataset, batch_size=args.cls_per_device_eval_batch_size, shuffle=False, num_workers=4, pin_memory=True
    )
    if progress_bar:
        dataloader = tqdm(dataloader)

    predictions = []
    for batch in dataloader:
        with torch.no_grad():
            move_dict_to_device(batch, "cuda")
            logits = model(**batch).logits
            batch_predictions = logits.argmax(dim=1).tolist()
            predictions.extend(batch_predictions)

    return predictions

def find_leakages(args, classification_model, data, cache=None):
    """Finds the leakages given the classification model and the data."""

    texts = []
    labels = []
    for i in data:
        y, x = i.split(sep="\t")
        texts.append(x)
        labels.append(int(y))

    if cache is None:
        predictions = run_classification_model(args, classification_model, texts, progress_bar=True)
    else:
        predictions = [cache["prediction_map"][text] for text in texts]

    leakages = []
    filter_candidates = 0
    for text, label, prediction in zip(texts, labels, predictions):
        if prediction == 1:
            filter_candidates += 1
        elif label == 1 and prediction == 0:
            leakages.append(text)
        else:
            continue

    return leakages, filter_candidates

def get_embedding_model(model):
    """Gets base transformer model from SequenceClassification Model."""

    basenames = ["bert", "roberta", "distilbert"]
    for basename in basenames:
        if hasattr(model, basename):
            return getattr(model, basename)

    raise ValueError("Couldn't find the base model.")

def compute_embeddings(args, texts, embedding_model, convert_to_numpy=False, progress_bar=False):
    """Computes embeddings of texts given an embedding model."""

    model, tokenizer = embedding_model["model"], embedding_model["tokenizer"]
    model.eval()
    text_dataset = TextDataset(args, tokenizer, texts)
    dataloader = DataLoader(
        text_dataset, batch_size=args.cls_per_device_eval_batch_size, shuffle=False, num_workers=4, pin_memory=True
    )
    if progress_bar:
        dataloader = tqdm(dataloader)

    embeddings = []

    for batch in dataloader:
        with torch.no_grad():
            move_dict_to_device(batch, "cuda")
            batch_embeddings = model(**batch, output_hidden_states=True).hidden_states[-1][:, 0, :]
            if convert_to_numpy:
                batch_embeddings = batch_embeddings.cpu()
            embeddings.append(batch_embeddings)
    embeddings = torch.cat(embeddings)

    if convert_to_numpy:
        embeddings = embeddings.numpy()

    return embeddings


# -*- coding: utf-8 -*-
# (c) Copyright IBM Corp. 2019. All Rights Reserved.
# pragma pylint: disable=unused-argument, no-self-use

import requests
from resilient_lib.components.integration_errors import IntegrationError

class RequestsCommon:
    """
    This class represents common functions around the use of the requests package for REST based APIs.
    It incorporates the app.config section "integrations" which can be used to define a common set of proxies
    for use by all functions using this library:

    [integrations]
    http_proxy=
    https_proxy=

    Similar properties may exist in the function's section which would override the [integrations] properties.
    """
    def __init__(self, opts=None, function_opts=None):
        # capture the properties for the integration as well as the global settings for all integrations for proxy urls
        self.integration_options = opts.get('integrations', None) if opts else None
        self.function_opts = function_opts

    def get_proxies(self):
        """ proxies can be specified globally for all integrations or specifically per function """
        proxies = None
        if self.integration_options and (self.integration_options.get("http_proxy") or self.integration_options.get("https_proxy")):
            proxies = {'http': self.integration_options.get("http_proxy"), 'https': self.integration_options.get("https_proxy")}

        if self.function_opts and (self.function_opts.get("http_proxy") or self.function_opts.get("https_proxy")):
            proxies = {'http': self.function_opts.get("http_proxy"), 'https': self.function_opts.get("https_proxy")}

        return proxies

    def execute_call(self, verb, url, payload={}, log=None, basicauth=None, verify_flag=True, headers=None,
                     proxies=None, timeout=None, resp_type='json', callback=None):
        """
        Function: perform the http API call. Different types of http operations are supported:
        GET, HEAD, PATCH, POST, PUT, DELETE
        Errors raise IntegrationError
        If a callback method is provided, then it's called to handle the error

        Using the 'json' parameter in the request will change the Content-Type in the header to application/json.
        If the headers you send include a specific Content-Type, your payload will be send as 'data' and not 'json'.

        :param verb: GET, HEAD, PATCH, POST, PUT, DELETE
        :param url:
        :param basicauth: used for basic authentication - (user, password)
        :param payload:
        :param log: optional log statement
        :param verify_flag: True/False - False used for debugging generally
        :param headers: dictionary of http headers
        :param proxies: http and https proxies for call
        :param timeout: timeout before call should abort
        :param resp_type: type of output to return: json, text, bytes
        :param callback: callback routine used to handle errors
        :return: json of returned data
        """

        try:
            (payload and log) and log.debug(payload)

            if verb.lower() not in ('get', 'post', 'put', 'patch', 'delete', 'head'):
                raise IntegrationError("unknown verb {}".format(verb))

            if proxies is None:
                proxies = self.get_proxies()

            if verb.lower() == 'post':
                if verify_headers(headers):
                    # If headers dict specifies Content-Type,
                    # pass the payload to the data argument.
                    # Use Content-Type specified in headers.
                    resp = requests.request(verb.upper(), url, verify=verify_flag, headers=headers, data=payload,
                                            auth=basicauth, timeout=timeout, proxies=proxies)
                else:
                    # If headers dict does not specify Content-Type,
                    # pass payload to the json argument.
                    # Content-Type will automatically set to application/json.
                    resp = requests.request(verb.upper(), url, verify=verify_flag, headers=headers, json=payload,
                                            auth=basicauth, timeout=timeout, proxies=proxies)
            else:
                resp = requests.request(verb.upper(), url, verify=verify_flag, headers=headers, params=payload,
                                        auth=basicauth, timeout=timeout, proxies=proxies)

            if resp is None:
                raise IntegrationError('no response returned')

            # custom handler for response handling?
            if callback:
                return callback(resp)

            # standard error handling
            if resp.status_code >= 300:
                # get the result
                # log resp.status_code in case resp.text isn't available
                raise IntegrationError(
                    "status_code: {}, msg: {}".format(resp.status_code, resp.text if resp.text else "N/A"))

            # check if anything returned
            log and log.debug(resp.text)

            # get the result
            if resp_type == 'json':
                r = resp.json()
            elif resp_type == 'text':
                r = resp.text
            elif resp_type == 'bytes':
                r = resp.content
            else:
                raise IntegrationError("incorrect response type: {}".format(resp_type))

            # Produce a IntegrationError with the return value
            return r      # json object needed, not a string representation
        except Exception as err:
            msg = str(err)
            log and log.error(msg)
            raise IntegrationError(msg)

def verify_headers(headers):
    """
    Verify if headers dict includes 'Content-Type' key.
    :param headers:
    :return: True or False
    """
    if headers is None:
        return False

    for key in headers:
        if key.lower() == "content-type":
            return True
    return False


from app import app, db, db_tools
from app.models.users import User
from app.models.events import EventType, Event, EventSlot
from app.models.booking import Booking
from app.models.payments import Promotion, Refund
from app.forms.forms import LoginForm, RegistrationForm, SearchForm, \
							BookingForm, PaymentForm, AccountUpdateForm
from flask import render_template, redirect, url_for, request, session, jsonify
from flask_login import current_user, login_user, logout_user
from flask import flash
from datetime import datetime

@app.login_manager.user_loader
def load_user(id_):
	return User.query.get(int(id_))

@app.route('/')
@app.route('/index')
@app.route('/search')
def index():
	return redirect(url_for('get_events', option='title'))

@app.route('/search/<option>', methods=['GET', 'POST'])
def get_events(option):
	form = SearchForm()
	form.search_type.data = option
	if option == 'date':
		form.search_field = form.DATE_FIELD
	elif option == 'price':
		form.search_field = form.PRICE_FIELD
	elif option == 'type':
		form.search_field = form.TYPE_FIELD

	if form.validate_on_submit():
		search_type = form.search_type.data
		if option == 'date' or option == 'price':
			keyword = form.search_field.data
		else:
			keyword = str(form.search_field.data).strip()

		if len(keyword) > 0:
			return render_template(
				'index.html', title='Event Booking System', form=form,
				event_list=db_tools.get_event_list(search_type, keyword))

	return render_template('index.html', title='Event Booking System',
						   form=form, event_list=db_tools.get_event_list())

@app.route('/event/details/<eid>')
def event_details(eid):
	# Redirect to homepage if no event with specified eid
	records = db_tools.details_query(eid)
	if not records:
		return redirect(url_for('index'))

	event = db_tools.format_events(records)
	return render_template('details.html',
						   title='EBS: {}'.format(event['title']),
						   event=event)

@app.route('/login', methods=['GET', 'POST'])
def login():
	# if already logged in redirect to homepage
	if current_user.is_authenticated:
		return redirect(url_for('index'))

	form = LoginForm()
	if form.validate_on_submit():
		user = User.query.filter_by(username=form.username.data).first()
		login_user(user, remember=form.remember_me.data)
		db_tools.add_login_record()
		session['payment_due'] = None

		# return regular users to homepage; staff users to admin page
		if user.is_regular():
			return redirect(url_for('index'))
		else:
			return redirect(url_for('admin.index'))

	# render login page
	return render_template('login.html', title='EBS: Sign In', form=form)

@app.route('/logout')
def logout():
	session['payment_due'] = None
	db_tools.add_logout_record()
	logout_user()
	return redirect(url_for('index'))

@app.route('/register', methods=['GET', 'POST'])
def register():
	# if already logged in redirect to homepage
	if current_user.is_authenticated:
		return redirect(url_for('index'))

	form = RegistrationForm()
	if form.validate_on_submit():
		# Add new user record to db
		new_user = User(username=form.username.data, email=form.email.data, group_id=1)
		new_user.set_password(form.password.data)
		db.session.add(new_user)
		db.session.commit()

		# Autologin and redirect new user
		login_user(new_user)
		db_tools.add_login_record()
		session['payment_due'] = None
		return redirect(url_for('index'))

	return render_template('register.html', title='EBS: Account Registration', form=form)

@app.route('/my_account', methods=['GET', 'POST'])
def my_account():
	# Redirect to other endpoint if pre-reqs not met
	if not current_user.is_authenticated:
		return redirect(url_for('index'))

	update_form = AccountUpdateForm()
	# Update email if validation checks passed
	if 'update_email-update_email' in request.form \
		and update_form.update_email.validate_on_submit():
			current_user.email = update_form.update_email.email.data
			db.session.commit()
			flash('Email updated successfully')
	# Update password if validation checks passed
	elif 'update_password-update_password' in request.form \
		 and update_form.update_password.validate_on_submit():
			current_user.set_password(update_form.update_password.new_password.data)
			db.session.commit()
			flash('Password updated successfully')

	# Reset form fields
	update_form.update_email.email.data = None
	update_form.update_password.old_password.data = None
	update_form.update_password.new_password.data = None
	update_form.update_password.confirm_password.data = None
	return render_template('my_account.html', update_form=update_form)

@app.route('/my_bookings')
def my_bookings():
	# Redirect to other endpoint if pre-reqs not met
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	elif current_user.is_admin():
		return redirect(url_for('index'))

	records = Booking.query.join(EventSlot, Booking.event_slot_id == EventSlot.slot_id)\
						   .filter(Booking.user_id == current_user.user_id,
								   Booking.quantity > 0,
								   EventSlot.event_date > datetime.now()).all()
	bookings = db_tools.format_bookings(records)
	return render_template('my_bookings.html', bookings=bookings)

@app.route('/my_bookings/add_to/<bid>/<delta>')
def add_to_booking(bid, delta):
	# Redirect to other endpoint if pre-reqs not met
	booking = Booking.query.get(bid)
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	elif current_user.user_id != booking.user_id:
		return redirect(url_for('index'))

	# Save payment details in current session object
	session['payment_due'] = {'event_id' : booking.slot.event.event_id,
							  'user_id' : current_user.user_id,
							  'slot_id' : booking.event_slot_id,
							  'quantity' : int(delta),
							  'price' : booking.slot.event.price,
							  'booking_type' : 'update',
							  'booking_id' : bid}
	return redirect(url_for('payment'))

@app.route('/my_bookings/cancel/<bid>/<delta>')
def cancel_booking(bid, delta):
	# Redirect to other endpoint if pre-reqs not met
	booking = Booking.query.get(bid)
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	elif current_user.user_id != booking.user_id:
		return redirect(url_for('index'))

	# Throw error if requested refund quantity exceeds total booking quantity
	request_balance = int(delta)
	if request_balance > booking.quantity:
		return render_template('error.html', e_msg='Error in refund quantity.',
							   page='your bookings page',
							   redirect_url=url_for('my_bookings'))

	# Loop through payments to refund as much request_balance as possible
	refund_amount = 0.0
	for payment in booking.payments:
		if request_balance > 0:
			payment_avail_refunds = payment.quantity - payment.total_refund_qty
			if payment_avail_refunds > 0:
				# Add new refund record to db
				new_refund_qty = min(payment_avail_refunds, request_balance)
				new_refund = Refund(quantity=new_refund_qty,
									payment_id=payment.payment_id)
				db.session.add(new_refund)

				# Update cumulative changes
				booking.quantity -= new_refund_qty
				refund_amount += payment.amount / payment.quantity * new_refund_qty
				request_balance -= new_refund_qty

	# Rollback db and throw error if created refunds exceed total booking quantity
	if request_balance < 0:
		db.session.rollback()
		return render_template('error.html', e_msg='Refund processing error.',
							   page='your bookings page',
							   redirect_url=url_for('my_bookings'))

	# Commit changes and redirect to confirmation page
	db.session.commit()
	details = db_tools.format_bookings([booking])[0]
	return render_template('confirm_refund.html', amount=refund_amount,
						   qty=delta, details=details)

@app.route('/booking/<eid>', methods=['GET', 'POST'])
def booking(eid):
	# Redirect to other endpoint if pre-reqs not met
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	elif current_user.is_admin():
		return redirect(url_for('event_details', eid=eid))
	event = Event.query.get(eid)
	if not event or not event.is_launched:
		return redirect(url_for('index'))

	# Create booking form
	form = BookingForm()
	form.preload(current_user, event)
	if form.is_submitted():
		# Load payment details into session
		session['payment_due'] = {'event_id' : eid,
								  'user_id' : current_user.user_id,
								  'slot_id' : form.time.data,
								  'quantity' : form.count.data,
								  'price' : round(event.price,2),
								  'booking_type' : 'new'}
		return redirect(url_for('payment'))

	return render_template('booking.html', form=form, eid=eid)

@app.route('/booking/<eid>/<date>')
def booking_slot(eid, date):
	timings = []

	records = db_tools.event_times_query(eid, date)
	for rec in records:
		# Only add timings for slots that still have available seats
		if rec.vacancy > 0:
			timing = {}
			timing['slot_id'] = rec.slot_id
			timing['time'] = datetime.strptime(rec.time, '%H:%M:%S')\
									 .strftime('%I:%M %p')
			timing['vacancy'] = EventSlot.query.get(rec.slot_id).vacancy
			timings.append(timing)

	return jsonify({ 'timings' : timings })

@app.route('/booking/vacancy/<sid>')
def booking_vacancy(sid):
	vacancy = EventSlot.query.get(sid).vacancy
	return jsonify({ 'vacancy' : vacancy })

@app.route('/booking/payment', methods=['GET', 'POST'])
def payment():
	# Redirect to other endpoint if pre-reqs not met
	if not current_user.is_authenticated:
		return redirect(url_for('login'))
	elif current_user.is_admin() or session['payment_due'] is None:
		return redirect(url_for('index'))

	# Retrieve payment details from session object
	payment = session['payment_due']
	payment['title'] = Event.query.get(payment['event_id']).title
	payment['time'] = EventSlot.query.get(payment['slot_id']).event_date\
							   .strftime('%d %b %Y, %I:%M %p')
	if not 'promo_id' in payment:
		payment['promo_id'] = None

	form = PaymentForm()
	form.promo.promo_event_id.data = payment['event_id']

	# Promotion code applied
	if 'promo-apply_promo' in request.form and form.promo.validate_on_submit():
		promo_record = Promotion.query.filter(Promotion.promo_code ==
											  form.promo.promo_code.data).first()
		base_price = Event.query.get(payment['event_id']).price
		discount = promo_record.promo_percentage
		payment['price'] =  base_price * (1-discount/100)
		payment['promo_id'] = promo_record.promotion_id
		form.promo.current_code_applied.data = form.promo.promo_code.data
		form.promo.promo_code.data = None
	# Payment submitted
	elif 'submit' in request.form and form.validate_on_submit():
		# Throw error if booking quantity more than current slot vacancy
		current_vacancy = EventSlot.query.get(payment['slot_id']).vacancy
		if payment['quantity'] > current_vacancy:
			session['[payment_due'] = None
			return render_template(
				'error.html',
				e_msg='{}{}'.format('Number of tickets exceed available seats. ',
									'Please edit your booking.'),
				page='booking page',
				redirect_url=url_for('booking', eid=payment['event_id']) )

		# Update db
		db_tools.update_booking_payment(form=form, payment=payment)

		# Clear session object and confirm booking
		session['payment_due'] = None
		is_new_booking = payment['booking_type'] == 'new'
		return render_template('confirm_booking.html',
							   redirect_homepage=is_new_booking)

	return render_template('payment.html', form=form, booking_details=payment)


import asyncio
import sys, traceback
from threading import Lock
import json
from uuid import uuid4
from copy import deepcopy

from flask import Flask, request, jsonify

from root import ROOT_DIR
from src.python.chess.chess_interop import format_move
from src.python.chess.chess_state import fen_to_state
from src.python.chess.chess_agency import ChessAgent
from src.python.primitive import highest

serve_folder = ROOT_DIR + "/serve"
app = Flask(__name__, static_url_path="/static", static_folder=serve_folder)
app.config["SEND_FILE_MAX_AGE_DEFAULT"] = 0

analysis_lock = Lock()
loop = asyncio.get_event_loop()
shared = {
    "agent": None
}

@app.route("/")
def root():
    return app.send_static_file("chess.html")

@app.route("/api/analysis", methods=["POST"])
def create_analysis():
    request_id = str(uuid4())

    if analysis_lock.acquire(timeout=100):
        body = request.get_json()
        print(f"Request {request_id[:6]} for POST /api/analysis")
        print(json.dumps(body))
        out = {
            "result": None
        }
        chess_state = fen_to_state(body["fen"])
        shared["agent"] = ChessAgent(int(body["depth"]))

        def anaylsis():
            out["result"] = shared["agent"].start_game(chess_state)
        try:
            future = loop.run_in_executor(None, anaylsis)
            loop.run_until_complete(future)
        except Exception:
            print("Failed create_analysis: ")
            traceback.print_exc(file=sys.stdout)
        finally:
            analysis_lock.release()

        (score, best_path) = out["result"]
        next_move = next(best_path)
        next_state = deepcopy(shared["agent"].game)
        next_state.apply(next_move)
        next_fen = next_state.to_fen()
        resp = {
            "score": score,
            "move": format_move(next_move),
            "fen": next_fen,
            "resign": abs(score) == highest - 1,
            "done": next_state.is_done
        }
        print(f"Reponse {request_id[:6]} for POST /api/analysis")
        print(json.dumps(resp))
        return jsonify(resp)

@app.route("/api/analysis", methods=["DELETE"])
def stop_analysis():
    request_id = str(uuid4())
    print(f"Request {request_id[:6]} for DELETE /api/analysis")
    if shared["agent"] is not None:
        shared["agent"].stop()
    print(f"Request {request_id[:6]} for DELETE /api/analysis")
    return "Ok"

if __name__ == "__main__":
    app.run(debug=True)


# 897. 海岛城市

# 问题
# Given a matrix of size n x m, the elements in the matrix are 0、1、2. 0 for the sea, 1 for the island, and 2 for the city on the island(You can assume that 2 is built on 1, ie 2 also represents the island).
# If two 1 are adjacent, then these two 1 belong to the same island. Find the number of islands with at least one city.

# 注意事项
# 我们只考虑上下左右为相邻。
# n <= 100，m <= 100。
# 你可以假设矩阵的四个边都被海包围。

# 样例
# Given mat =
# [
#      [1,1,0,0,0],
#      [0,1,0,0,1],
#      [0,0,0,1,1],
#      [0,0,0,0,0],
#      [0,0,0,0,1]
# ]
# , return 0.

# Explanation:
# There are 3 islands, but none of them contain cities.
# Given mat =
# [
#      [1,1,0,0,0],
#      [0,1,0,0,1],
#      [0,0,2,1,2],
#      [0,0,0,0,0],
#      [0,0,0,0,2]
# ]
# , return 2.

# Explanation:
# There are 3 islands, and two of them have cities.

class Solution:
    """
    @param grid: an integer matrix
    @return: an integer
    """
    def numIslandCities(self, grid):
        # Write your code here
        count=0
        for n in range(0,len(grid)):
            for m in range(0,len(grid[0])):
                if grid[n][m]==2:

                    count+=1
        return count


# taken from pyramid.compat

from __future__ import absolute_import
import sys
import six

# True if we are running on Python 3.
PY3 = sys.version_info[0] == 3

if PY3:  # pragma: no cover
    text_type = str
else:
    text_type = six.text_type

if PY3:
    string_types = (str,)
else:
    string_types = (six.string_types,)