""" Transforms Factory

Adapted from TIMM / Ross Wightman:
https://github.com/rwightman/pytorch-image-models/blob/7c67d6aca992f039eece0af5f7c29a43d48c00e4/timm/data/transforms_factory.py#L44

"""
import math

import torch
from torchvision import transforms

from timm.data.constants import IMAGENET_DEFAULT_MEAN, IMAGENET_DEFAULT_STD, DEFAULT_CROP_PCT

# from timm.data.auto_augment import rand_augment_transform, augment_and_mix_transform, auto_augment_transform

# use custom version for cv2 instead of PIL
# from dataloaders.autoaugment.autoaug_cv2 import rand_augment_transform, augment_and_mix_transform, auto_augment_transform

from timm.data.transforms import str_to_interp_mode, str_to_pil_interp, RandomResizedCropAndInterpolation, ToNumpy
from timm.data.random_erasing import RandomErasing

import random
import math
import re
from PIL import Image, ImageOps, ImageEnhance, ImageChops
import PIL
import numpy as np

from numba import njit
from ffcv.pipeline.operation import Operation, AllocationQuery
from ffcv.pipeline.compiler import Compiler
from ffcv.writer import DatasetWriter

""" AutoAugment, RandAugment, and AugMix for PyTorch
This code implements the searched ImageNet policies with various tweaks and improvements and
does not include any of the search code.
AA and RA Implementation adapted from:
    https://github.com/tensorflow/tpu/blob/master/models/official/efficientnet/autoaugment.py
AugMix adapted from:
    https://github.com/google-research/augmix
Papers:
    AutoAugment: Learning Augmentation Policies from Data - https://arxiv.org/abs/1805.09501
    Learning Data Augmentation Strategies for Object Detection - https://arxiv.org/abs/1906.11172
    RandAugment: Practical automated data augmentation... - https://arxiv.org/abs/1909.13719
    AugMix: A Simple Data Processing Method to Improve Robustness and Uncertainty - https://arxiv.org/abs/1912.02781
Hacked together by / Copyright 2019, Ross Wightman
"""

_PIL_VER = tuple([int(x) for x in PIL.__version__.split('.')[:2]])

_FILL = (128, 128, 128)

_LEVEL_DENOM = 10.  # denominator for conversion from 'Mx' magnitude scale to fractional aug level for op arguments

_HPARAMS_DEFAULT = dict(
    translate_const=250,
    img_mean=_FILL,
)

_RANDOM_INTERPOLATION = (Image.BILINEAR, Image.BICUBIC)

def _interpolation(kwargs):
    interpolation = kwargs.pop('resample', Image.BILINEAR)
    if isinstance(interpolation, (list, tuple)):
        return random.choice(interpolation)
    else:
        return interpolation

def _check_args_tf(kwargs):
    if 'fillcolor' in kwargs and _PIL_VER < (5, 0):
        kwargs.pop('fillcolor')
    kwargs['resample'] = _interpolation(kwargs)

def shear_x(img, factor, **kwargs):
    _check_args_tf(kwargs)
    return img.transform(img.size, Image.AFFINE, (1, factor, 0, 0, 1, 0), **kwargs)

def shear_y(img, factor, **kwargs):
    _check_args_tf(kwargs)
    return img.transform(img.size, Image.AFFINE, (1, 0, 0, factor, 1, 0), **kwargs)

def translate_x_rel(img, pct, **kwargs):
    pixels = pct * img.size[0]
    _check_args_tf(kwargs)
    return img.transform(img.size, Image.AFFINE, (1, 0, pixels, 0, 1, 0), **kwargs)

def translate_y_rel(img, pct, **kwargs):
    pixels = pct * img.size[1]
    _check_args_tf(kwargs)
    return img.transform(img.size, Image.AFFINE, (1, 0, 0, 0, 1, pixels), **kwargs)

def translate_x_abs(img, pixels, **kwargs):
    _check_args_tf(kwargs)
    return img.transform(img.size, Image.AFFINE, (1, 0, pixels, 0, 1, 0), **kwargs)

def translate_y_abs(img, pixels, **kwargs):
    _check_args_tf(kwargs)
    return img.transform(img.size, Image.AFFINE, (1, 0, 0, 0, 1, pixels), **kwargs)

# def rotate(img, degrees, **kwargs)
#     pass
def rotate(img, degrees, **kwargs):
    _check_args_tf(kwargs)
    if _PIL_VER >= (5, 2):
        return img.rotate(degrees, **kwargs)
    elif _PIL_VER >= (5, 0):
        w, h = img.size
        post_trans = (0, 0)
        rotn_center = (w / 2.0, h / 2.0)
        angle = -math.radians(degrees)
        matrix = [
            round(math.cos(angle), 15),
            round(math.sin(angle), 15),
            0.0,
            round(-math.sin(angle), 15),
            round(math.cos(angle), 15),
            0.0,
        ]

        def transform(x, y, matrix):
            (a, b, c, d, e, f) = matrix
            return a * x + b * y + c, d * x + e * y + f

        matrix[2], matrix[5] = transform(
            -rotn_center[0] - post_trans[0], -rotn_center[1] - post_trans[1], matrix
        )
        matrix[2] += rotn_center[0]
        matrix[5] += rotn_center[1]
        return img.transform(img.size, Image.AFFINE, matrix, **kwargs)
    else:
        return img.rotate(degrees, resample=kwargs['resample'])

# swapping np functions instead of PIL
def auto_contrast(img, prob, level_args, fillcolor, resample):
    """Implements Autocontrast function from PIL using numpy ops instead.
    Args:
    image: A 3D uint8 tensor.
    Returns:
    The image after it has had autocontrast applied to it and will be of type
    uint8.

    source:
    https://github.com/poodarchu/learn_aug_for_object_detection.numpy/blob/master/autoaugment_utils.py
    """

    # no op
    if prob < 1.0 and random.random() > prob:
        return

    def scale_channel(img):
        """Scale the 2D image using the autocontrast rule."""
        # A possibly cheaper version can be done using cumsum/unique_with_counts
        # over the histogram values, rather than iterating over the entire image.
        # to compute mins and maxes.
        lo = float(np.min(img))
        hi = float(np.max(img))

        # Scale the image, making the lowest value 0 and the highest value 255.
        def scale_values(im):
            scale = 255.0 / (hi - lo)
            offset = -lo * scale
            im = im.astype(np.float32) * scale + offset
            im = np.clip(im, 0.0, 255.0)
            return im.astype(np.uint8)

        if hi > lo:
            result = scale_values(img)
        else:
            result = img

        return result

    # Assumes RGB for now.  Scales each channel independently
    # and then stacks the result.
    img[:,:, 0] = scale_channel(img[:, :, 0])
    img[:,:, 1] = scale_channel(img[:, :, 1])
    img[:,:, 2] = scale_channel(img[:, :, 2])
    # img = np.stack((s1, s2, s3), 2)
    # return img

def equalize(img, prob, level_args, fillcolor, resample):

    """

    source / adapted from these:
    https://opencv24-python-tutorials.readthedocs.io/en/latest/py_tutorials/py_imgproc/py_histograms/py_histogram_equalization/py_histogram_equalization.html
    and
    https://msameeruddin.hashnode.dev/image-equalization-contrast-enhancing-in-python

    note - can't use np.ma, not numba supported

    """

    # no op
    if prob < 1.0 and random.random() > prob:
        return

    image_flattened = img.flatten()

    bins_const = 256
    image_hist,bins = np.histogram(image_flattened,bins_const,[0,bins_const])

    # cummulative sum
    cum_sum = np.cumsum(image_hist)
    norm = (cum_sum - cum_sum.min()) * 255
    # normalization of the pixel values
    n_ = cum_sum.max() - cum_sum.min()
    uniform_norm = norm / n_
    uniform_norm = uniform_norm.astype('int')

    # flat histogram
    image_eq = uniform_norm[image_flattened]
    # reshaping the flattened matrix to its original shape

    img[:,:,:] = image_eq.reshape(img.shape)
    return

def invert(img, prob, level_args, fillcolor, resample):
    """
    Source:
    https://yashaslokesh.github.io/inverting-the-colors-of-an-image.html

    """

    # no op
    if prob < 1.0 and random.random() > prob:
        return

    img[:,:,:] = 255 - img

    # return 255 - img

def solarize(img, prob, level_args, fillcolor, resample):
    # no op
    if prob < 1.0 and random.random() > prob:
        return

    thresh = level_args[0]
    img[:,:,:] = np.where(img < thresh, img, 255 - img).astype(np.uint8)  # make sure to cast!

    # img = new_img
    # return new_img

# def invert(img, **__):
#     return ImageOps.invert(img)

# def equalize(img, **__):
#     return ImageOps.equalize(img)

# def solarize(img, thresh, **__):
#     return ImageOps.solarize(img, thresh)

def solarize_add(img, add, thresh=128, **__):
    lut = []
    for i in range(256):
        if i < thresh:
            lut.append(min(255, i + add))
        else:
            lut.append(i)
    if img.mode in ("L", "RGB"):
        if img.mode == "RGB" and len(lut) == 256:
            lut = lut + lut + lut
        return img.point(lut)
    else:
        return img

def posterize(img, bits_to_keep, **__):
    if bits_to_keep >= 8:
        return img
    return ImageOps.posterize(img, bits_to_keep)

def contrast(img, factor, **__):
    return ImageEnhance.Contrast(img).enhance(factor)

# def color(img, factor, **__):
#     return ImageEnhance.Color(img).enhance(factor)

def color(img, prob, level_args, fillcolor, resample):
    """

    def color(img, factor):
        # Equivalent of PIL Color
        if img.shape[0] == 0 or img.shape[1] == 0:
            return img

        degenerate = np.tile(rgb2gray(img)[..., np.newaxis], [1, 1, 3])
        return blend(degenerate, img, factor)

    """

    # no op
    if prob < 1.0 and random.random() > prob:
        return
    if img.shape[0] == 0 or img.shape[1] == 0:
        return

    factor = level_args[0]

    degenerate_gray = np.expand_dims(_rgb2gray(img), axis=2)
    stacked_gray = np.concatenate((degenerate_gray, degenerate_gray, degenerate_gray), axis=2)
    img[:,:,:] = _blend(stacked_gray, img, factor)
    return

@njit
def _rgb2gray(img):
    """Helpers, note it returns an image"""
    # return np.dot(img[...,:3], np.array([0.2989, 0.5870, 0.1140])).astype(np.uint8)

    h, w, c = img.shape

    ch = (0.2989, 0.5870, 0.1140)

    a = img[:,:,0].flatten() * ch[0]
    b = img[:,:,1].flatten() * ch[1]
    c = img[:,:,2].flatten() * ch[2]

    d = a + b + c

    return d.astype(np.uint8).reshape(h, w)

    # return img.dot([0.2989, 0.5870, 0.1140]).astype(np.uint)

@njit
def _blend(image1, image2, factor):
    """Blend image1 and image2 using 'factor'.
    Factor can be above 0.0.  A value of 0.0 means only image1 is used.
    A value of 1.0 means only image2 is used.  A value between 0.0 and
    1.0 means we linearly interpolate the pixel values between the two
    images.  A value greater than 1.0 "extrapolates" the difference
    between the two pixel values, and we clip the results to values
    between 0 and 255.
    Args:
    image1: An image Tensor of type uint8.
    image2: An image Tensor of type uint8.
    factor: A floating point value above 0.0.
    Returns:
    A blended image Tensor of type uint8.
    """
    if factor == 0.0:
        return image1.astype(np.uint8)
    if factor == 1.0:
        return image2.astype(np.uint8)

    image1 = image1.astype(np.float32)
    image2 = image2.astype(np.float32)

    difference = image2 - image1
    scaled = factor * difference

    # Do addition in float.
    temp = image1 + scaled

    # Interpolate
    if factor > 0.0 and factor < 1.0:
    # Interpolation means we always stay within 0 and 255.
        return temp.astype(np.uint8)

    # Extrapolate:
    #
    # We need to clip and then cast.
    return np.clip(temp, 0.0, 255.0).astype(np.uint8)

def brightness(img, factor, **__):
    return ImageEnhance.Brightness(img).enhance(factor)

def sharpness(img, factor, **__):
    return ImageEnhance.Sharpness(img).enhance(factor)

def _randomly_negate(v):
    """With 50% prob, negate the value"""
    return -v if random.random() > 0.5 else v

def _rotate_level_to_arg(level, _hparams):
    # range [-30, 30]
    level = (level / _LEVEL_DENOM) * 30.
    level = _randomly_negate(level)
    return level,

def _enhance_level_to_arg(level, _hparams):
    # range [0.1, 1.9]
    return (level / _LEVEL_DENOM) * 1.8 + 0.1,

def _enhance_increasing_level_to_arg(level, _hparams):
    # the 'no change' level is 1.0, moving away from that towards 0. or 2.0 increases the enhancement blend
    # range [0.1, 1.9] if level <= _LEVEL_DENOM
    level = (level / _LEVEL_DENOM) * .9
    level = max(0.1, 1.0 + _randomly_negate(level))  # keep it >= 0.1
    return level,

def _shear_level_to_arg(level, _hparams):
    # range [-0.3, 0.3]
    level = (level / _LEVEL_DENOM) * 0.3
    level = _randomly_negate(level)
    return level,

def _translate_abs_level_to_arg(level, hparams):
    translate_const = hparams['translate_const']
    level = (level / _LEVEL_DENOM) * float(translate_const)
    level = _randomly_negate(level)
    return level,

def _translate_rel_level_to_arg(level, hparams):
    # default range [-0.45, 0.45]
    translate_pct = hparams.get('translate_pct', 0.45)
    level = (level / _LEVEL_DENOM) * translate_pct
    level = _randomly_negate(level)
    return level,

def _posterize_level_to_arg(level, _hparams):
    # As per Tensorflow TPU EfficientNet impl
    # range [0, 4], 'keep 0 up to 4 MSB of original image'
    # intensity/severity of augmentation decreases with level
    return int((level / _LEVEL_DENOM) * 4),

def _posterize_increasing_level_to_arg(level, hparams):
    # As per Tensorflow models research and UDA impl
    # range [4, 0], 'keep 4 down to 0 MSB of original image',
    # intensity/severity of augmentation increases with level
    return 4 - _posterize_level_to_arg(level, hparams)[0],

def _posterize_original_level_to_arg(level, _hparams):
    # As per original AutoAugment paper description
    # range [4, 8], 'keep 4 up to 8 MSB of image'
    # intensity/severity of augmentation decreases with level
    return int((level / _LEVEL_DENOM) * 4) + 4,

def _solarize_level_to_arg(level, _hparams):
    # range [0, 256]
    # intensity/severity of augmentation decreases with level
    return int((level / _LEVEL_DENOM) * 256),

def _solarize_increasing_level_to_arg(level, _hparams):
    # range [0, 256]
    # intensity/severity of augmentation increases with level
    return 256 - _solarize_level_to_arg(level, _hparams)[0],

def _solarize_add_level_to_arg(level, _hparams):
    # range [0, 110]
    return int((level / _LEVEL_DENOM) * 110),

# not sure what this maps to
LEVEL_TO_ARG = {
    'AutoContrast': None,
    'Equalize': None,
    'Invert': None,
    'Rotate': _rotate_level_to_arg,
    # There are several variations of the posterize level scaling in various Tensorflow/Google repositories/papers
    'Posterize': _posterize_level_to_arg,
    'PosterizeIncreasing': _posterize_increasing_level_to_arg,
    'PosterizeOriginal': _posterize_original_level_to_arg,
    'Solarize': _solarize_level_to_arg,
    'SolarizeIncreasing': _solarize_increasing_level_to_arg,
    'SolarizeAdd': _solarize_add_level_to_arg,
    'Color': _enhance_level_to_arg,
    'ColorIncreasing': _enhance_increasing_level_to_arg,
    'Contrast': _enhance_level_to_arg,
    'ContrastIncreasing': _enhance_increasing_level_to_arg,
    'Brightness': _enhance_level_to_arg,
    'BrightnessIncreasing': _enhance_increasing_level_to_arg,
    'Sharpness': _enhance_level_to_arg,
    'SharpnessIncreasing': _enhance_increasing_level_to_arg,
    'ShearX': _shear_level_to_arg,
    'ShearY': _shear_level_to_arg,
    'TranslateX': _translate_abs_level_to_arg,
    'TranslateY': _translate_abs_level_to_arg,
    'TranslateXRel': _translate_rel_level_to_arg,
    'TranslateYRel': _translate_rel_level_to_arg,
}

NAME_TO_OP = {
    'AutoContrast': auto_contrast,  # before had Auto_Contrast
    'Equalize': equalize,
    'Invert': invert,
    'Rotate': rotate,
    'Posterize': posterize,
    'PosterizeIncreasing': posterize,
    'PosterizeOriginal': posterize,
    'Solarize': solarize,
    'SolarizeIncreasing': solarize,
    'SolarizeAdd': solarize_add,
    'Color': color,
    'ColorIncreasing': color,
    'Contrast': contrast,
    'ContrastIncreasing': contrast,
    'Brightness': brightness,
    'BrightnessIncreasing': brightness,
    'Sharpness': sharpness,
    'SharpnessIncreasing': sharpness,
    'ShearX': shear_x,
    'ShearY': shear_y,
    'TranslateX': translate_x_abs,
    'TranslateY': translate_y_abs,
    'TranslateXRel': translate_x_rel,
    'TranslateYRel': translate_y_rel,
}

# this needs to be a function that returns numpy functions, and passes the right hyparams
# needs to do the exact same thing as Augment Op basically
def augment_op_factory(name, prob=0.5, magnitude=10, hparams=None):

    op_name = name
    # note it uses both name to op and level to arg (but level is sometimes None)
    op_aug_fn = NAME_TO_OP[op_name]
    op_level_fn = LEVEL_TO_ARG[op_name]
    op_prob = prob
    op_magnitude = magnitude
    op_hparams = hparams.copy()

    fillcolor=hparams['img_mean'] if 'img_mean' in hparams else _FILL,
    fillcolor_np = np.array(fillcolor)

    resample=hparams['interpolation'] if 'interpolation' in hparams else _RANDOM_INTERPOLATION,
    resample_np = np.array(resample)

    op_magnitude_std = op_hparams.get('magnitude_std', 0)
    op_magnitude_max = op_hparams.get('magnitude_max', None)

    if op_magnitude_std > 0:
        # magnitude randomization enabled
        if op_magnitude_std == float('inf'):
            op_magnitude = random.uniform(0, op_magnitude)
        elif op_magnitude_std > 0:
            op_magnitude = random.gauss(op_magnitude, op_magnitude_std)
    # default upper_bound for the timm RA impl is _LEVEL_DENOM (10)
    # setting magnitude_max overrides this to allow M > 10 (behaviour closer to Google TF RA impl)
    upper_bound = op_magnitude_max or _LEVEL_DENOM
    op_magnitude = max(0., min(op_magnitude, upper_bound))

    # returns a tuple
    level_args = op_level_fn(op_magnitude, op_hparams) if op_level_fn is not None else tuple()
    # convert to np
    level_args_np = np.array(level_args)

    op_compiled = Compiler.compile(op_aug_fn)

    # breakpoint()

    def op(img):

        return op_compiled(img, prob=prob, level_args=level_args_np, fillcolor=fillcolor_np, resample=resample_np)

    return op

# we currently don't use this one
_RAND_TRANSFORMS_INCREASING_FFCV = [
    'AutoContrast',
    'Equalize',
    'Invert',
    # 'Rotate',
    # 'PosterizeIncreasing',
    'SolarizeIncreasing',
    # 'SolarizeAdd',
    'ColorIncreasing',
    # 'ContrastIncreasing',
    # 'BrightnessIncreasing',
    # 'SharpnessIncreasing',
    # 'ShearX',
    # 'ShearY',
    # 'TranslateXRel',
    # 'TranslateYRel',
    #'Cutout'  # NOTE I've implement this as random erasing separately
]

# # we currently don't use this one
# _RAND_TRANSFORMS = [
#     'AutoContrast',
#     'Equalize',
#     'Invert',
#     'Rotate',
#     'Posterize',
#     'Solarize',
#     'SolarizeAdd',
#     'Color',
#     'Contrast',
#     'Brightness',
#     'Sharpness',
#     'ShearX',
#     'ShearY',
#     'TranslateXRel',
#     'TranslateYRel',
#     #'Cutout'  # NOTE I've implement this as random erasing separately
# ]

# ### # we use this one
# _RAND_INCREASING_TRANSFORMS = [
#     'AutoContrast',
#     'Equalize',
#     'Invert',
#     'Rotate',
#     'PosterizeIncreasing',
#     'SolarizeIncreasing',
#     'SolarizeAdd',
#     'ColorIncreasing',
#     'ContrastIncreasing',
#     'BrightnessIncreasing',
#     'SharpnessIncreasing',
#     'ShearX',
#     'ShearY',
#     'TranslateXRel',
#     'TranslateYRel',
#     #'Cutout'  # NOTE I've implement this as random erasing separately
# ]

# These experimental weights are based loosely on the relative improvements mentioned in paper.
# They may not result in increased performance, but could likely be tuned to so.
# all add up to 100
_RAND_CHOICE_WEIGHTS_0 = {
    'Rotate': 0.3,
    'ShearX': 0.2,
    'ShearY': 0.2,
    'TranslateXRel': 0.1,
    'TranslateYRel': 0.1,
    'Color': .025,
    'Sharpness': 0.025,
    'AutoContrast': 0.025,
    'Solarize': .005,
    'SolarizeAdd': .005,
    'Contrast': .005,
    'Brightness': .005,
    'Equalize': .005,
    'Posterize': 0,
    'Invert': 0,
}

def _select_rand_weights(weight_idx=0, transforms=None):
    transforms = transforms or _RAND_TRANSFORMS
    assert weight_idx == 0  # only one set of weights currently
    rand_weights = _RAND_CHOICE_WEIGHTS_0
    probs = [rand_weights[k] for k in transforms]
    probs /= np.sum(probs)
    return probs

# make a version that finds the numpy versions only
def rand_augment_ops_ffcv(magnitude=10, hparams=None, transforms=None):
    """
    Runs a for loop to call transform factory on each op
    """
    hparams = hparams or _HPARAMS_DEFAULT
    transforms = transforms or _RAND_TRANSFORMS_INCREASING_FFCV

    return [augment_op_factory(
        name, prob=0.5, magnitude=magnitude, hparams=hparams) for name in transforms]

class RandAugmentFFCV(Operation):
    """
    This single custom ffcv function utilizes many non-ffcv functions (compiled).  It
    allows us to not need to write custom ffcv functions for each transform, but instead
    compiles each non-ffcv function it uses.

    """

    def __init__(self, transforms, num_layers=2, choice_weights=None):
        self.transforms = transforms  # can't have any duplicates, will break!
        self.num_layers = num_layers
        self.choice_weights = choice_weights

    def generate_code(self):
        # Compiler.set_enabled(False)  # turn on for debugging only
        parallel_range = Compiler.get_iterator()

        # inner function can't handle any object vars
        num_layers = self.num_layers
        replace = False  # I believe we want this

        # can't use p weights in numba
        # choice_weights = tuple(self.choice_weights) if self.choice_weights is not None else None

        transforms_compiled_list = []

        # compile all possible helper functions/transforms here
        for t in parallel_range(len(self.transforms)):
            trx_comp = Compiler.compile(self.transforms[t])
            transforms_compiled_list.append(trx_comp)

        # must use tuple
        transforms_compiled = tuple(transforms_compiled_list)

        def op(images, dst):
            for i in parallel_range(images.shape[0]):
                im = images[i]
                new_im = im  # must use new var name

                # select n_layer of transforms to use
                ixs = np.random.choice(len(transforms_compiled), num_layers, replace=replace)

                # indexing tuple while calling transform must be hardcorded, can't use for loop
                # of a variable to index w/numba
                for j in parallel_range(num_layers):
                    t = ixs[j]
                    if t == 0:
                        transforms_compiled[0](new_im)
                    elif t == 1:
                        transforms_compiled[1](new_im)
                    elif t == 2:
                        transforms_compiled[2](new_im)
                    elif t == 3:
                        transforms_compiled[3](new_im)
                    elif t == 4:
                        transforms_compiled[4](new_im)

                dst[i] = new_im

            return dst

        op.is_parallel = True
        return op

    def declare_state_and_memory(self, previous_state):
        # Current shape
        h, w, c = previous_state.shape

        # Logic here to determine if the op actually changes the shape
        # new_shape = (h // 2, w // 2, c)
        # TODO:
        pass

        new_state = previous_state
        new_shape = (h, w, c)
        return (new_state, AllocationQuery(new_shape, previous_state.dtype))

    def __repr__(self):
        fs = self.__class__.__name__ + f'(n={self.num_layers}, ops='
        for trx in self.transforms:
            fs += f'\n\t{trx}'
        fs += ')'
        return fs

def rand_augment_transform(config_str, hparams):
    """
    Create a RandAugment transform
    :param config_str: String defining configuration of random augmentation. Consists of multiple sections separated by
    dashes ('-'). The first section defines the specific variant of rand augment (currently only 'rand'). The remaining
    sections, not order sepecific determine
        'm' - integer magnitude of rand augment
        'n' - integer num layers (number of transform ops selected per image)
        'w' - integer probabiliy weight index (index of a set of weights to influence choice of op)
        'mstd' -  float std deviation of magnitude noise applied, or uniform sampling if infinity (or > 100)
        'mmax' - set upper bound for magnitude to something other than default of  _LEVEL_DENOM (10)
        'inc' - integer (bool), use augmentations that increase in severity with magnitude (default: 0)
    Ex 'rand-m9-n3-mstd0.5' results in RandAugment with magnitude 9, num_layers 3, magnitude_std 0.5
    'rand-mstd1-w0' results in magnitude_std 1.0, weights 0, default magnitude of 10 and num_layers 2
    :param hparams: Other hparams (kwargs) for the RandAugmentation scheme
    :return: A PyTorch compatible Transform
    """
    magnitude = _LEVEL_DENOM  # default to _LEVEL_DENOM for magnitude (currently 10)
    num_layers = 2  # default to 2 ops per image
    weight_idx = None  # default to no probability weights for op choice
    transforms = _RAND_TRANSFORMS_INCREASING_FFCV  # note the change here
    config = config_str.split('-')
    assert config[0] == 'rand'
    config = config[1:]
    for c in config:
        cs = re.split(r'(\d.*)', c)
        if len(cs) < 2:
            continue
        key, val = cs[:2]
        if key == 'mstd':
            # noise param / randomization of magnitude values
            mstd = float(val)
            if mstd > 100:
                # use uniform sampling in 0 to magnitude if mstd is > 100
                mstd = float('inf')
            hparams.setdefault('magnitude_std', mstd)
        elif key == 'mmax':
            # clip magnitude between [0, mmax] instead of default [0, _LEVEL_DENOM]
            hparams.setdefault('magnitude_max', int(val))
        elif key == 'inc':  # we use this one
            if bool(val):
                # transforms = _RAND_INCREASING_TRANSFORMS
                transforms = _RAND_TRANSFORMS_INCREASING_FFCV  # overide for now
        elif key == 'm':
            magnitude = int(val)
        elif key == 'n':  # we don't use
            num_layers = int(val)
        elif key == 'w':  # we don't use, currently breaks with this, not sure why
            weight_idx = int(val)
        else:
            assert False, 'Unknown RandAugment config section'

    # returns a list of object ops (not functions, but uses __call__)
    ra_ops = rand_augment_ops_ffcv(magnitude=magnitude, hparams=hparams, transforms=transforms)

    # ra_ops = rand_augment_ops(magnitude=magnitude, hparams=hparams, transforms=transforms)
    # probably will be None
    choice_weights = None if weight_idx is None else _select_rand_weights(weight_idx)

    # eventually replace with RandAugmentFFCV version
    return RandAugmentFFCV(ra_ops, num_layers, choice_weights=choice_weights)

#### end autoaug_cv2.py

def transforms_noaug_train(
        img_size=224,
        interpolation='bilinear',
        use_prefetcher=False,
        mean=IMAGENET_DEFAULT_MEAN,
        std=IMAGENET_DEFAULT_STD,
):
    if interpolation == 'random':
        # random interpolation not supported with no-aug
        interpolation = 'bilinear'
    tfl = [
        transforms.Resize(img_size, interpolation=str_to_interp_mode(interpolation)),
        transforms.CenterCrop(img_size)
    ]
    if use_prefetcher:
        # prefetcher and collate will handle tensor conversion and norm
        tfl += [ToNumpy()]
    else:
        tfl += [
            transforms.ToTensor(),
            transforms.Normalize(
                mean=torch.tensor(mean),
                std=torch.tensor(std))
        ]
    return transforms.Compose(tfl)

def transforms_imagenet_train(
        img_size=224,
        scale=None,
        ratio=None,
        hflip=0.5,
        vflip=0.,
        color_jitter=0.4,
        auto_augment=None,
        interpolation='random',
        use_prefetcher=False,
        mean=IMAGENET_DEFAULT_MEAN,
        std=IMAGENET_DEFAULT_STD,
        re_prob=0.,
        re_mode='const',
        re_count=1,
        re_num_splits=0,
        separate=False,
):
    """
    If separate==True, the transforms are returned as a tuple of 3 separate transforms
    for use in a mixing dataset that passes
     * all data through the first (primary) transform, called the 'clean' data
     * a portion of the data through the secondary transform
     * normalizes and converts the branches above with the third, final transform
    """
    scale = tuple(scale or (0.08, 1.0))  # default imagenet scale range
    ratio = tuple(ratio or (3./4., 4./3.))  # default imagenet ratio range

    primary_tfl = []

    # add the primary ffcv transforms here

    # primary_tfl = [
    #     RandomResizedCropAndInterpolation(img_size, scale=scale, ratio=ratio, interpolation=interpolation)]
    # if hflip > 0.:
    #     primary_tfl += [transforms.RandomHorizontalFlip(p=hflip)]
    # if vflip > 0.:
    #     primary_tfl += [transforms.RandomVerticalFlip(p=vflip)]

    secondary_tfl = []
    if auto_augment:
        assert isinstance(auto_augment, str)
        if isinstance(img_size, (tuple, list)):
            img_size_min = min(img_size)
        else:
            img_size_min = img_size
        aa_params = dict(
            translate_const=int(img_size_min * 0.45),
            img_mean=tuple([min(255, round(255 * x)) for x in mean]),
        )
        if interpolation and interpolation != 'random':
            aa_params['interpolation'] = str_to_pil_interp(interpolation)

        if auto_augment.startswith('rand'):  ####   we use this one  ####
            secondary_tfl += [rand_augment_transform(auto_augment, aa_params)]

        # # we don't use this ones, don't implement
        # elif auto_augment.startswith('augmix'):
        #     aa_params['translate_pct'] = 0.3
        #     secondary_tfl += [augment_and_mix_transform(auto_augment, aa_params)]
        # else:
        #     secondary_tfl += [auto_augment_transform(auto_augment, aa_params)]
    elif color_jitter is not None:
        # color jitter is enabled when not using AA
        if isinstance(color_jitter, (list, tuple)):
            # color jitter should be a 3-tuple/list if spec brightness/contrast/saturation
            # or 4 if also augmenting hue
            assert len(color_jitter) in (3, 4)
        else:
            # if it's a scalar, duplicate for brightness, contrast, and saturation, no hue
            color_jitter = (float(color_jitter),) * 3
        secondary_tfl += [transforms.ColorJitter(*color_jitter)]

    # final_tfl = []
    # if use_prefetcher:
    #     # prefetcher and collate will handle tensor conversion and norm
    #     final_tfl += [ToNumpy()]
    # else:
    #     final_tfl += [
    #         transforms.ToTensor(),
    #         transforms.Normalize(
    #             mean=torch.tensor(mean),
    #             std=torch.tensor(std))
    #     ]
    #     if re_prob > 0.:
    #         final_tfl.append(
    #             RandomErasing(re_prob, mode=re_mode, max_count=re_count, num_splits=re_num_splits, device='cpu'))

    # if separate:
    #     return transforms.Compose(primary_tfl), transforms.Compose(secondary_tfl), transforms.Compose(final_tfl)
    # else:
    #     return transforms.Compose(primary_tfl + secondary_tfl + final_tfl)

    return secondary_tfl

def transforms_imagenet_eval(
        img_size=224,
        crop_pct=None,
        interpolation='bilinear',
        use_prefetcher=False,
        mean=IMAGENET_DEFAULT_MEAN,
        std=IMAGENET_DEFAULT_STD):
    crop_pct = crop_pct or DEFAULT_CROP_PCT

    if isinstance(img_size, (tuple, list)):
        assert len(img_size) == 2
        if img_size[-1] == img_size[-2]:
            # fall-back to older behaviour so Resize scales to shortest edge if target is square
            scale_size = int(math.floor(img_size[0] / crop_pct))
        else:
            scale_size = tuple([int(x / crop_pct) for x in img_size])
    else:
        scale_size = int(math.floor(img_size / crop_pct))

    tfl = [
        transforms.Resize(scale_size, interpolation=str_to_interp_mode(interpolation)),
        transforms.CenterCrop(img_size),
    ]
    if use_prefetcher:
        # prefetcher and collate will handle tensor conversion and norm
        tfl += [ToNumpy()]
    else:
        tfl += [
            transforms.ToTensor(),
            transforms.Normalize(
                     mean=torch.tensor(mean),
                     std=torch.tensor(std))
        ]

    return transforms.Compose(tfl)

def create_transform(
        input_size,
        is_training=False,
        use_prefetcher=False,
        no_aug=False,
        scale=None,
        ratio=None,
        hflip=0.5,
        vflip=0.,
        color_jitter=0.4,
        auto_augment=None,
        interpolation='bilinear',
        mean=IMAGENET_DEFAULT_MEAN,
        std=IMAGENET_DEFAULT_STD,
        re_prob=0.,
        re_mode='const',
        re_count=1,
        re_num_splits=0,
        crop_pct=None,
        tf_preprocessing=False,
        separate=False):

    if isinstance(input_size, (tuple, list)):
        img_size = input_size[-2:]
    else:
        img_size = input_size

    if tf_preprocessing and use_prefetcher:
        assert not separate, "Separate transforms not supported for TF preprocessing"
        from timm.data.tf_preprocessing import TfPreprocessTransform
        transform = TfPreprocessTransform(
            is_training=is_training, size=img_size, interpolation=interpolation)
    else:
        # if is_training and no_aug:
        #     assert not separate, "Cannot perform split augmentation with no_aug"
        #     transform = transforms_noaug_train(
        #         img_size,
        #         interpolation=interpolation,
        #         use_prefetcher=use_prefetcher,
        #         mean=mean,
        #         std=std)
        # elif is_training:
        transform = transforms_imagenet_train(
            img_size,
            scale=scale,
            ratio=ratio,
            hflip=hflip,
            vflip=vflip,
            color_jitter=color_jitter,
            auto_augment=auto_augment,
            interpolation=interpolation,
            use_prefetcher=use_prefetcher,
            mean=mean,
            std=std,
            re_prob=re_prob,
            re_mode=re_mode,
            re_count=re_count,
            re_num_splits=re_num_splits,
            separate=separate)
        # else:
        #     assert not separate, "Separate transforms not supported for validation preprocessing"
        #     transform = transforms_imagenet_eval(
        #         img_size,
        #         interpolation=interpolation,
        #         use_prefetcher=use_prefetcher,
        #         mean=mean,
        #         std=std,
        #         crop_pct=crop_pct)

    return transform

    # overide for testing, send back list of Op (ffcv functions)
    # make sure not to use ToTensor, Normalize, or use Compose(), dataset will handle
    # return [RandAugmentFFCV([auto_contrast, auto_contrast], num_layers=2)]


'''
This damn GraphRXN is a pain in butt.
'''

import numpy as np
import pandas as pd
from rdkit import Chem
from rdkit.Chem import AllChem

from suzuki_splits import load_parsed_data, ranking_nucleophiles_and_electrophiles, \
    split_on_reactant, split_on_multiple_electrophiles, split_on_cat_lig, \
    ranking_catalysts_and_ligands, find_reactants, find_catalysts_ligands, reformat_ligs_and_cats, clean_ligands

def canonicalize_smiles(smiles):
    return Chem.MolToSmiles(Chem.MolFromSmiles(smiles))

def make_stars(rxn_dictionary, index):
    nucleophile, electrophile = find_reactants(rxn_dictionary[index]['rx'])
    catalyst, ligand = find_catalysts_ligands(rxn_dictionary[index])
    catalyst = reformat_ligs_and_cats([catalyst])
    ligand = clean_ligands([ligand])
    ligand = reformat_ligs_and_cats(ligand)
    if index == 6009:
        product = make_product(nucleophile, electrophile)
    else:
        product = make_product(electrophile, nucleophile)

    rxn_smiles = canonicalize_smiles(electrophile) + '*' + canonicalize_smiles(nucleophile) + '*' + canonicalize_smiles(catalyst[0]) + '*' + canonicalize_smiles(ligand[0]) + '*' + canonicalize_smiles(product)
    return rxn_smiles

def make_product(electrophile, nucleophile):
    electrophile = Chem.MolFromSmiles(electrophile)
    nucleophile = Chem.MolFromSmiles(nucleophile)

    rxn = AllChem.ReactionFromSmarts('[c:1][Cl,Br,I:2].[c:3]-[B:4]>>[c:1][c:3]')
    product = Chem.MolToSmiles(rxn.RunReactants((electrophile, nucleophile))[0][0])
    return product

def make_reaction_column(dict):
    reactions = []
    for i in list(dict.keys()):
        reactions.append(make_stars(dict, i))
    return reactions

def make_labels(rxn_dict):
    labels = []
    for i in list(rxn_dict.keys()):
        labels.append(rxn_dict[i]['yield'])
    return np.array(labels)

def make_graphrxn_input(dict, save_path):
    df = pd.DataFrame()
    df['reaction'] = make_reaction_column(dict)
    labels = make_labels(dict)
    mean = np.mean(labels)
    std = np.std(labels)
    scaled = [((x - mean) / std) for x in labels]
    df['temp'] = np.nan
    df['output'] = scaled
    df['origin_output'] = labels
    if save_path is not None:
        df.to_csv(save_path, index=False)
        return print(f'Saved to {save_path}')
    else:
        return df

def main():
    split = 'electrophile'

    print('Loading in data...')
    print()
    # Import the datasets.
    data_paths = ['suzuki_from_arom_USPTO_parsed_het.txt', 'suzuki_from_arom_USPTO_parsed_homo.txt']
    suzuki_rxns = load_parsed_data(data_paths[0], start_index=0)
    suzuki_rxns_2 = load_parsed_data(data_paths[1], start_index=len(suzuki_rxns))
    suzuki_rxns.update(suzuki_rxns_2)

    # Deleting the rxns with super long catalysts.
    del suzuki_rxns[3818], suzuki_rxns[420], suzuki_rxns[2922]

    # Dataframe splits.
    most_common_nucleophiles, most_common_electrophiles = ranking_nucleophiles_and_electrophiles(suzuki_rxns)
    if split == 'nucleophlie':
        train_val_dict, test_dict = split_on_reactant(suzuki_rxns, most_common_nucleophiles[0])
        train_dict, val_dict = split_on_reactant(train_val_dict, most_common_nucleophiles[1])
    else:
        train_val_dict, test_dict = split_on_multiple_electrophiles(suzuki_rxns, most_common_electrophiles[0:35])
        train_dict, val_dict = split_on_multiple_electrophiles(train_val_dict, most_common_electrophiles[35:])

    make_graphrxn_input(train_dict, 'suzuki_electrophile_graphrxn_train.csv')
    make_graphrxn_input(test_dict, 'suzuki_electrophile_graphrxn_test.csv')

if __name__ == '__main__':
    main()


import os, queue
from random import shuffle, randrange

def cria_labirinto(larg = 8, alt = 3):
  vis = [[0] * larg + [1] for _ in range(alt)] + [[1] * (larg + 1)]
  sem_muros = []

  def quebra_muros(lin, col):
    vis[lin][col] = 1
    d = [(lin + 1, col), (lin - 1, col), (lin, col + 1), (lin, col - 1)]
    shuffle(d)

    for (l, c) in d:
      if vis[l][c] != 1:
        no = (lin, col)
        vizinho = (l, c)
        sem_muros.append((no, vizinho))
        quebra_muros(l, c)

  quebra_muros(randrange(alt), randrange(larg))
  return(sem_muros)

def desenha_labirinto(lab, larg = 8, alt = 3):
  ver = [['|  '] * larg + ['|'] for i in range(alt)] + [[]]
  hor = [['+--'] * larg + ['+'] for _ in range(alt + 1)]

  for ((l1, c1), (l2, c2)) in lab:
    if l1 == l2:
      ver[l1][max(c1, c2)] = '   '
    if c1 == c2:
      hor[max(l1, l2)][c1] = '+  '

  print('  '.format(), end= '')
  for i in range(larg):#coordenadas x
    print(' {} '.format(i), end= '')
  print()

  r = range(larg + 1)
  i = 0
  for (a, b) in zip(hor, ver):
    print(''.join(['  '] + a + ['\n'] + ['{} '.format(r[i] if i < larg else '')] + b))
    i += 1

def heuristica(no, objetivo):
    (xi, yi) = no["coordenadas"]
    (xf, yf) = objetivo
    return abs(xi - xf) + abs(yi - yf)

def folhas(lab, no):
    nos_folhas = []
    for (de,para) in filter(lambda caminho: no["coordenadas"] in caminho, lab):
        coordenada_folha = para if no["coordenadas"] == de else de
        custo_pai = no["custo"]
        nos_folhas.append(criar_no(coordenada_folha, pai = no, custo = custo_pai + 1))

    return nos_folhas

def a_estrela(lab, inicio, objetivo):
    fronteira = queue.PriorityQueue()
    #coloco o nó inicial
    no_inicio = criar_no(inicio)
    fronteira.put((0, id(no_inicio), no_inicio))
    visitados = []
    visitados.append(no_inicio)
    custo_ate_aqui = 0
    while not fronteira.empty():
        #pego o proximo elemento
        (_, _, no) = fronteira.get()

        #verifico se alcancei o objetivo
        if no["coordenadas"] == objetivo:
            #visitados.append(no)
            break

        for folha in folhas(lab, no):

            novo_custo = folha["custo"] #podemos melhorar esse custo
            if(folha["coordenadas"] in list(map(lambda x: x["coordenadas"], visitados))):
                continue

            custo_ate_aqui = novo_custo
            prioridade = heuristica(folha, objetivo) + novo_custo
            fronteira.put((prioridade, id(folha), folha))
            #registro como um caminho visitado
            visitados.append(folha)

    return visitados

def criar_no(coordenadas, pai = None, custo = 0):
  return {
    "pai": pai,
    "coordenadas": coordenadas,
    "custo": custo
  }

def limpar_caminho(visitados):
  caminho = []
  no = visitados[-1]
  while no is not None:
    caminho.append(no['coordenadas'])
    no = no['pai']
  return caminho[::-1]
def tratar_list_nos_visitados(visitados):
  nos = []
  for no in visitados:
    nos.append(no["coordenadas"])

  return nos

if __name__ == '__main__':
  os.system('cls' if os.name == 'nt' else 'clear')
  x = int(input('Digite a largura do seu labirinto:'))
  y = int(input('Digite a altura do seu labirinto:'))
  labirinto = cria_labirinto(x,y)
  desenha_labirinto(labirinto, x, y)

  i1 = input('Separando por virgula, digite as coordenadas x,y do ponto de início: ')
  (xi,yi) = tuple(int(x) for x in i1.split(","))
  i2 = input('Separando por virgula, digite as coordenadas x,y do objetivo: ')
  (xf,yf) = tuple(int(x) for x in i2.split(","))

  visitados = a_estrela(labirinto, (xi,yi), (xf,yf))
  print('Melhor caminho encontrado:')
  print(limpar_caminho(visitados))
  print('Nós Visitados:')
  print(tratar_list_nos_visitados(visitados))


"""Read URL Configuration

The `urlpatterns` list routes URLs to views. For more information please see:
    https://docs.djangoproject.com/en/1.11/topics/http/urls/
Examples:
Function views
    1. Add an import:  from my_app import views
    2. Add a URL to urlpatterns:  url(r'^$', views.home, name='home')
Class-based views
    1. Add an import:  from other_app.views import Home
    2. Add a URL to urlpatterns:  url(r'^$', Home.as_view(), name='home')
Including another URLconf
    1. Import the include() function: from django.conf.urls import url, include
    2. Add a URL to urlpatterns:  url(r'^blog/', include('blog.urls'))
"""
import json

from django.conf.urls import url,include
from django.core.paginator import Paginator
from django.shortcuts import render
from art.models import Tag,Articl
import xadmin as admin
from user import helper

def toIndex(request):
    # 加载所有分类
    tags = Tag.objects.all()
    # locals()将当前函数的局部变量转变为字典的k-v

    # 读取分类id
    tag_id = request.GET.get('tag')
    if tag_id:
        tag_id = int(tag_id)
        articls = Articl.objects.filter(tag_id=tag_id)
    else:
        tag_id = 0
        articls = Articl.objects.all()
    #将文章分页
    paginator = Paginator(articls,10)
    page = int(request.GET.get('page',1))
    pager = paginator.page(page)

    # 获取登录用户信息
    login_user = helper.getLoginInfo(request)
    return render(request,'index.html',locals())

urlpatterns = [
    url(r'^admin/', admin.site.urls),
    url(r'^ueditor/',include('DjangoUeditor.urls')),
    url(r'^user/', include('user.urls')),
    url(r'^articl/',include('art.urls')),
    url(r'^$',toIndex),

]


from flask import render_template,redirect,session,request, flash
from flask_app import app
from flask_app.models.student import Student
from flask_app.models.essay import Essay

@app.route('/new/essay')
def new_essay():
    if 'student_id' not in session:
        return redirect('/logout')
    data = {
        "id":session['student_id']
    }
    return render_template('new_essay.html',student=Student.get_by_id(data))

@app.route('/create/essay',methods=['POST'])
def create_essay():
    if 'student_id' not in session:
        return redirect('/logout')
    if not Essay.validate_essay(request.form):
        return redirect('/new/essay')
    data = {
        "title": request.form["title"],
        "subject": request.form["subject"],
        "date_completed": request.form["date_completed"],
        "notes": request.form["notes"],
        "student_id": session["student_id"]
    }
    Essay.save(data)
    return redirect('/dashboard')

@app.route('/edit/essay/<int:id>')
def edit_essay(id):
    if 'student_id' not in session:
        return redirect('/logout')
    data = {
        "id":id
    }
    student_data = {
        "id":session['student_id']
    }
    return render_template("edit_essay.html",edit=Essay.get_one(data),student=Student.get_by_id(student_data))

@app.route('/update/essay',methods=['POST'])
def update_essay():
    if 'student_id' not in session:
        return redirect('/logout')
    if not Essay.validate_essay(request.form):
        return redirect('/new/essay')
    data = {
        "title": request.form["title"],
        "subject": request.form["subject"],
        "notes": request.form["notes"],
        "date_completed": request.form["date_completed"],
        "id": request.form['id']
    }
    # "id" above may need to be student_id - need to figure this out; Update: it looks ok and seems to work
    Essay.update(data)
    return redirect('/dashboard')

@app.route('/show/essay/<int:id>')
def show_essay(id):
    if 'student_id' not in session:
        return redirect('/logout')
    data = {
        "id":id
    }
    student_data = {
        "id":session['student_id']
    }
    return render_template("show_essay.html",essay=Essay.get_one(data),student=Student.get_by_id(student_data))

@app.route('/destroy/essay/<int:id>')
def destroy_essay(id):
    if 'student_id' not in session:
        return redirect('/logout')
    data = {
        "id":id
    }
    Essay.destroy(data)
    return redirect('/dashboard')


import time
import sys
from math import sqrt, tan

import cozmo
from cozmo.objects import CustomObject
from cozmo.util import Pose, degrees, radians, speed_mmps, distance_mm

from custom_objects import objects, custom_object_pose
from take_photo import setup_camera, photo
from action_manager import ActionManager

custom_object = None

stops_visited = []

def handle_object_appeared(evt, **kw):
    # Cela sera appelé chaque fois qu'un EvtObjectAppeared est déclanché
    # chaque fois qu'un objet entre en vue
    if isinstance(evt.obj, CustomObject):
        print(f"Cozmo started seeing a type: {str(evt.obj.object_type)} id: {str(evt.obj.object_id)}")

def handle_object_disappeared(evt, **kw):
    # Cela sera appelé lorsqu'un EvtObjectDisappeared est declanché
    # chaque fois qu'un objet est hors de vue.
    if isinstance(evt.obj, CustomObject):
        print(f"Cozmo stopped seeing a {str(evt.obj.object_type)}")

def custom_objects(robot: cozmo.robot.Robot):

    # Gestionnaires d'évennements à chaque fois que Cozmo vois ou arrète de voir un objet
    robot.add_event_handler(cozmo.objects.EvtObjectAppeared, handle_object_appeared)
    robot.add_event_handler(cozmo.objects.EvtObjectDisappeared, handle_object_disappeared)

    # Création des custom objects
    objs = objects(robot)
    if None not in objs:
        print("All objects defined successfully!")
    else:
        print("One or more object definitions failed!")
        return

    robot.say_text("À la recherche des objet").wait_for_completed()
    setup_camera(robot)
    origin = robot.pose
    am = ActionManager(robot)
    stops = 1

    while len(stops_visited) < 6:

        # Chercer les objest
        lookaround = robot.start_behavior(cozmo.behavior.BehaviorTypes.LookAroundInPlace)
        objs = robot.world.wait_until_observe_num_objects(num=1, object_type=CustomObject, timeout=60)
        lookaround.stop()

        if objs[0].object_type in stops_visited:
            continue

        stops_visited.append(objs[0].object_type)

        robot.say_text("Objet trouvé").wait_for_completed()

        if len(objs) > 0:

            photo(robot)

            pose = custom_object_pose(robot, objs[0])
            robot.go_to_pose(pose, relative_to_robot=False).wait_for_completed()

            photo(robot)

            robot.say_text(f"Arrête {stops}").wait_for_completed()
            am.launch(objs[0])

            print("origin: ", origin)
            robot.go_to_pose(origin, relative_to_robot=False).wait_for_completed()
            stops += 1

        else:
            print("Cannot locate custom box")

    robot.play_anim_trigger(cozmo.anim.Triggers.SparkSuccess).wait_for_completed()

    while True:
        time.sleep(0.1)

cozmo.run_program(custom_objects, use_3d_viewer=True, use_viewer=True)


import datetime
from re import findall
from dateutil import parser

try:
    import isodate
except:
    pass  # Duration parsing not supported

def timedelta2duration(timedelta):
    components = {
        "days": getattr(timedelta, "days", 0),
        "hours": 0,
        "minutes": 0,
        "seconds": getattr(timedelta, "seconds", 0),
    }
    if components["seconds"]:
        components["hours"], components["minutes"], components["seconds"] = [
            int(i) for i in str(datetime.timedelta(seconds=components["seconds"])).split(":")
        ]
    return isodate.Duration(**components)

def ifc2datetime(element):
    if isinstance(element, str) and "P" in element[0:2]:  # IfcDuration
        duration = parse_duration(element)
        if isinstance(duration, datetime.timedelta):
            return timedelta2duration(duration)
        return duration
    elif isinstance(element, str) and len(element) > 3 and element[2] == ":":  # IfcTime
        return datetime.time.fromisoformat(element)
    elif isinstance(element, str) and ":" in element:  # IfcDateTime
        return datetime.datetime.fromisoformat(element)
    elif isinstance(element, str):  # IfcDate
        return datetime.date.fromisoformat(element)
    elif isinstance(element, int):  # IfcTimeStamp
        return datetime.datetime.fromtimestamp(element)
    elif element.is_a("IfcDateAndTime"):
        return datetime.datetime(
            element.DateComponent.YearComponent,
            element.DateComponent.MonthComponent,
            element.DateComponent.DayComponent,
            element.TimeComponent.HourComponent,
            element.TimeComponent.MinuteComponent,
            int(element.TimeComponent.SecondComponent),
            # TODO: implement TimeComponent timezone
        )
    elif element.is_a("IfcCalendarDate"):
        return datetime.date(
            element.YearComponent,
            element.MonthComponent,
            element.DayComponent,
        )

def get_isosplit(s, split):
    if split in s:
        n, s = s.split(split)
    else:
        n = 0
    return n, s

def readable_ifc_duration(string):
    string = string.split("P")[-1]

    years, string = get_isosplit(string, "Y")
    months, string = get_isosplit(string, "M")
    weeks, string = get_isosplit(string, "W")
    days, string = get_isosplit(string, "D")
    _, string = get_isosplit(string, "T")
    hours, string = get_isosplit(string, "H")
    minutes, string = get_isosplit(string, "M")
    seconds, string = get_isosplit(string, "S")

    final_string = ""
    final_string += f"{years} y " if years else ""
    final_string += f"{months} m " if months else ""
    final_string += f"{weeks} w " if weeks else ""
    final_string += f"{days} d " if days else ""
    final_string += f"{round(float(hours),2)} h " if hours else ""
    final_string += f"{minutes} m " if minutes else ""
    final_string += f"{seconds} s " if seconds else ""

    return final_string

def datetime2ifc(dt, ifc_type):
    if isinstance(dt, str):
        if ifc_type == "IfcDuration":
            return dt
        try:
            dt = datetime.datetime.fromisoformat(dt)
        except:
            dt = datetime.time.fromisoformat(dt)

    if ifc_type == "IfcDuration":
        return isodate.duration_isoformat(dt)
    elif ifc_type == "IfcTimeStamp":
        return int(dt.timestamp())
    elif ifc_type == "IfcDateTime":
        if isinstance(dt, datetime.datetime):
            return dt.isoformat()
        elif isinstance(dt, datetime.date):
            return datetime.datetime.combine(dt, datetime.datetime.min.time()).isoformat()
    elif ifc_type == "IfcDate":
        if isinstance(dt, datetime.datetime):
            return dt.date().isoformat()
        elif isinstance(dt, datetime.date):
            return dt.isoformat()
    elif ifc_type == "IfcTime":
        if isinstance(dt, datetime.datetime):
            return dt.time().isoformat()
        elif isinstance(dt, datetime.time):
            return dt.isoformat()
    elif ifc_type == "IfcCalendarDate":
        return {
            "DayComponent": dt.day,
            "MonthComponent": dt.month,
            "YearComponent": dt.year,
        }
    elif ifc_type == "IfcLocalTime":
        # TODO implement timezones
        return {
            "HourComponent": dt.hour,
            "MinuteComponent": dt.minute,
            "SecondComponent": dt.second,
        }

def string_to_date(string):
    if not string:
        return None
    try:
        return parser.isoparse(string)
    except:
        try:
            return parser.parse(string, dayfirst=True, fuzzy=True)
        except:
            return None

def string_to_duration(duration_string):
    # TODO support years, months, weeks aswell
    days = 0
    hours = 0
    minutes = 0
    seconds = 0
    match = findall(r"(\d+\.?\d*)d", duration_string)
    if match:
        days = float(match[0])
    match = findall(r"(\d+\.?\d*)h", duration_string)
    if match:
        hours = float(match[0])
    match = findall(r"(\d+\.?\d*)m", duration_string)
    if match:
        minutes = float(match[0])
    match = findall(r"(\d+\.?\d*)s", duration_string)
    if match:
        seconds = float(match[0])
    return isodate.duration_isoformat(datetime.timedelta(days=days, hours=hours, minutes=minutes, seconds=seconds))

def parse_duration(value):
    if not value:
        return None
    if isinstance(value, str):
        if "P" in value:
            try:
                return isodate.parse_duration(value)
            except ModuleNotFoundError:
                print("Duration parsing not supported: isodate module not found")
            except:
                print("Error parsing ISO string duration")
            return None
        else:
            try:
                final_string = "P"
                value_upper = value.upper()
                for char in value_upper:
                    if char.isdigit():
                        final_string += char
                    elif char == "D":
                        final_string += "D"
                        if "H" in value_upper or "S" in value_upper or "MIN" in value_upper:
                            final_string += "T"
                    elif char == "W":
                        final_string += "W"
                    elif char == "M":
                        final_string += "M"
                    elif char == "Y":
                        final_string += "Y"
                    elif char == "H":
                        final_string = (
                            final_string[:1] + "T" + final_string[1:] if "T" not in final_string else final_string
                        )
                        final_string += "H"
                    elif char == "M":
                        if "MIN" in value_upper and "T" not in final_string:
                            final_string = final_string[:1] + "T" + final_string[1:]
                        final_string += "M"
                    elif char == "S":
                        final_string = (
                            final_string[:1] + "T" + final_string[1:] if "T" not in final_string else final_string
                        )
                        final_string += "S"
                return isodate.parse_duration(final_string)
            except:
                print("error fuzzy parsing duration")
                return None


import face_landmark as land
import cv2
import numpy as np
import pandas as pd

import oracle_db as oradb
from face_alignment import align_image

# userface 에 USER FACE정보 insert
def userfaceland_insert(data):
    conn = oradb.connect()
    print(data)
    query = '''insert into USERFACE values
    (SEQ_FID.nextval, :1, :2, :3, :4, :5, :6, :7, :8, :9, :10, :11, :12, :13, :14, :15, 'base')'''

    try:
        cursor = conn.cursor()
        cursor.execute(query, data)
        oradb.commit(conn)
        print("새 회원 face정보 저장완료")

    except Exception as msg:
        oradb.rollback(conn)
        print('user face 정보 저장(userfaceland_insert) 에러 발생 : ', msg)

    finally:
        cursor.close()
        oradb.close(conn)

#새로등록할 face_num 가져오기
def bring_face_num():
    # face_num 가져오기
    sql = """
            select max(face_num)
            from userface
            """
    conn = oradb.connect()
    cursor = conn.cursor()
    num_list = []
    rs = cursor.execute(sql)
    for record in rs:
       num_list.append(record[0])
    num = num_list[0]

    return num

# 1. 웹에서 이미지가 등록되어 image폴더에 이미지가 등록되면 align_image 폴더에 align한 이미지 파일 저장

# face_num 을 이미지이름(db의 face_num 최대값 가져와서)과 동일하게

# DB에서 가장 최근 face_num 값 다음 num으로 이미지 align
face_num = bring_face_num()+1
image_file= './image/{}.jpg'.format(face_num)
align_image(image_file) # face_alignment.py 의 align_image 함수 실행

#align된 이미지 landmark 돌려 userface TABLE 에 insert
align_image_file = './align_image/{}.jpg'.format(face_num)
image = cv2.imread(align_image_file)

userfaceland_insert(land.landmark(image)) #land.landmark(image)가 list형식의 한사람 데이터 가져오고 userfaceland_insert함수가 db에 리스트 1개씩 데이터 저장

# df = pd.DataFrame(columns=['eye_width', 'eye_height', 'nose_height', 'nose_width', 'nose_high', 'mouth_width', 'mouth_height', 'eyebrow_width', 'eye_to_eyebrow', 'eye_to_eye', 'eye_to_temple', 'nose_to_mouth', 'mouth_to_jaw', 'face_width', 'face_height'])
#######

# align: 얼굴 수평 맞추기 => align_image폴더 만들어 놓으면 폴더에 수평맞춰진 사진 저장됨
# for i in range(1,401):
#     image_file= './image/{}.jpg'.format(i)
#     align_image(image_file) # face_alignment.py 의 align_image 함수 실행

#align된 이미지 landmark 돌려서 얼굴비율 추출, DB에 저장
#######
# for i in range(1,401):
#     align_image_file = './align_image/{}.jpg'.format(i)
#     image = cv2.imread(align_image_file)
#
#     userfaceland_insert(land.landmark(image)) #land.landmark(image)가 list형식의 한사람 데이터 가져오고 userfaceland_insert함수가 db에 리스트 1개씩 데이터 저장
#######
#csv에 저장
# df.to_csv('landmark_test.csv', sep= ',')


import hashlib
import re
from functools import partial
from typing import Any, Dict, Generator, List, Tuple

import imageio
import numpy as np
import yaml

def write_video(
    dst_file: str,
    frames: List[np.ndarray],
    fps: int = 30,
    **kwargs,
):
    """! Writes the provided list of frames (video) to a local video file.
    @param dst_file (str) Full destination video file.
    @param frames (List[np.ndarray]) List of video frames in RGB.
    @param fps (int, optional) Desired FPS of the video. Defaults to 30.
    """
    with imageio.get_writer(dst_file, fps=fps, **kwargs) as writer:
        for image in frames:
            writer.append_data(image)

def read_yaml(filename: str) -> Dict[str, Any]:
    """!

    @param filename (str) Reads a yaml file and returns the content as a dict.

    @return Dict[str, Any] Dictionary with contents of yaml.
    """
    with open(filename, "r") as stream:
        data_loaded = yaml.safe_load(stream)
        return data_loaded

def md5sum(file_path: str) -> str:
    """Returns the md5 sum hash of a given LOCAL file

    @param file_path (str) Full path to file

    @return str Md5 hash string
    """
    with open(file_path, mode="rb") as f:
        d = hashlib.md5()
        for buf in iter(partial(f.read, 1024), b""):
            d.update(buf)
    return d.hexdigest()

def signed2gcs(signed_url: str) -> str:
    """!
    Converts a signed URL to a GCS path. The signed urls
    have the form: https://storage.googleapis.com/gcs_path?X-Goog-Algorithm=...
    @param signed_url string with signed URL
    @return string with GCS path
    """
    gcs_url = signed_url.replace("https://storage.googleapis.com/", "gs://")
    gcs_url = gcs_url.split("?")[0]
    return gcs_url

def get_bucket_and_path(gcs_full_path: str) -> Tuple[str]:
    """Splits a google cloud storage path into bucket_name and the rest
    of the path without the 'gs://' at the beginning
    Args:
        gcs_full_path (str): A valid Gcloud Storage path
    Raises:
        ValueError: If input path does not start with gs://
    Returns:
        Tuple[str]: Bucket name and the rest of the path
    """
    m = re.match(r"(gs://)([^/]+)/(.*)", gcs_full_path)

    if m is None:
        raise ValueError("path is not valid, it needs to start with 'gs://'")

    bucket = m.group(2)
    file_path = m.group(3)
    return bucket, file_path

def decode_video(video_bytes: bytes) -> Tuple[List[np.ndarray], Dict[str, Any]]:
    """! Decodes video from bytes to numpy array and metadata dict.
        It uses ffmpeg as backend.
    @param video_bytes (bytes) Video bytes.
    @return Tuple[List[np.ndarray], Dict[str, Any]] List of frames and metadata.
    """
    frames = []
    with imageio.get_reader(video_bytes, "ffmpeg") as reader:
        meta = reader.get_meta_data()
        for image in reader:
            frames.append(image)
    return frames, meta

def decode_video_gen(
    video_bytes: bytes,
) -> Generator[Tuple[np.ndarray, Dict[str, Any]], None, None]:
    """! Decodes video from bytes to numpy array and metadata dict.
        It uses ffmpeg as backend.
    @param video_bytes (bytes) Video bytes.
    @return Tuple[List[np.ndarray], Dict[str, Any]] List of frames and metadata.
    """
    with imageio.get_reader(video_bytes, "ffmpeg") as reader:
        meta = reader.get_meta_data()
        for image in reader:
            yield image, meta


from discord.ext import commands
from discord.ext.commands import Context
from . import account_access
from ark_bot.bot import utilities
from economy_module.data_access.account_connection import AccountConnection

# noinspection PyMethodMayBeStatic
class Account(commands.Cog):
    def init_tables(self):
        db = AccountConnection()
        db.create_tables()
        db.close()

    @commands.Cog.listener()
    async def on_message(self, message):
        if message.author.bot:
            return

        account = account_access.get_account_by_did(message.author.guild.id, message.author.id)

        if account is None:
            account_access.add_account(message.author)
        else:
            account.Balance += 1
            account_access.update_account(account)

    @commands.command(aliases=["bal"], help="Get a dm with your balance for this server.")
    async def balance(self, ctx: Context):
        member = ctx.author
        account = account_access.get_account_by_did(member.guild.id, member.id)

        if account is None:
            account_access.add_account(member)
            account = account_access.get_account_by_did(member.guild.id, member.id)

        if member.dm_channel is None:
            dm = await member.create_dm()
            await dm.send("Your balance on " + ctx.guild.name + " is: " + str(account.Balance))
        else:
            await member.dm_channel.send("Your balance is: " + str(account.Balance))

    @commands.command(help="Give points to another user.")
    async def give(self, ctx: Context):
        split = ctx.message.content.split()

        amount = split[2]

        try:
            if int(amount) < 0:
                await ctx.send("You can't take point from someone like that. Nice try, however.")
                return
        except ValueError:
            await ctx.send("The amount has to be in number format. -_-")
            return

        target = split[1]
        prefix = target[2]

        if str(target[3 if prefix == '!' else 2:-1]) == str(ctx.author.id):
            await ctx.send("Why do you want to give points to yourself?")
            return

        error = self.withdraw(ctx.author, amount)

        if error == 1 or error == 2:
            await ctx.send("You don't have enough points. Better get to typing.")

        if prefix == '!' or '0' <= prefix <= '9':
            member = utilities.find_member_by_id(ctx.guild.members, target[3 if prefix == '!' else 2:-1])
            self.deposit(member, amount)
            await ctx.send("You gave " + target + " " + str(amount) + " points!")
        else:
            await ctx.send("You can only give points to users.")

    @commands.group(help="Grant points to a user or all users under a role. Admin only")
    async def grant(self, ctx: Context):
        if ctx.invoked_subcommand is not None:
            return

        if not ctx.message.author.guild_permissions.administrator:
            await ctx.send("Only administrators can invoke that command.")
            return

        split = ctx.message.content.split()

        amount = split[2]

        try:
            if int(amount) < 0:
                await ctx.send("Grant amount has to be a positive number.")
                return
        except ValueError:
            await ctx.send("Grant amount has to be in number format. -_-")
            return

        target = split[1]
        prefix = target[2]

        if prefix == '!' or '0' <= prefix <= '9':
            if self._grant_user(ctx, target[3 if prefix == '!' else 2:-1], amount) == 0:
                await ctx.send("Granted " + target + " " + amount + " points!")
            else:
                await ctx.send("Something went wrong, no points were granted.")
        elif prefix == '&':
            if self._grant_role(ctx, target[3:-1], amount) == 0:
                await ctx.send("Granted all " + target + " members " + amount + " points!")
            else:
                await ctx.send("Something went wrong, one or more users didn't receive any points")

    def _grant_user(self, ctx: Context, did, amount):
        member = utilities.find_member_by_id(ctx.guild.members, did)

        return self.deposit(member, int(amount))

    def _grant_role(self, ctx, did, amount):
        members = utilities.find_members_by_role(ctx.guild.members, utilities.find_role(ctx.guild.roles, did))

        error = 0

        for member in members:
            error += self._grant_user(ctx, member.id, amount)

        return error

    @grant.command(name="all", help="Grant all users points. Admin only")
    async def grant_all(self, ctx):
        async with ctx.channel.typing():
            amount = ctx.message.content.split()[2]

            for member in ctx.message.channel.guild.members:
                if member.bot:
                    continue
                self._grant_user(ctx, member.id, amount)

        await ctx.message.channel.send("Granted all users " + amount + " points!")

    def withdraw(self, target, amount):
        account = account_access.get_account_by_did(target.guild.id, target.id)

        if account is None:
            return 2
        if account.Balance < 0:
            return 1

        account.Balance -= int(amount)

        account_access.update_account(account)

        return 0

    def deposit(self, target, amount):
        account = account_access.get_account_by_did(target.guild.id, target.id)

        if account is None:
            account_access.add_account(target)
            account = account_access.get_account_by_did(target.guild.id, target.id)
            amount -= 1

        account.Balance += int(amount)

        account_access.update_account(account)

        return 0


f=open('e:\pyNote\调用资料/105.txt','r',encoding='utf-8')
p=f.readlines()
print(p)
x=''.join(p)
print(x)
k=x.split('\n')
# 去\n方法:先转换为字符串,再用\n做分隔符转回列表--k

#创建字典,初始化值为0
dic= dict.fromkeys(k,0)
print(dic)

# 用打包方法zip： 双循环，双列表生成字典
vau=[i for i in range(10)]
for i,j in zip(dic,vau):
	dic[i]=j
print(dic)


from nltk.corpus import stopwords
from nltk.tokenize import word_tokenize
from nltk.stem import PorterStemmer
from nltk.probability import FreqDist

def text_summarization(text, num_sentences):
    # Tokenize the text into individual words
    words = word_tokenize(text.lower())

    # Remove stopwords (common words like "the", "is", etc.)
    stop_words = set(stopwords.words("english"))
    filtered_words = [word for word in words if word.casefold() not in stop_words]

    # Perform stemming to reduce words to their root form
    stemmer = PorterStemmer()
    stemmed_words = [stemmer.stem(word) for word in filtered_words]

    # Calculate the frequency distribution of words
    word_frequencies = FreqDist(stemmed_words)

    # Sort the words based on their frequency
    sorted_words = sorted(word_frequencies.items(), key=lambda x: x[1], reverse=True)

    # Extract the top 'num_sentences' most frequent words
    top_words = [word[0] for word in sorted_words[:num_sentences]]

    # Generate the summary by joining the top words into sentences
    summary = ' '.join(top_words)

    return summary

# Example usage
input_text = "Lorem ipsum dolor sit amet, consectetur adipiscing elit. Sed efficitur lorem auctor, blandit velit in, faucibus ipsum. Vivamus tincidunt mauris ut nisl tristique, et scelerisque purus interdum. Phasellus eu urna massa. Aliquam convallis dictum est, id aliquet dui hendrerit eget. Sed ullamcorper tincidunt lacinia. Mauris auctor lorem eget luctus venenatis. Duis tincidunt nunc sit amet eros ullamcorper placerat. Sed in lectus ac sapien tristique tincidunt. Sed viverra dignissim sapien, sit amet consectetur lorem dignissim a."

num_sentences = 2
summary = text_summarization(input_text, num_sentences)
print("Summary:")
print(summary)


exampleSet = [{'type':'type1'},
              {'type':'type2'},
              {'type':'type2'},
              {'type':'type3'}
              ]

keyValList = ['type2','type3']
expectedResult = [d for d in exampleSet if d['type'] in keyValList]
print(expectedResult)

# 2 вариант

res = list(filter(lambda d: d['type'] in keyValList, exampleSet))
print(res)
# [{'type': 'type2'}, {'type': 'type2'}, {'type': 'type3'}]

# 3 вариант

from itertools import filterfalse
for elem in filterfalse(lambda x: x['type'] not in keyValList, exampleSet):
    print( elem)


from PIL import Image
from diffusers import DPMSolverMultistepScheduler, ControlNetModel, StableDiffusionControlNetPipeline
import torch
from controlnet_aux import MidasDetector, LineartDetector
import PIL.ImageOps

import numpy as np
import cv2

# set device
device = torch.device('cuda' if torch.cuda.is_available() else 'cpu')
if device.type != 'cuda':
    raise ValueError("need to run on GPU")
# set mixed precision dtype
dtype = torch.bfloat16 if torch.cuda.get_device_capability()[0] == 8 else torch.float16

def resize_image(image: Image, resolution = 512):
    W, H = image.size
    if resolution < min(W, H):
        k = resolution / min(W, H)
        W *= k
        H *= k

    W_new = int(np.round(W/8) * 8)
    H_new = int(np.round(H/8) * 8)
    return image.resize((W_new, H_new))

lineart = LineartDetector.from_pretrained("lllyasviel/Annotators")
depth = MidasDetector.from_pretrained("lllyasviel/Annotators")

cn_steps = [
    ControlNetModel.from_pretrained("lllyasviel/control_v11p_sd15_lineart", torch_dtype=torch.float16),
    ControlNetModel.from_pretrained("lllyasviel/control_v11f1p_sd15_depth", torch_dtype=torch.float16)
]

pipe = StableDiffusionControlNetPipeline.from_pretrained(
    "runwayml/stable-diffusion-v1-5", controlnet=cn_steps, torch_dtype=torch.float16
)
pipe.scheduler = DPMSolverMultistepScheduler.from_config(pipe.scheduler.config)
pipe.enable_xformers_memory_efficient_attention()
pipe.enable_model_cpu_offload()

generator = torch.Generator(device="cpu").manual_seed(1)

with open("cat.jpg", "rb") as i:
    image = Image.open("cat.jpg").convert("RGB")

image = resize_image(image)

cn_images = [
    lineart(image),
    depth(image),
]

output_image = pipe(
    prompt="A cute cat sitting on marble stairs, high quality, highly-detailed, hyper-realistic, RAW, DSLR",
    negative_prompt="ugly, deformed, malformed, bad, low quality",
    image=cn_images,
    generator=generator,
    guidance_scale=7.5,
    num_inference_steps=40,
).images[0]

print("Done rendering image.")

print(output_image)


class Solution(object):
    """
    :type s: int
    :type nums: List[int]
    :rtype: int
    """
    def minSubArrayLen(self, s, nums):
        if nums == None or len(nums) == 0 or s <= 0:
            return 0

        j, sum, count = 0, 0, len(nums)+1
        for i in range(len(nums)):
            while j < len(nums) and sum < s:
                sum += nums[j]
                j += 1
            if sum >= s:
                count = min(count, j-i)
            sum -= nums[i]

        if count == len(nums)+1:
            return 0
        else:
            return count


from flask import Flask, render_template, request, redirect
from flask_sqlalchemy import SQLAlchemy
from datetime import datetime

app=Flask(__name__)

app.config['SQLALCHEMY_DATABASE_URI'] = "sqlite:///vatsetu.db"
app.config['SQLALCHEMY_TRACK_MODIFICATIONS'] = False
db = SQLAlchemy(app)

class vatsetu(db.Model):
    sno = db.Column(db.Integer, primary_key=True)
    phone = db.Column(db.Integer, nullable=False)
    description = db.Column(db.String(800), nullable=True)
    place = db.Column(db.String(200), nullable=False)
    item = db.Column(db.String(500), nullable=False)

    date_created = db.Column(db.DateTime, default=datetime.utcnow)

    def __repr__(self) -> str:
        return f"{self.sno} - {self.title}"

@app.route('/',methods=['GET','POST'])
def fun1():
    return render_template("index.html")

@app.route('/txtfind', methods=['GET','POST'])
def search():
    if request.method=='POST':
        search=request.form['search']
        allTodo=vatsetu.query.all()
        return render_template('page3.html',allTodo=allTodo, search=search)
    else:
        return render_template("index.html")

@app.route('/fun')
def fun():
    return render_template("page1.html")

@app.route('/donor', methods=['GET','POST'])
def donate():
    allTodo = vatsetu.query.all()
    if request.method=='POST':
        items = request.form['donoitem']
        desc = request.form['donodesc']
        phone = int(request.form['donomobile'])
        city = request.form['donocity']
        todo = vatsetu(phone=phone, place=city, item=items, description=desc)
        db.session.add(todo)
        db.session.commit()
        allTodo = vatsetu.query.all()
    return render_template('page3.html', allTodo=allTodo, item=0, place=0,search=0)

@app.route('/donorinfo')
def donar():
    return render_template('page2.html')

@app.route('/search', methods=['GET','POST'])
def find():
    if request.method=='POST':
        item=request.form['item']
        place=request.form['place']
        allTodo = vatsetu.query.all()
        return render_template("page3.html", item=item, place=place, allTodo=allTodo)
    else:
        return render_template('index.html')

@app.route('/delete/<int:sno>')
def delete(sno):
    todo = vatsetu.query.filter_by(sno=sno).first()
    db.session.delete(todo)
    db.session.commit()
    return redirect("/donor")

@app.route('/update/<int:sno>', methods=['GET', 'POST'])
def update(sno):
    if request.method=='POST':
        item = request.form['title']
        desc = request.form['desc']
        phone = request.form['phone']
        place = request.form['city']
        todo = vatsetu.query.filter_by(sno=sno).first()
        todo.item = item
        todo.phone = phone
        todo.place = place
        todo.description = desc
        db.session.add(todo)
        db.session.commit()
        return redirect("/donor")

    todo = vatsetu.query.filter_by(sno=sno).first()
    return render_template('update.html', todo=todo)

if __name__ == "__main__":
    app.run(debug=False, post='0.0.0.0')


import socket
import pickle
import struct
from PIL import Image

def read_image(file_path):
    with Image.open(file_path) as im:
        width, height=im.width, im.height
    with open(file_path, "rb") as file:
        image_bytes = file.read()
    return width, height, image_bytes

print("Result Generated, sending across")
# Constants
HOST = '192.168.29.16'
PORT = 12345

# Create a socket connection to Unity
client_socket = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
client_socket.connect((HOST, PORT))

width, height, imagebytes=read_image("mask.png")

client_socket.sendall(imagebytes)
#client_socket.sendall(height.to_bytes(2, 'little', signed=False))

client_socket.close()
client_socket=None

#a=input()


from pathlib import Path
import matplotlib.pyplot as plt # ensure you have intalled matplotlib before importing it. available in the project brief.
import csv

#--------------- PART 1: This part of the program is completed for you --------------#

# create a file to csv file.
fp = Path.cwd()/"superstore_transaction.csv"

# read the csv file to append profit and quantity from the csv.
with fp.open(mode="r", encoding="UTF-8", newline="") as file:
    reader = csv.reader(file)
    next(reader) # skip header

    # create 3 empty lists to store profit and quantity by each cluster
    cluster1 = []
    cluster2 = []
    cluster3 = []

    # append profit and quantity as a list back to each empty list
    for row in reader:

        if row[4] == "Cluster 1":
            cluster1.append([row[13], row[14]])
        elif row[4] == "Cluster 2":
            cluster2.append([row[13], row[14]])
        else:
            cluster3.append([row[13], row[14]])

#---------------------------- PART 2: Insert your own code ---------------------------#
# 1. Calculate the total profit and total quantity using cluster 1,2,3 variables from part 1
# 2. Write the calculated profit to a txt file. Name it as cluster_report.txt.

# This is to import path method from pathlib
from pathlib import Path
# This is to create a file path to the computer's home directory
file_path = Path.home()/"cluster_report.txt"
# Creating a new .txt file to store the calculated total profit and total quantity
file_path.touch()
# Create a function that has 1 parameter to calculate the total profit using the cluster variables
def profit_calc(cluster):
    """
    - This function calculates the total profit
    - This function accepts 1 parameter : cluster
    """
    # This is to create a variable and assign the value of 0 to store the values and so that total+=data is 0 + data
    total_Profit = 0
    # using a for loop to loop the data from clusters 1,2, and 3
    for data in cluster:
        # Checking if there is a negative symbol at the beginning of the value ( index position 0 )
        if data[0][0]=='-':
            # Replacing the dollar sign symbol $ at the beginning of the value with an empty space
            new_profit = data[0].replace("$", "")
            # Replacing , with an empty space
            new_profit = new_profit.replace(",", "")
            # Calculating the total profit by adding the new profit to the total profit of 0
            total_Profit += float(new_profit)
        # Checking if the value is positive and has no negative symbol
        else:
            # Replacing the dollar sign symbol $ with an empty space
            new_profit = data[0].replace("$", "")
            # Replacing the , with an empty space
            new_profit = new_profit.replace(",", "")
            # Adding the value of 0 which is the total to new profit in order to calculate the total profit
            total_Profit += float(new_profit)
    # return the total calculated profit to the main program
    return total_Profit

# Creating a function to calculate the total quantity
def quantity_calc(cluster):
    """
    - This function calculates the total quantity
    - This function accepts 1 parameter : cluster
    """
    #This is to create a variable to store the values and assign the value of 0 so that total+=data is 0 + data
    total_Quantity =0
    #using a for loop to loop the data from the clusters
    for data in cluster:
        # Calculating the total quantity by adding the total quantity of 0 to the quantity which is found in index position 1 of each of the clusters
        total_Quantity += float(data[1])
    # Return the total calculated quantity to the main program
    return total_Quantity

# This is to open a file using "with" and "open" keyword in write mode
with file_path.open(mode="w", encoding="UTF-8") as file:
    # Writing the respective total profits of Clusters 1,2,3 into the cluster_report.txt file
    file.write(f"PROFIT REPORT\n=============\nCluster 1: ${profit_calc(cluster1)}\nCluster 2: ${profit_calc(cluster2)}\nCluster 3: ${profit_calc(cluster3)}\n")
    # Writing the respective total quantity of Clusters 1,2,3 into the cluster_report.txt file
    file.write(f"\nQUANTITY REPORT\n===============\nCluster 1: {quantity_calc(cluster1)}\nCluster 2: {quantity_calc(cluster2)}\nCluster 3: {quantity_calc(cluster3)}")

#--------------- PART 3: This part of the program is completed for you  --------------#

# This part of the program plots the profits and quantities by clusters.
# The values profits and quantities are hard-coded, so it is not link to part 2.
# Even if part 2 does not work, part 3 can still be executed.
# Simply execute the code and the plot will be saved as an image file.
# Click on the png file in the explorer panel to see the barplot.

# Do not worry about how the code below works.
# It is an example of visualising data using Python.
# You will learn about data visulisation in analytics module in year 2.

cluster_profit = [133426, 43684, 109224] # hardcoded profit by clusters
cluster_quantity = [18632, 8716, 10524] # hardcoded quantity sold by clusters.
fig, axs = plt.subplots(2, figsize = (10,7))
fig.suptitle("SuperStore Business Performance")
cluster = ["cluster 1", "cluster 2", "cluster 3"]
axs[0].bar(cluster, cluster_profit)
axs[1].bar(cluster, cluster_quantity)
axs[0].set_xlabel("Profit by Clusters")
axs[1].set_xlabel("Quantity Sold by Clusters")
axs[0].set_ylabel("Profit ($)")
axs[1].set_ylabel("Quantity (000s)")
fig.savefig("cluster_barplot.png")
plt.imread("cluster_barplot.png")
plt.show()

Individual Assignment 2/Naomi Ho_IA2_Superstore_Automate.py


#2020.04.30
#Presented by SeongHyeon0409
#분할정복, 재귀

n = int(input())
a = [list(input()) for _ in range(n)]
ans = ''

def b(x, y, n):
    global ans
    temp = a[x][y]
    for i in range(x, x+n):
        for j in range(y, y+n):
            if a[i][j] != temp:
                ans += '('
                b(x, y, n // 2)
                b(x, y + n//2, n // 2)
                b(x + n//2, y, n // 2)
                b(x + n//2, y + n//2, n // 2)
                ans += ')'
                return

    if temp == '0':
        ans += '0'
    else:
        ans += '1'

b(0, 0, n)
print(ans)


import pandas as pd
import matplotlib.pyplot as plt
import numpy as np
x = np.matrix([[1],[2],[3],[4]])
x[2][0] = 5
print(x)

df = pd.read_csv('../ucidata/iris.data') # 加载Iris数据集作为DataFrame对象
X = df.iloc[:, [0, 2]].values # 取出2个特征，并把它们用Numpy数组表示

plt.scatter(X[:50, 0], X[:50, 1],color='red', marker='o', label='setosa') # 前50个样本的散点图
plt.scatter(X[50:100, 0], X[50:100, 1],color='blue', marker='x', label='versicolor') # 中间50个样本的散点图
plt.scatter(X[100:, 0], X[100:, 1],color='green', marker='+', label='Virginica') # 后50个样本的散点图
plt.xlabel('petal length')
plt.ylabel('sepal length')
plt.legend(loc=2) # 把说明放在左上角，具体请参考官方文档
plt.show()
# x = np.ones((np.shape(X)[0],1))
# sample = np.hstack((x,X))
# y1 = sample[:40]
# y2 = sample[50:90]
# print(y1)
# print(y2)
# print(np.shape(y1))
# print(np.shape(y2))
# print(np.shape(np.vstack((y1,y2))))

# X = np.mat([[1],[2],[3]])
# Y = [2,3,4]
# print(np.diag(Y))
# print(np.ones(3))
# print(np.diag(np.diag(X*np.ones(3))))

## 使用拟牛顿法计算 W (并且在找相识Hessian时用BFGS算法)
# def caculateW_BFGS(X,Y,epsilon,Lambda):
#     m = np.shape(X)
#     Lambda  = 0
#     Gk = lambda W: X.T * (Y - np.exp(X * W) / (1 + np.exp(X * W))) + Lambda * W
#     w = np.zeros((m[1],1))
#     D = np.eye(m[1])    #初始化D0
#     k = 0                          #初始化k
#     d = -D * Gk(w)
#     s = findFeet(X,Y,w,d)*d
#     w1 = w + s
#     while math.fabs(Gk(w1).max()) > epsilon:
#         y = Gk(w1)-Gk(w)
#         D = (np.eye(m[1])-(s*y.T)/(y.T*s))*D*(np.eye(m[1])-(y*s.T)/(y.T*s))+(s*s.T)/(y.T*s)
#         w = w1
#         d = -D *Gk(w)
#         s = findFeet(X,Y,w,d)*d
#         w1 = w+s
#     return w1
#
# def findFeet(X,Y,w,dk):          # BFGS线性搜索步长
#     Lw = lambda W: Y.T * X * W - np.ones((1, np.shape(X)[0])) * np.log(1 + np.exp(X * W))
#     Gk = lambda W: X.T * (Y - np.exp(X * W) / (1 + np.exp(X * W))) + Lambda * W  # 梯度计算公式
#     rho = 0.55
#     deta = 0.4
#     alpha = 0
#     alphaK = 0
#     while alpha < 20:
#         newf= Lw(w+(rho**alpha)*dk)
#         old = Lw(w)
#         if(newf < old+deta*(rho**alpha)*Gk(w).T*dk):
#             alphaK = alpha;
#             break
#         alpha += 1
#     return rho**alphaK

def caculateW_NT(X,Y,epsilon):
    Xw = lambda W: np.exp(X*W)/(1+np.exp(X*W))
    m = np.shape(X)
    w = np.zeros((m[1],1))    # 初始化 w
    P = np.diag(np.diag(Xw(w)*np.ones(m[0])))    # 生成以Xw(w)为对角线的矩阵
    A = P.T*P-P            # 计算A
    H = X.T*A*X             # 计算H'
    U = X.T*(Y-Xw(w))         # 计算U
    deta = np.linalg.inv(H)*U   # 计算Xnew - Xold 即 (H')^-1*U
    i = 0
    while np.fabs(deta).max() > epsilon:
        w = w-deta               # 更新w
        P = np.diag(np.diag(Xw(w) * np.ones(m[0])))
        A = P-P.T*P             # 更新A
        H = X.T*A*X            # 更新H'
        U = X.T*(Y-Xw(w))        # 更新U
        deta = np.linalg.inv(H)*U # 更新 Xnew - Xold
        i+=1
    return w

def caculateW_NT(X,Y,epsilon,Num):
    XMin = X.min(0)
    XMin[0,0] = 0
    XMax = X.max(0)
    X = (X-XMin)/(XMax-XMin)
    print("X", X)
    print("Y", Y)
    Xw = lambda W: np.exp(X*W)/(1+np.exp(X*W))
    m = np.shape(X)
    w = np.ones((m[1],1))    # 初始化 w
    print("w",w)
    print("Xw",Xw(w))
    P = np.diag(np.diag(Xw(w)*np.ones(m[0])))
    print("P",P)
    A = P.T*P-P            # 计算A
    print("A",A)
    H = X.T*A*X             # 计算H
    print("H",H)
    U = X.T*(Y-Xw(w))         # 计算U
    print("U",U)
    deta = np.linalg.pinv(H)*U   # 计算Xnew - Xold 即 (H)^-1*U
    print("deta",deta)
    i = 0
    while i <= Num:
        w = w-deta               # 更新w
        print("w",i,w)
        P = np.diag(np.diag(Xw(w) * np.ones(m[0])))
        print("P", i, P)
        A = P-P.T*P             # 更新A'
        if A.max() == 0:
            return w
        print("A", i, A)
        H = X.T*A*X            # 更新H'
        print("H", i, H)
        U = X.T*(Y-Xw(w))        # 更新U
        print("U", i, U)
        deta = np.linalg.pinv(H)*U # 更新 Xnew - Xold
        print("deta", i, deta)
        i+=1
    return w


INPUT_FILE_PATH = "input/d7.txt"
EXECUTION_TAG = "$"
CHANGE_DIR = "cd"
LIST = "ls"
DIR = "dir"

class Node:
    def __init__(self, name, parent=None, size=0):
        self.name = name
        self.size = size
        self.subdirs = []
        self.subfiles = []
        self.parent = parent

    def __repr__(self):
        return "name = " + self.name + " size = " + str(self.size)

    def add_file(self, name, size):
        parent = self
        while parent is not None:
            parent.size += size
            parent = parent.parent
        self.subfiles.append(Node(name, self, size))

    def add_dir(self, name):
        self.subdirs.append(Node(name, self))

    def change_dir(self, name):
        if name == '..':
            return self.parent
        for node in self.subdirs:
            if node.name == name:
                return node
        if self.name == name:
            return self

def all_dirs(nodes, dirs):
    if nodes == []:
        return dirs
    n = nodes.pop()
    for node in n.subdirs:
        if node not in nodes:
            nodes.append(node)
        if node not in dirs:
            dirs.append(node)
    return all_dirs(nodes, dirs)

def main():
    input = parse_input()
    print("Part 1 = ", calc_total_size(input, 100000))
    print("Part 2 = ", size_of_deleted_dir(input))

def size_of_deleted_dir(input):
    root = create_tree(input)
    dirs = all_dirs([root], []) + [root]
    unused_space = 70000000 - root.size
    req_space = 30000000 - unused_space
    lim_dirs = list(filter(lambda d: d.size >= req_space, dirs))
    return sorted(map(lambda d: d.size, lim_dirs))[0]

def calc_total_size(input, limit):
    root = create_tree(input)
    dirs = all_dirs([root], []) + [root]
    lim_dirs = list(filter(lambda d: d.size < limit, dirs))
    return sum(map(lambda d: d.size, lim_dirs))

def create_tree(input):
    root = Node("/")
    node = root
    for line in input:
        node = execute_line(line, node)
    return root

def execute_line(line, node):
    cmd = line.split(" ")
    if cmd[0] == EXECUTION_TAG:
        if cmd[1] == CHANGE_DIR:
            node = node.change_dir(cmd[2])
        elif cmd[1] == LIST:
            pass
    elif cmd[0] == DIR:
        node.add_dir(cmd[1])
    elif cmd[0].isnumeric():
        node.add_file(cmd[1], int(cmd[0]))
    return node

def parse_input():
    with open(INPUT_FILE_PATH) as f:
        return list(map(lambda s: s.strip(), f.readlines()))

if __name__ == "__main__":
   main()