import numpy as np
import torch
from torch.utils.data import Dataset
import matplotlib
from matplotlib import pyplot as plt
import enum
import scipy
from scipy import ndimage, signal
import io
from . import fileloader, util, zernike
from skimage import restoration

@enum.unique
class Augmentation(enum.Enum):
    PIXEL_SHIFT = 1
    NOISE_GAUSSIAN =2

class BaseDataset(Dataset):
    def __init__(self):
        super().__init__()
        self.target_is_image = False

class SimulatedImageDataset(BaseDataset):
    """
    Base class.
    """
    def __init__(self, out_size=(32, 32), length=512, dropout_p=0,
                 image_params={},
                 noise_params={'poisson':True, 'gaussian':10},
                 conv_kernel=None,
                 normalize=True, augmentations={Augmentation.PIXEL_SHIFT:[8,8]},
                 image_params_preset={}):
        super().__init__()

        for key in augmentations:
            if not isinstance(key, Augmentation):
                raise Exception("Augmentation '{}' not recognized. Use Augmentation enum.".format(key))

        self.params_range = image_params
        self.augmentations = augmentations
        self.padding = augmentations.get(Augmentation.PIXEL_SHIFT, [0,0]) # x, y
        self.gen_size = (out_size[0]+2*self.padding[0], out_size[1]+2*self.padding[1])
        self.out_size = out_size

        output_image_shape = np.atleast_1d(np.asarray(length))
        if output_image_shape.shape[0]<2:
            output_image_shape = np.concatenate([output_image_shape, [1]])

        self.set_params(output_image_shape, image_params, image_params_preset)

        shifts = np.stack([self.params['x'].flatten(), self.params['y'].flatten(), self.params['z'].flatten()], axis=-1)

        images = self.generate_images(self.gen_size, output_image_shape, shifts, image_params)

        if dropout_p > 0:
            images = images * (np.random.rand(images.shape[0], 1, 1) > dropout_p)

        images = images * self.params['A'].reshape(-1, 1, 1)

        images = images.reshape(output_image_shape[0], output_image_shape[1], images.shape[1], images.shape[2])
        images = images.sum(axis=1, keepdims=True)

        images = images + self.params['bg'].reshape(-1, 1, 1, 1)

        if not conv_kernel is None:
            conv_kernel = torch.as_tensor(conv_kernel, dtype=torch.float).reshape(1, 1, conv_kernel.shape[-2], conv_kernel.shape[-1])
            images = torch.as_tensor(images, dtype=torch.float)
            images = torch.nn.functional.pad(images, (conv_kernel.shape[-1]//2,)*2 + (conv_kernel.shape[-2]//2,)*2, mode="reflect")
            images = torch.nn.functional.conv2d(images, conv_kernel, padding=0).numpy()

        if len(noise_params) > 0:
            images = self.add_noise(images, noise_params)

        if normalize:
            images -= images.min(axis=(2,3), keepdims=True)
            images /= images.max(axis=(2,3), keepdims=True)

        self.images = images.astype(np.float32)

    def set_params(self, output_image_shape, image_params, image_params_preset):
        # print("Image parameters settings: {}".format(image_params))
        self.params = {}
        self.params['id'] = np.arange(output_image_shape[0])
        self.params['A'] = np.random.uniform(image_params['A'][0], image_params['A'][1], output_image_shape).astype(np.float32)
        self.params['bg'] = np.random.uniform(image_params['bg'][0], image_params['bg'][1], output_image_shape[0]).astype(np.float32)
        self.params['x'] = np.random.uniform(image_params['x'][0], image_params['x'][1], output_image_shape).astype(np.float32)
        self.params['y'] = np.random.uniform(image_params['y'][0], image_params['y'][1], output_image_shape).astype(np.float32)

        if 'z' in image_params:
            self.params['z'] = np.random.uniform(image_params['z'][0], image_params['z'][1], output_image_shape).astype(np.float32)
        else:
            self.params['z'] = np.zeros(output_image_shape).astype(np.float32)

        self.params.update(image_params_preset)

    def generate_images(self, size, length, shifts, image_params):
        raise NotImplementedError()

    def add_noise(self, images, noise_params):
        ret = images.copy()
        if noise_params.get('poisson', False) is True:
            ret += np.random.poisson(images) - images
        if 'gaussian' in noise_params:
            ret += np.random.normal(np.zeros_like(images), noise_params['gaussian'])
        return ret

    def __len__(self):
        return self.images.shape[0]

    def __getitem__(self, key):
        image = self.images[key]
        label = {param_key: param_val[key] for param_key, param_val in self.params.items()}

        if Augmentation.PIXEL_SHIFT in self.augmentations:
            shift = [np.random.randint(0, 2*i+1) for i in self.padding]
            label['x'] = label['x'] - shift[0] + self.padding[0]
            label['y'] = label['y'] - shift[1] + self.padding[1]
            image = image[:,shift[0]:shift[0]+self.out_size[0],shift[1]:shift[1]+self.out_size[1]]

        if Augmentation.NOISE_GAUSSIAN in self.augmentations:
            noise_sig = self.augmentations[Augmentation.NOISE_GAUSSIAN] * (image.max() - image.min())
            image = np.random.normal(image, noise_sig).astype(np.float32)

        return image, label

    def to(self, device):
        self.images = torch.as_tensor(self.images, device=device)

class SingleImageDataset(SimulatedImageDataset):
    """
    Repeatedly sample a single image.
    """
    def __init__(self, data, out_size=(64, 64), length=16, dropout_p=0,
                 image_params={},
                 noise_params={'poisson':True, 'gaussian':10},
                 conv_kernel = None,
                 normalize=True, augmentations={Augmentation.PIXEL_SHIFT:[8,8]},
                 image_params_preset={}):

        default_image_params = {
            'A': [0.5, 2.0],
            'bg': [0, 10],
            'x': [-5, 5],
            'y': [-5, 5],
            # 'conv':np.ones((3,3)),
        }

        _image_params = dict(default_image_params, **image_params)
        _image_params['data'] = data

        super().__init__(out_size=out_size, length=length, dropout_p=dropout_p,
                         image_params=_image_params,
                         noise_params=noise_params,
                         conv_kernel=conv_kernel,
                         normalize=normalize, augmentations=augmentations,
                         image_params_preset=image_params_preset)

    def generate_images(self, size, length, shifts, image_params):
        data = image_params['data']
        # add padding larger than shifts
        shift_max = [np.ceil(np.max([np.abs(shifts[:,i].min()), shifts[:,i].max()])).astype(int) for i in range(len(shifts.shape))]
        crop_size = [size[i] + 2*shift_max[i] for i in range(len(data.shape))]
        data = data[:crop_size[0],:crop_size[1]]

        # zero padding for fft
        padding = [(int(np.ceil(1.5 * data.shape[0])),)*2, (int(np.ceil(1.5 * data.shape[1])),)*2]
        data = np.pad(data, padding, mode='wrap')

        kx = np.fft.fftshift(np.fft.fftfreq(data.shape[0]))
        ky = np.fft.fftshift(np.fft.fftfreq(data.shape[1]))
        self.KX, self.KY = np.meshgrid(kx, ky, indexing='ij')

        fft_image = np.fft.fftshift(np.fft.fft2(data))
        fft_image_mag = np.abs(fft_image)
        fft_image_phase = np.angle(fft_image)

        # helps remove ringing artifacts
        fft_image_mag = fft_image_mag * signal.windows.tukey(fft_image_mag.shape[0], alpha=0.5)[:,None]
        fft_image_mag = fft_image_mag * signal.windows.tukey(fft_image_mag.shape[1], alpha=0.5)[None,:]

        # x, y shift
        fft_image_phase = fft_image_phase - 2 * np.pi * (self.KX[None,...] * shifts[:,0,None,None])
        fft_image_phase = fft_image_phase - 2 * np.pi * (self.KY[None,...] * shifts[:,1,None,None])

        shifted_fft = fft_image_mag * np.exp(1j * fft_image_phase)
        shifted_img = np.fft.ifft2(np.fft.ifftshift(shifted_fft))

        crop = np.concatenate([shift_max[i] + padding[i] for i in range(len(data.shape))])
        shifted_img = shifted_img[:, crop[0]:-crop[1], crop[2]:-crop[3]]

        return np.abs(shifted_img)

class SimulatedPSFDataset(SimulatedImageDataset):
    def __init__(self, out_size=(32, 32), length=512, dropout_p=0,
                 image_params={},
                 noise_params={'poisson':True, 'gaussian':10},
                 normalize=True, augmentations={Augmentation.PIXEL_SHIFT:[8,8]},
                 image_params_preset={}):

        default_image_params = {
            'A': [500, 2000],
            'bg': [0, 100],
            'x': [-0.35*out_size[0], 0.35*out_size[0]],
            'y': [-0.35*out_size[1], 0.35*out_size[1]],
        }

        _image_params = dict(default_image_params, **image_params)

        super().__init__(out_size=out_size, length=length, dropout_p=dropout_p,
                         image_params=_image_params,
                         noise_params=noise_params,
                         normalize=normalize, augmentations=augmentations,
                         image_params_preset=image_params_preset)

    def generate_images(self, size, length, shifts, image_params):
        raise NotImplementedError()

class Gaussian2DPSFDataset(SimulatedPSFDataset):
    def __init__(self, out_size=(32, 32), length=512, dropout_p=0,
                 psf_params={},
                 noise_params={'poisson':True, 'gaussian':100},
                 normalize=False, augmentations={},
                 image_params_preset={}):

        default_image_params = {
            'sig_x':[5, 5],
            'sig_y':[5, 5],
        }

        _image_params = dict(default_image_params, **psf_params)

        super().__init__(out_size=out_size, length=length, dropout_p=dropout_p,
                         image_params=_image_params,
                         noise_params=noise_params,
                         normalize=normalize, augmentations=augmentations,
                         image_params_preset=image_params_preset)

    def generate_images(self, size, length, shifts, psf_params):
        xs = np.arange(0, size[0]) - 0.5*(size[0]-1)
        ys = np.arange(0, size[1]) - 0.5*(size[1]-1)
        XS, YS = np.meshgrid(xs, ys, indexing='ij')

        self.params['sig_x'] = np.random.uniform(*psf_params['sig_x'], length).astype(np.float32)
        self.params['sig_y'] = np.random.uniform(*psf_params['sig_y'], length).astype(np.float32)
        ret = np.exp(-((XS[None,...]-shifts[:,0,None,None])**2/(2*self.params['sig_x'].reshape(-1,1,1)) \
                       + (YS[None,...]-shifts[:,1,None,None])**2/(2*self.params['sig_y'].reshape(-1,1,1))))

        return ret

class FourierOpticsPSFDataset(SimulatedPSFDataset):
    def __init__(self, out_size=(32, 32), length=512, dropout_p=0,
                 psf_params={}, psf_zerns={},
                 noise_params={'poisson':True, 'gaussian':100},
                 normalize=False, augmentations={},
                 image_params_preset={}):

        default_psf_params = {
            'apod':False,
            'pupil_scale':0.75,
        }

        _psf_params = dict(default_psf_params, **psf_params)
        _psf_params["psf_zerns"] = psf_zerns

        super().__init__(out_size=out_size, length=length, dropout_p=dropout_p,
                         image_params=_psf_params,
                         noise_params=noise_params,
                         normalize=normalize, augmentations=augmentations,
                         image_params_preset=image_params_preset)

    def generate_images(self, size, length, shifts, psf_params):
        pupil_padding_factor = 4
        pupil_padding_clip = 0.5 * (pupil_padding_factor - 1)
        pupil_padding = int(pupil_padding_clip*size[0]), int(-pupil_padding_clip*size[0]), int(pupil_padding_clip*size[1]), int(-pupil_padding_clip*size[1])
        kx = np.fft.fftshift(np.fft.fftfreq(pupil_padding_factor*size[0]))
        ky = np.fft.fftshift(np.fft.fftfreq(pupil_padding_factor*size[1]))
        self.KX, self.KY = np.meshgrid(kx, ky, indexing='ij')

        us = np.linspace(-1, 1, pupil_padding_factor*size[0]) * (pupil_padding_factor*size[0]-1) / (size[0]-1)  / psf_params.get('pupil_scale', 0.75)
        vs = np.linspace(-1, 1, pupil_padding_factor*size[1]) * (pupil_padding_factor*size[0]-1) / (size[0]-1)  / psf_params.get('pupil_scale', 0.75)
        US, VS = np.meshgrid(us, vs, indexing='ij')
        R = np.sqrt(US**2 + VS**2)

        if psf_params.get('apod', False):
            pupil_mag = np.sqrt(1-np.minimum(R, 1)**2)
        else:
            pupil_mag = (R <= 1).astype(np.float)
        pupil_phase = zernike.calculate_pupil_phase(R*(R<=1), np.arctan2(US, VS), psf_params.get("psf_zerns", {}))

        self.pupil = pupil_mag * np.exp(1j*pupil_phase)
        self.pupil = self.pupil[pupil_padding[0]:pupil_padding[1], pupil_padding[2]:pupil_padding[3]]
        self.pupil_suppl = {"radial_distance": (R*(R<=1))[pupil_padding[0]:pupil_padding[1], pupil_padding[2]:pupil_padding[3]],
                           "azimuthal_angle": np.arctan2(US, VS)[pupil_padding[0]:pupil_padding[1], pupil_padding[2]:pupil_padding[3]]}

        shifted_pupil_phase = np.tile(pupil_phase, (shifts.shape[0], 1, 1))
        shifted_pupil_phase = shifted_pupil_phase - 2 * np.pi * (self.KX[None,...] * shifts[:,0,None,None])
        shifted_pupil_phase = shifted_pupil_phase - 2 * np.pi * (self.KY[None,...] * shifts[:,1,None,None])
        shifted_pupil_phase = shifted_pupil_phase + np.sqrt(1-np.minimum(R, 1)**2) * shifts[:,2,None,None]

        shifted_pupils = pupil_mag[None,...]*np.exp(1j*shifted_pupil_phase)

        psfs = np.fft.ifftshift(np.fft.ifft2(np.fft.fftshift(shifted_pupils)))
        psfs = psfs[:, pupil_padding[0]:pupil_padding[1], pupil_padding[2]:pupil_padding[3]]
        psfs = np.abs(psfs)**2

        ref_psf = np.fft.ifftshift(np.fft.ifft2(np.fft.fftshift(np.pad(self.pupil, ((pupil_padding[0], -pupil_padding[1]), (pupil_padding[2], -pupil_padding[3]))))))
        ref_psf = ref_psf[pupil_padding[0]:pupil_padding[1], pupil_padding[2]:pupil_padding[3]]
        ref_psf = np.abs(ref_psf)**2

        psfs /= ref_psf.max()

        return psfs

class FileDataset(BaseDataset):
    def __init__(self, file_path,
                 transform=None,
                 image_slice=slice(None),
                 length=None,
                 file_loader=fileloader.PilImageFileLoader,
                 slices=(slice(None),), stack_to_volume=False, cache=True):
        super().__init__()
        self.file = self.load_file(file_path,
                                   file_loader=file_loader,
                                   slices=slices,
                                   stack_to_volume=stack_to_volume,
                                   cache=cache)

        if length is None:
            self.length = len(self.file)
        else:
            self.length = length
        self.transform = transform
        self.image_slice = np.arange(len(self.file), dtype=np.int32)[image_slice]

    def load_file(self, file_path, file_loader, slices, stack_to_volume, cache):
        file_loaded = file_loader(file_path, slices=slices,
                                  stack_to_volume=stack_to_volume, cache=cache)
        print(", ".join(["{}: {}".format(key, val) for key, val in
                         {"filepath":file_loaded.file_path,
                          "frames":len(file_loaded),
                          "image shape":file_loaded[0].shape}.items()]))
        return file_loaded

    def __len__(self):
        return self.length

    def __getitem__(self, key):
        file_id = np.random.choice(self.image_slice)

        img = torch.as_tensor(self.file[file_id])
        if not self.transform is None:
            img = self.transform(img)

        return img, {'id': key}

class ResamplingFileDataset(FileDataset):
    # overlap with SingleImageDataset?
    def __init__(self, file_path, out_size=(64, 64, 64),
                 length=16,
                 file_loader=fileloader.PilImageFileLoader,
                 slices=(slice(None),), stack_to_volume=False, cache=True):
        super().__init__(file_path=file_path, length=length,
                         file_loader=file_loader,
                         slices=slices, stack_to_volume=stack_to_volume,
                         cache=cache)

        self.in_size = self.file[0][0].shape
        self.out_size = [min(out_size[dim], self.in_size[dim]) for dim in range(len(out_size))]

        if (self.out_size < list(out_size)):
            print("out_size {} clipped to {}".format(out_size, self.out_size))
        print(self.in_size, self.out_size)

    def __getitem__(self, key):
        file_id = np.random.randint(0, len(self.file), dtype=np.int32)
        shifts = np.asarray([np.random.randint(0, self.in_size[dim] - self.out_size[dim] + 1) for dim in range(len(self.in_size))])

        labels = {'id':file_id, }
        labels.update({"slice_{}".format(['x','y','z'][i]): shift for i, shift in enumerate(shifts)})

        slicing = np.stack([shifts, shifts + self.out_size], -1)
        slicing = tuple([slice(None),] + [slice(a, b) for (a, b) in slicing])

        return self.file[file_id][slicing], labels

class FilePairsDataset(FileDataset):
    def __init__(self, file_path, target_file_path,
                 transform=None, target_transform=None,
                 image_slice=slice(None),
                 length=16,
                 file_loader=fileloader.PilImageFileLoader,
                 slices=(slice(None),), stack_to_volume=False, cache=True):
        super().__init__(file_path=file_path,
                         file_loader=file_loader, slices=slices,
                         stack_to_volume=stack_to_volume,
                         cache=cache)

        self.target_is_image = True
        self.target_file = self.load_file(target_file_path,
                                          file_loader=file_loader,
                                          slices=slices,
                                          stack_to_volume=stack_to_volume,
                                          cache=cache)
        self.transform = transform
        self.target_transform = target_transform

        self.image_slice = np.arange(len(self.file), dtype=np.int32)[image_slice]

    def __getitem__(self, key):
        file_id = np.random.choice(self.image_slice)

        img = torch.as_tensor(self.file[file_id])
        target = torch.as_tensor(self.target_file[file_id])

        seed = np.random.randint(2147483648)
        if not self.transform is None:
            torch.manual_seed(seed)
            img = self.transform(img)
        if not self.target_transform is None:
            torch.manual_seed(seed)
            target = self.transform(target)

        return img, target

def inspect_images(dataset, indices=None):
    if indices is None:
        indices = np.random.choice(len(dataset), min(8, len(dataset)), replace=False)
    images, labels = zip(*[(dataset[i][0].detach().cpu().numpy() if torch.is_tensor(dataset[i][0]) else dataset[i][0], dataset[i][1]) for i in indices])

    tiled_images, n_col, n_row  = util.tile_images(util.reduce_images_dim(np.stack(images, axis=0)), full_output=True)

    fig, axes = plt.subplots(2, 1, figsize=(4*n_col, 3*n_row*2))
    im = axes[0].imshow(tiled_images)
    plt.colorbar(im, ax=axes[0])
    im = axes[1].imshow(np.log(tiled_images))
    plt.colorbar(im, ax=axes[1])
    axes_to_label = [axes,]

    if dataset.target_is_image is True:
        tiled_images, n_col, n_row  = util.tile_images(util.reduce_images_dim(np.stack(labels, axis=0)), full_output=True)
        fig, axes = plt.subplots(2, 1, figsize=(4*n_col, 3*n_row*2))
        im = axes[0].imshow(tiled_images)
        plt.colorbar(im, ax=axes[0])
        im = axes[1].imshow(np.log(tiled_images))
        plt.colorbar(im, ax=axes[1])
        axes_to_label.append(axes)

    for i, id in enumerate(indices):
        label = "{}:\t".format(id)
        if dataset.target_is_image is False:
            for key, val in labels[i].items():
                label += " [{} =".format(key)
                for datum in np.atleast_1d(val.squeeze()):
                    label += " {:.3f},".format(datum)
                label += "],"
        print(label)

        for axes in axes_to_label:
            for j in range(2):
                axes[j].text(i%n_col / n_col, i//n_col / n_row,
                             # label,
                             id,
                             bbox={'facecolor':'white', 'alpha':1},
                             ha='left', va='bottom',
                             fontsize='medium',
                             transform=axes[j].transAxes)

    if hasattr(dataset, 'params'):
        fig, axes = plt.subplots(1, len(dataset.params), figsize=(4*len(dataset.params), 3))
        for i, (key, val) in enumerate(dataset.params.items()):
            axes[i].hist(val.flatten(), bins=20)
            axes[i].set_xlabel(key)

    if hasattr(dataset, 'pupil'):
        fig, axes = plt.subplots(1, 3, figsize=(4*2 + 8, 3), gridspec_kw={'width_ratios': [1,1,3]})
        pupil_magnitude = np.abs(dataset.pupil)
        pupil_magnitude_colored, norm, cmap = util.color_images(pupil_magnitude, full_output=True)
        im = axes[0].imshow(pupil_magnitude_colored)
        plt.colorbar(matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap), ax=axes[0])
        axes[0].set_title('pupil mag')

        pupil_phase = restoration.unwrap_phase(np.ma.array(np.angle(dataset.pupil), mask=np.abs(dataset.pupil)<=0))
        pupil_phase_colored, norm, cmap = util.color_images(pupil_phase, vsym=True, full_output=True)
        im = axes[1].imshow(pupil_phase_colored)
        plt.colorbar(matplotlib.cm.ScalarMappable(norm=norm, cmap=cmap), ax=axes[1])
        axes[1].set_title('pupil phase')

        zernike_coeffs = zernike.fit_zernike_from_pupil(dataset.pupil, 16, dataset.pupil_suppl["radial_distance"], dataset.pupil_suppl["azimuthal_angle"])
        zernike.plot_zernike_coeffs(axes[2], zernike_coeffs)

        fig.tight_layout()


#!/usr/bin/env python3

heatmap_skeleton = '''$(function () {
    $('#container').highcharts({
        chart: {
            type: 'heatmap',
            marginTop: 40,
            marginBottom: 40
        },
        title: {
            text: null
        },
        xAxis: {
            categories: [%s],
            title: 'k'
        },
        yAxis: {
            categories: [%s],
            title: 'm'
        },
        colorAxis: {
            min: 0,
            minColor: '#FFFFFF',
            maxColor: Highcharts.getOptions().colors[1]
        },
        legend: {
            align: 'right',
            layout: 'vertical',
            margin: 0,
            verticalAlign: 'top',
            y: 25,
            symbolHeight: 320
        },
        series: [{
            name: null,
            borderWidth: 1,
            data: [%s],
            dataLabels: {
                enabled: false,
                color: 'black',
                style: {
                    textShadow: 'none',
                    HcTextStroke: null
                }
            }
        }]
    });
});'''
heatmap_skeleton = ' '.join(s.strip() for s in heatmap_skeleton.split('\n'))

if __name__ == '__main__':
    import sys
    import re

    filename_reg = re.compile(r'^(time|count)-(.+)-(\d+)-(\d+)-(\d+)$')

    data = {'time': {}, 'count': {}}
    for line in sys.stdin.readlines():
        line = line.strip()
        match = filename_reg.match(line)
        if match:
            type_ = match.group(1)
            name = match.group(2)
            k = int(match.group(3))
            m = int(match.group(4))
            n = int(match.group(5))

            if type_ == 'count' and k <= 3:
                continue

            try:
                ls = list(map(float, open(match.group(0)).readlines()))
            except ValueError:
                print('File %s is malformated' % match.group(0), file=sys.stderr)
                continue
            if not ls:
                continue

            avg = sum(ls) / len(ls)

            data[type_].setdefault(name, {})
            data[type_][name][k, m, n] = avg

    for type_, element in data.items():
        for name, table in element.items():
            kCategories = set()
            mCategories = set()
            for (k, m, n), avg in table.items():
                kCategories.add(k)
                mCategories.add(m)

            kCategories = sorted(kCategories)
            mCategories = sorted(mCategories)

            serie = list()
            for (k, m, n), avg in table.items():
                serie.append((kCategories.index(k), mCategories.index(m), avg))

            strKCategories = ', '.join(map(str, kCategories))
            strMCategories = ', '.join(map(str, mCategories))
            strSerie = ', '.join('[%s, %s, %s]' % e for e in serie)
            print(type_, name)
            print(heatmap_skeleton % (strKCategories, strMCategories, strSerie))


import math
import os.path
import re
import html

def calcScore(now, best):
    if now<1e-9:
        return 0
    #return now / best
    return best / now

def isBetter(now, best):
    if now<1e-9:
        return False
    #return best < now
    return now < best

def main():
    import sqlite3
    db = sqlite3.connect('mm.sqlite3')
    cur = db.cursor()
    cur.execute('select run_id, name, source, created_at from runs')
    CREATED_AT = {}
    NAME = {}
    SRC = {}
    for run_id, name, source, created_at in cur.fetchall():
        NAME[run_id] = name
        SRC[run_id] = source
        CREATED_AT[run_id] = created_at
    cur.execute('select run_id, test_id, sec, stdout, stderr from results order by run_id, test_id')
    R = {}
    for run_id, test_id, sec, text_stdout, text_stderr in cur.fetchall():
        if run_id not in R:
            R[run_id] = 0
        R[run_id] += 1
    pattern = re.compile(r'(\w+) *[=:] *([\d\.]+)')
    T = {}
    S = {}
    TIME = {}
    cur.execute('select run_id, test_id, sec, stdout, stderr from results order by run_id, test_id')
    for run_id, test_id, sec, text_stdout, text_stderr in cur.fetchall():
        if R[run_id] != 100:
            continue
        if run_id not in S:
            S[run_id] = {}
        if test_id not in T:
            T[test_id] = {}
        if run_id not in TIME:
            TIME[run_id] = [sec, sec, sec]
        else:
            TIME[run_id][0] = min(TIME[run_id][0], sec)
            TIME[run_id][1] += sec
            TIME[run_id][2] = max(TIME[run_id][2], sec)
        S[run_id][test_id] = -1
        for text in (text_stdout, text_stderr):
            for line in text.split("\n"):
                m = pattern.match(line)
                if m:
                    if m.group(1).lower()=='score':
                        S[run_id][test_id] = float(m.group(2))
                    else:
                        T[test_id][m.group(1)] = float(m.group(2))
    BEST = {}
    BEST_COUNT = {}
    for run_id in S:
        for test_id in S[run_id]:
            if test_id not in BEST or isBetter(S[run_id][test_id], BEST[test_id]):
                BEST[test_id] = S[run_id][test_id]
                BEST_COUNT[test_id] = 1
            elif BEST[test_id] == S[run_id][test_id]:
                BEST_COUNT[test_id] += 1
    T2 = {}
    for test_id in T:
        for name in T[test_id]:
            if name not in T2:
                T2[name] = []
            T2[name].append(T[test_id][name])
    T2 = {name: sorted(T2[name]) for name in T2}
    print(T2)
    def splitKind(values):
        target = len(values) / 3
        best = len(values)
        best_i = 0
        for i in range(1, len(values)):
            if values[i-1]!=values[i]:
                sc = abs(i-target)
                if best is None or sc<best:
                    best = sc
                    best_i = i
        assert best_i is not None
        for j in range(10):
            sep = ('{:.%df}' % (j, )).format((values[best_i-1]+values[best_i])/2)
            sep_f = float(sep)
            if values[best_i-1] < sep_f < values[best_i]:
                break
        best = len(values)
        best_i = len(values)-1
        for i in range(len(values)-1, 0, -1):
            if values[i-1]!=values[i]:
                sc = abs(len(values)-i-target)
                if best is None or sc<best:
                    best = sc
                    best_i = i
        assert best_i is not None
        for j in range(10):
            sep2 = ('{:.%df}' % (j, )).format((values[best_i-1]+values[best_i])/2)
            sep2_f = float(sep2)
            if values[best_i-1] < sep2_f < values[best_i]:
                break
        return sep, sep2

    T3 = {name: splitKind(T2[name]) for name in T2}
    print(T3)
    import http.server
    import urllib.parse
    class MyHandler(http.server.BaseHTTPRequestHandler):
        def getSource(self, query):
            self.send_response(200)
            self.send_header('Content-Type', 'text/plain; charset=utf-8')
            self.end_headers()
            run_id = int(query.get('id', [])[0])
            self.wfile.write(SRC[run_id].encode())
        def getDetail(self, query):
            self.send_response(200)
            self.send_header('Content-Type', 'text/html; charset=utf-8')
            self.end_headers()
            param = query.get('PARAM', [])
            run_id = int(query.get('id', [])[0])
            query.pop('id')
            htmls = []
            htmls.append('')
            htmls.append('')
            htmls.append('<title>MM Analytics</title>')
            htmls.append('')
            htmls.append('')
            htmls.append(f'
Name: {html.escape(f"{NAME[run_id]}")}
')
            htmls.append(f'[TOP]')
            htmls.append(f'[SOURCE]')
            htmls.append('
')
            if 2<=len(param):
                sum_score = [0]*9
                sum2_score = [0]*9
                count_score = [0]*9
                bests = [0]*9
                uniques = [0]*9
                fails = [0]*9
                for test_id in S[run_id]:
                    kind = 4
                    if T[test_id][param[0]]<float(T3[param[0]][0]):
                        kind -= 1
                    elif float(T3[param[0]][1])<T[test_id][param[0]]:
                        kind += 1
                    if T[test_id][param[1]]<float(T3[param[1]][0]):
                        kind -= 3
                    elif float(T3[param[1]][1])<T[test_id][param[1]]:
                        kind += 3
                    if 0 < S[run_id][test_id]:
                        sc1 = calcScore(S[run_id][test_id], BEST[test_id])
                        sum_score[kind] += sc1
                        sum2_score[kind] += sc1*sc1
                    else:
                        fails[kind] += 1
                    count_score[kind] += 1
                    if BEST[test_id] == S[run_id][test_id]:
                        bests[kind] += 1
                        if BEST_COUNT[test_id]==1:
                            uniques[kind] += 1
                #for kind in range(3):
                #    score = '{:.3f}'.format(100 * sum_score[kind] / count_score[kind])
                #    htmls.append(f'{score}	{bests[kind]}	{uniques[kind]}	{fails[kind]}	')
                htmls.append('
')
                htmls.append(f'
	{T3[param[0]][0]}>	{param[0]}	>{T3[param[0]][1]}
')
                htmls.append('
')
                for i in range(3):
                    htmls.append('Score	Std	Bests	Uniqs	Fails	Tests	')
                htmls.append('
')
                labels = [f'{T3[param[1]][0]}>', f'{param[1]}', f'>{T3[param[1]][1]}']
                for y in range(3):
                    htmls.append(f'
{labels[y]}	')
                    for x in range(3):
                        kind = y * 3 + x
                        avg_score = sum_score[kind] / count_score[kind]
                        score = '{:.3f}'.format(100 * avg_score)
                        std_score = '{:.3f}'.format(100 * math.sqrt((sum2_score[kind] - sum_score[kind]*avg_score) / count_score[kind]))
                        htmls.append(f'{score}	{std_score}	{bests[kind]}	{uniques[kind]}	{fails[kind]}	{count_score[kind]}	')
                    htmls.append('
')
                htmls.append('
')
            htmls.append('')
            htmls.append('')
            self.wfile.write("\n".join(htmls).encode())
        def getIndex(self, query):
            if 'id' in query or 'name' in query:
                if 'id' in query and 'name' in query:
                    cur.execute('update runs set name = ? where run_id = ?', (query['name'][-1], int(query['id'][-1])))
                    NAME[int(query['id'][-1])] = query['name'][-1]
                    db.commit()
                query.pop('id')
                query.pop('name')
                self.send_response(302)
                self.send_header('Location', '/?' + urllib.parse.urlencode(query, True))
                self.end_headers()
                return
            self.send_response(200)
            self.send_header('Content-Type', 'text/html; charset=utf-8')
            self.end_headers()
            param = query.get('PARAM', [])
            htmls = []
            htmls.append('')
            htmls.append('')
            htmls.append('<title>MM Analytics</title>')
            htmls.append('')
            htmls.append('')
            htmls.append('''

''')
            for name in T3:
                if name not in param:
                    htmls.append(f'
_ {name}: {T3[name][0]}, {T3[name][1]}
')
                else:
                    param2 = list(param)
                    param2.remove(name)
                    htmls.append(f'
v {name}: {T3[name][0]}, {T3[name][1]}
')
            htmls.append('
')
            htmls.append('
ID	CREATED_AT	NAME	Time	Whole	')
            for name in param:
                htmls.append(f'{T3[name][0]}>	')
                htmls.append(f'{name}	')
                htmls.append(f'>{T3[name][1]}	')
            htmls.append('
')
            htmls.append('
')
            htmls.append('MIN	AVG	MAX	')
            htmls.append('Score	Std	Bests	Uniqs	Fails	Tests	')
            for name in param:
                htmls.append('Score	Std	Bests	Uniqs	Fails	Tests	')
                htmls.append('Score	Std	Bests	Uniqs	Fails	Tests	')
                htmls.append('Score	Std	Bests	Uniqs	Fails	Tests	')
            htmls.append('
')
            for run_id in reversed(list(S.keys())):
                sum_score = 0
                sum2_score = 0
                count_score = 0
                bests = 0
                uniques = 0
                fails = 0
                for test_id in S[run_id]:
                    if 0 < S[run_id][test_id]:
                        sc1 = calcScore(S[run_id][test_id], BEST[test_id])
                        sum_score += sc1
                        sum2_score += sc1*sc1
                    else:
                        fails += 1
                    count_score += 1
                    if BEST[test_id] == S[run_id][test_id]:
                        bests += 1
                        if BEST_COUNT[test_id]==1:
                            uniques += 1
                avg_score = sum_score / count_score
                score = '{:.3f}'.format(100 * avg_score)
                std_score = '{:.3f}'.format(100 * math.sqrt((sum2_score - sum_score*avg_score) / count_score))
                sec_min = '{:.3f}'.format(TIME[run_id][0])
                sec_avg = '{:.3f}'.format(TIME[run_id][1] / count_score)
                sec_max = '{:.3f}'.format(TIME[run_id][2])
                htmls.append(f'
{run_id}	{CREATED_AT[run_id]}	{html.escape(f"{NAME[run_id]}")}	{sec_min}	{sec_avg}	{sec_max}	{score}	{std_score}	{bests}	{uniques}	{fails}	{count_score}	')
                for name in param:
                    sum_score = [0]*3
                    sum2_score = [0]*3
                    count_score = [0]*3
                    bests = [0]*3
                    uniques = [0]*3
                    fails = [0]*3
                    for test_id in S[run_id]:
                        kind = 1
                        if T[test_id][name]<float(T3[name][0]):
                            kind = 0
                        elif float(T3[name][1])<T[test_id][name]:
                            kind = 2
                        if 0 < S[run_id][test_id]:
                            sc1 = calcScore(S[run_id][test_id], BEST[test_id])
                            sum_score[kind] += sc1
                            sum2_score[kind] += sc1*sc1
                        else:
                            fails[kind] += 1
                        count_score[kind] += 1
                        if BEST[test_id] == S[run_id][test_id]:
                            bests[kind] += 1
                            if BEST_COUNT[test_id]==1:
                                uniques[kind] += 1
                    for kind in range(3):
                        avg_score = sum_score[kind] / count_score[kind]
                        score = '{:.3f}'.format(100 * avg_score)
                        std_score = '{:.3f}'.format(100 * math.sqrt((sum2_score[kind] - sum_score[kind]*avg_score) / count_score[kind]))
                        htmls.append(f'{score}	{std_score}	{bests[kind]}	{uniques[kind]}	{fails[kind]}	{count_score[kind]}	')
                htmls.append(f'
')
            htmls.append('
')
            htmls.append('')
            htmls.append('')
            self.wfile.write("\n".join(htmls).encode())
        def do_GET(self):
            path, qs = (self.path.split('?') + [''])[:2]
            query = urllib.parse.parse_qs(qs)
            #query = {q: (query[q]+[''])[-1] for q in query}
            if path=='/':
                return self.getIndex(query)
            if path=='/detail':
                return self.getDetail(query)
            elif path=='/source':
                return self.getSource(query)
            elif path=='/favicon.ico':
                self.send_response(200)
                self.send_header('Content-Type', 'image/x-icon')
                self.end_headers()
                self.wfile.write(open(os.path.join(os.path.dirname(__file__), 'favicon.ico'), 'rb').read())
            else:
                self.send_response(200)
                self.send_header('Content-Type', 'text/html; charset=utf-8')
                self.end_headers()
                htmls = []
                htmls.append('')
                htmls.append('')
                htmls.append(self.path)
                htmls.append(f'{query}')
                htmls.append('')
                htmls.append('')
                self.wfile.write("\n".join(htmls).encode())
    with http.server.HTTPServer(('', 8080), MyHandler) as server:
        print('start httpd ...')
        server.serve_forever()


# 구구단2단 출력하는 함수를 만들어 보세요
# gugudan
def gugudan(dan) :
    for j in range(1,10):
        print(dan,'x', j, '=', dan*j)

for dan in range(2, 20+1):
    gugudan(dan)

# 이거 하는데 1시간 걸림


import numpy as np
def main(x):
    result = 1
    k = 2
    while x> 1.99:
        if int(x**(1/k)) == 1:
            break
        elif int(x**(1/k)) == x**(1/k):
            result *= k
            x = x**(1/k)
            k = 2
        else:
            k+=1
    if result<=1:
        return "NO"
    return result

print(1000**(1/3))
print(int(1000**(1/3)))
n = int(input())
for i in range(n):
    print(main(int(input())))


#!/usr/bin/env python3

import hashlib

key = 'iwrupvqb'
i = 1
while True:
    s = '{}{}'.format(key, i)
    h = hashlib.md5(s.encode('ascii')).hexdigest()
    if h.startswith('00000'):
        print("Answer for 5 zeros is {} ({})".format(i, s))
        break
    i += 1

i = 1
while True:
    s = '{}{}'.format(key, i)
    h = hashlib.md5(s.encode('ascii')).hexdigest()
    if h.startswith('000000'):
        print("Answer for six zeros is {} ({})".format(i, s))
        break
    i += 1


from PYmodule import *

log10Ms = [9,10,11,12]
typenames = ['H'+r'$_2$', 'H-H'+r'$_2$', 'H-H']

pres = ['./data/1e9','./data/1e10','./data/1e11','./data/1e12','./data/1e13']

print('z=6 to 4, t in Myr: ', (t_from_z(4)-t_from_z(6))/Myr)

M_grow_ratio = 5.
f_lambda = np.log(M_grow_ratio) * t_Edd / (t_from_z(4)-t_from_z(6))
print(f_lambda)

exit(0)

i_bsm = 0
iM = 2

T_tell = 8000
eta = 0.3

T=ascii.read(pres[iM]+'Jcol_'+str(i_bsm)+'.txt', guess=False,delimiter=' ') #  None has np.where(T['z_col']==-1)
T['Mdot'] = (k_B*T['Tg_loi']*T['f_loi']/(mu*m_H))**1.5/G/(Ms/yr)
T['Mstar0'] = np.zeros(len(T))
T['Mstar_z'] = np.zeros(len(T))
T['Lbol_z'] = np.zeros(len(T))
T['M1450_z'] = np.zeros(len(T))
for i in range(len(T)):
    T['Mstar0'][i] = Mdot2M(T['Mdot'][i]*eta)
T['on'] = np.ones(len(T))
T['Edd_ratio'] = np.ones(len(T))
# print("max T['Edd_ratio']=",np.max(T['Edd_ratio']))

abin_mf =  np.logspace(2,12,num=40) # default endpoint=True
wid_mf = abin_mf[1:]-abin_mf[:-1]
dlog10M = np.log10(abin_mf[1]/abin_mf[0]) # print(dlog10M)

for z in [4,6]:
    f_duty = 0.5
    mu_fit = .3
    sigma_fit = .15

    N_concatenate = int(1e0)
    # if z==6:
    #     N_concatenate = int(1e4)
    # else:
    #     N_concatenate = int(1e0)
    h0_mf = np.zeros(len(abin_mf)-1); h1_mf = np.zeros(len(abin_mf)-1); h2_mf = np.zeros(len(abin_mf)-1)

    for i_concatenate in range(N_concatenate):
        # T = T[T['z_col']>z]
        T['Edd_ratio'] = lognorm.rvs(sigma_fit*np.log(10), scale=mu_fit, size=len(T)) # scatter=0.1dex; center=scale
        for i in range(len(T)):
            # T['Edd_ratio'][i] = .3
            T['Mstar_z'][i] = T['Mstar0'][i] * np.exp( (t_from_z(z)-t_from_z(T['z_col'][i])) / t_Edd * f_duty* T['Edd_ratio'][i] )
        # print(np.argmax(T['Mstar_z'])," max Mstar:", np.max(T['Mstar_z']), "corresponding Edding_ratio",T['Edd_ratio'][np.argmax(T['Mstar_z'])], "t_grow Myr",(t_from_z(6)-t_from_z(T['z_col'][np.argmax(T['Mstar_z'])]))/Myr)

        T_H2 = T[T['Tg_max']<=T_tell]
        T_isofail = T[np.logical_and(T['Tg_max']>T_tell, T['iso_col']==0)]
        T_isoOK =  T[np.logical_and(T['Tg_max']>T_tell, T['iso_col']==1)]

        hist0_mf, bin_edges = np.histogram(T_H2['Mstar_z'],bins=abin_mf,density=False)
        hist1_mf, bin_edges = np.histogram(T_isofail['Mstar_z'],bins=abin_mf,density=False)
        hist2_mf, bin_edges = np.histogram(T_isoOK['Mstar_z'],bins=abin_mf,density=False)
        h0_mf += hist0_mf*n_base[iM]/(1e4*N_concatenate)/dlog10M*f_duty
        h1_mf += hist1_mf*n_base[iM]/(1e4*N_concatenate)/dlog10M*f_duty
        h2_mf += hist2_mf*n_base[iM]/(1e4*N_concatenate)/dlog10M*f_duty

    fig, ax = plt.subplots(1,2,figsize=(20,10),dpi=400)
    ax[0].plot(abin_mf, MF(abin_mf,z),label='Willott 2010 or extrapolate')
    x = (abin_mf[:-1]+abin_mf[1:])/2.
    ax[0].bar(x, h0_mf,width=wid_mf,color='C'+str(0),alpha=0.5,label=typenames[0])
    ax[0].bar(x, h1_mf,width=wid_mf,bottom=h0_mf,color='C'+str(1),alpha=0.5,label=typenames[1])
    ax[0].bar(x, h2_mf,width=wid_mf,bottom=(h0_mf+h1_mf),color='C'+str(2),alpha=0.5,label=typenames[2])
    ax[0].tick_params(labelsize=fstick)
    ax[0].set_xlabel(r'$\mathrm{M_{\bullet}}$',fontsize=fslabel)
    ax[0].set_ylabel(r'$\mathrm{\Phi}$'+' '+r'$\mathrm{[Mpc^{-3}dex^{-1}]}$',fontsize=fslabel)
    ax[0].set_xscale('log'); ax[0].set_yscale('log')
    ax[0].set_title('z='+str(int(z)),fontsize=fslabel)
    ax[0].set_xlim(1e7,10**10.5);  ax[0].set_ylim(1.e-9,1e-4)
    ax[0].grid(True)
    ax[0].legend(fontsize=fslegend,loc='best')
    ax[1].plot(abin_mf, MF(abin_mf,z),label='Willott 2010 or extrapolate')
    ax[1].bar(x, h0_mf,width=wid_mf,color='C'+str(0),alpha=0.5,label=typenames[0])
    ax[1].bar(x, h1_mf,width=wid_mf,bottom=h0_mf,color='C'+str(1),alpha=0.5,label=typenames[1])
    ax[1].bar(x, h2_mf,width=wid_mf,bottom=(h0_mf+h1_mf),color='C'+str(2),alpha=0.5,label=typenames[2])
    ax[1].tick_params(labelsize=fstick)
    ax[1].set_xlabel(r'$\mathrm{M_{\bullet}}$',fontsize=fslabel)
    ax[1].set_ylabel(r'$\mathrm{\Phi}$'+' '+r'$\mathrm{[Mpc^{-3}dex^{-1}]}$',fontsize=fslabel)
    ax[1].set_xscale('log'); ax[1].set_yscale('log')
    ax[1].set_title('z='+str(int(z)),fontsize=fslabel)
    ax[1].set_xlim(abin_mf[0],abin_mf[1]); ax[1].set_ylim()
    ax[1].grid(True)
    ax[1].legend(fontsize=fslegend,loc='best')
    plt.savefig(figpre+'MF_z'+str(int(z))+'eta'+str(int(10*eta))+'f'+str(f_duty)+'mu'+str(mu_fit)+'sigma'+str(sigma_fit)+'N'+str(int(np.log10(N_concatenate)))+'.png')
    ascii.write(Table([(abin_mf[:-1]+abin_mf[1:])/2.,h0_mf,h1_mf,h2_mf, ],names=['bin_center','hist_0','hist_1','hist_2']), datapre+'histBHmass_z'+str(int(z))+'eta'+str(int(10*eta))+'f'+str(f_duty)+'mu'+str(mu_fit)+'sigma'+str(sigma_fit)+'N'+str(int(np.log10(N_concatenate))),overwrite=True)


#coding: latin-1
import numpy as np

def shell_tube_eff(NTU,Cr,nshell=1):
#
# shell and tube (nshell shell pass)
# NTU is the total NTU
    NTUn = NTU/nshell
    G = np.sqrt(1+Cr**2)
    y = np.exp(-NTUn*G)
    ep1 = 2/(1+Cr+G*(1+y)/(1-y))
    if nshell > 1:
        if Cr == 1:
            ep = nshell*ep1/(1+ep1*(n-1))
        else:
            z = (1-ep1*Cr)/(1-ep1)
            ep = (z**nshell-1)/(z**nshell-Cr)
    else:
        ep = ep1
    return ep

def shell_tube_NTU(ep,Cr,nshell=1):
#
# shell and tube (nshell shell pass)
# NTU is the total NTU
    G = np.sqrt(1+Cr**2)
    if nshell > 1:
        if Cr ==1:
            ep1 = ep/(nshell - ep*(n-1))
        else:
            F = ((ep*Cr -1)/(ep-1))**(1/nshell)
            ep1 = (F-1)/(F-Cr)
    else:
        ep1 = ep
    E = (2/ep1 - (1+Cr))/G
    if E > 1:
        NTU1 = -np.log((E-1)/(E+1))/G
        NTU = nshell*NTU1
    else:
        print('impossible')
        NTU = -999
    return NTU
def F_coef_shell_tube(Tci,Tco,Thi,Tho,N):
    P = (Tco-Tci)/(Thi-Tci)
    R = (Thi-Tho)/(Tco-Tci)
    A = 2/P - 1 - R
    B = 2/P*np.sqrt((1-P)*(1-P*R))
    num = np.sqrt(R**2 + 1)/(R-1)*np.log((1-P)/(1-P*R))
    if N == 1:
        den = np.log((A+np.sqrt(R**2+1))/(A-np.sqrt(R**2+1)))
        F = num/den
    else:
        den = 2*np.log((A+B+np.sqrt(R**2+1))/(A+B-np.sqrt(R**2+1)))
        F = num/den
    return F

def counter_flow_NTU(ep,Cr):
    if Cr < 1:
        NTU = 1/(Cr-1)*np.log((ep-1)/(ep*Cr-1))
    else:
        NTU = ep/(1.0-ep)
    return NTU

def counter_flow_eff(NTU,Cr):

    if Cr < 1:
        ep = (1-np.exp(-NTU*(1-Cr)))/(1-Cr*np.exp(-NTU*(1-Cr)))
    else:
        ep = NTU/(1+NTU)
    return ep


import torch
from torch import nn

def conv_block(in_channel, channel, kernel_size=3, stride=1, padding=1, inplace=False):
    norm = nn.InstanceNorm2d
    return nn.Sequential(
        nn.Conv2d(in_channel, channel, kernel_size=kernel_size, stride=stride, padding=padding, bias=True),
        norm(channel, affine=True, momentum=0.4),
        nn.ELU(inplace=inplace)
    )

class ResNextBlock(nn.Module):
    """
    resnext不是太好，将原先的+改为了cat，残差不变
    我想命名为 ResNextX
    """

    def __init__(self, in_channel, out_channel, split_num: int = 4, **kwargs):
        super().__init__()

        mid_channel = 4

        self.split_num = split_num
        blocks = []

        kernel_style = [
            (1, 1),
            (1, 3),
            (3, 1),
            (3, 3)
        ]

        padding_style = [
            (k1 // 2, k2 // 2) for k1, k2 in kernel_style
        ]
        inplace = kwargs.get("inplace", True)
        for i in range(split_num):
            blocks.append(nn.Sequential(
                conv_block(in_channel, mid_channel, kernel_size=kernel_style[i], stride=1, padding=padding_style[i], inplace=inplace),
                conv_block(mid_channel, mid_channel, kernel_size=3, stride=1, padding=1, inplace=inplace),
                conv_block(mid_channel, out_channel, kernel_size=kernel_style[i], stride=1, padding=padding_style[i], inplace=inplace),
                # conv_block(out_channel, mid_channel, kernel_size=1, stride=1, padding=0, inplace=inplace),
                # conv_block(mid_channel, mid_channel, kernel_size=3, stride=1, padding=1, inplace=inplace),
                # conv_block(mid_channel, out_channel, kernel_size=1, stride=1, padding=0, inplace=inplace)
            ))
        self.scale = conv_block(out_channel * split_num, out_channel, kernel_size=1, stride=1, padding=0, inplace=inplace)
        self.blocks = nn.ModuleList(blocks)

        if in_channel != out_channel:
            self.skip = nn.Conv2d(in_channel, out_channel, kernel_size=1, stride=1, padding=0)
        else:
            self.skip = None

    def forward(self, x):
        if self.skip:
            res = self.skip(x)
        else:
            res = x

        outputs = []
        for i in range(self.split_num):
            outputs.append(torch.add(self.blocks[i](x), res))

        x = self.scale(torch.cat(outputs, dim=1))

        return torch.add(x, res)


import sys
import parser

''' Grammar:
program = statement

statement = seq | single

seq = single; seq | single; single

single = assign | if | for

assign = var = expr

var = x | y

const = 0 | 1

expr = var | const | expr + var | expr + const

if = if cmp then statement else statement endif

for = for var = expr; cmp; expr do statement endfor

cmp = expr == expr | expr > expr | expr < expr
'''

class ForLang(object):
    def parsing_error(self, tok1, tok2):
        print(self.input)
        print("Error: expecting %s but get %s at location %d" % (tok1, str(tok2), self.p.cur))
        sys.exit(1)

    def debug(self, msg):
        if self.is_debug:
            print(msg)

    def lookAHead(self):
        if self.nextToken is None:
            self.nextToken = self.p.next_token()
        return self.nextToken

    def fetch(self):
        token = self.lookAHead()
        self.nextToken = self.p.next_token()
        return token

    def parse(self, input, debug=False):
        self.is_debug = debug
        self.input = input
        self.p = parser.tokenizer(input)
        self.nextToken = None
        return self.parseProgram()

    def parseProgram(self):
        return self.parseStatement()

    def parseStatement(self):
        self.debug('parsing statement')
        s1 = self.parseSingle()
        t = self.lookAHead()
        if t == ';':
            self.fetch()
            s2 = self.parseStatement()
            return ['<SEQ>', s1, s2]
        else:
            return s1

    def parseSingle(self):
        self.debug('parsing single')
        t = self.lookAHead()
        if t == 'if':
            return self.parseIf()
        elif t == 'for':
            return self.parseFor()
        else:
            return self.parseAssign()

    def match(self, token):
        t = self.fetch()
        if t != token:
            self.parsing_error(token, t)

    def parseIf(self):
        self.debug('parsing if')
        self.match('if')
        cmp = self.parseCmp()
        self.match('then')
        then_branch = self.parseStatement()
        self.match('else')
        else_branch = self.parseStatement()
        self.match('endif')
        return ['<IF>', cmp, then_branch, else_branch]

    def parseFor(self):
        self.debug('parsing for')
        self.match('for')
        var = self.parseVar()
        self.match('=')
        init = self.parseExpr()
        self.match(';')
        cond = self.parseCmp()
        self.match(';')
        inc = self.parseExpr()
        self.match('do')
        stat = self.parseStatement()
        self.match('endfor')
        return ['<FOR>', var, init, cond, inc, stat]

    def parseAssign(self):
        self.debug('parsing assign')
        var = self.parseVar()
        self.match('=')
        expr = self.parseExpr()
        return ['<ASSIGN>', var, expr]

    def parseVar(self):
        self.debug('parsing var')
        v = self.fetch()
        if type(v) != type('a'):
            self.parsing_error('<var>', v)
        return v

    def parseConst(self):
        v = self.fetch()
        if type(v) != type(10):
            self.parsing_error('<num>', v)
        return v

    def parseExpr(self):
        self.debug('parsing expr')
        v1 = self.fetch()
        while self.lookAHead() == '+' or self.lookAHead() == '-':
            if self.lookAHead() == '+':
                self.match('+')
                v2 = self.fetch()
                v1 = ['<Op+>', v1, v2]
            else:
                self.match('-')
                v2 = self.fetch()
                v1 = ['<Op->', v1, v2]
        return ['<Expr>', v1]

    def parseCmp(self):
        self.debug('parsing cmp')
        e1 = self.parseExpr()
        op = self.lookAHead()
        if op != '==' and op != '>' and op != '<':
            self.parsing_error('==|>|<', op)
        op = self.fetch()
        e2 = self.parseExpr()
        return ['<CMP>', e1, op, e2]

    def printast(self, ast, indent):
        id = ast[0] if type(ast) == type([]) else ast
        print('\t'*indent + str(id))
        if type(ast) == type([]):
            for i in range(1, len(ast)):
                self.printast(ast[i], indent + 1)

def test1():
    program = '''for i=1; i<10; i+1 do
    if x>0 then y=y+1 else
        y=y
        endif
    endfor;
    a = a + 1
    '''
    forlang = ForLang()
    p = forlang.parse(program, debug=True)
    forlang.printast(p, 0)

if __name__ == '__main__':
    test1()
    pass

Code and data set of Tree to tree neural network progration/Tree2Tree-master/src/For2Lam/lang_for.py


import sys
import os
import itertools
import numpy as np
import enum

OUTPUT_FILE = 'vector_type_predef.hpp'
STATIC_BUFFER_TYPE = 'static_buffer'
DEVICE_HOST_MACRO = 'DEVICE_HOST'

def gen_p2_array(n):
    i = 1
    rtn = []
    while i <= n:
        rtn.append(i)
        i = i * 2
    return rtn

class vector_type(object):
    def __init__(self, n):
        self.n = n

    def __call__(self, fp):
        n = self.n
        fp.write(f'template <typename T> struct vector_type<T, {n}> {{\n')
        for d in gen_p2_array(n):
            if d == 1:
                fp.write(f'    using d1_t = T;\n')
            else:
                fp.write(f'    typedef T d{d}_t __attribute__((ext_vector_type({d})));\n')
        fp.write(f'    using type = d{n}_t;\n')
        fp.write(f'    union {{\n')
        fp.write(f'        type d{n}_;\n')
        for d in gen_p2_array(n):
            fp.write(f'        {STATIC_BUFFER_TYPE}<d{d}_t, {n // d}> d{d}x{n // d}_;\n')
        fp.write(f'    }} data_;\n')
        fp.write(f'    {DEVICE_HOST_MACRO} constexpr vector_type() : data_{{type{{0}}}} {{}}\n')
        fp.write(f'    {DEVICE_HOST_MACRO} constexpr vector_type(type v) : data_{{v}} {{}}\n')
        fp.write(f'    template<typename VEC> {DEVICE_HOST_MACRO} constexpr const auto& to_varray() const {{ return data_.d{n}_; }}\n')
        fp.write(f'    template<typename VEC> {DEVICE_HOST_MACRO} constexpr auto&       to_varray()       {{ return data_.d{n}_; }}\n')

        for d in gen_p2_array(n):
            fp.write(f'    template<> {DEVICE_HOST_MACRO} constexpr const auto& to_varray<d{d}_t>() const {{ return data_.d{d}x{n//d}_;}}\n')
            fp.write(f'    template<> {DEVICE_HOST_MACRO} constexpr auto&       to_varray<d{d}_t>()       {{ return data_.d{d}x{n//d}_;}}\n')
        fp.write(f'}};\n')

def gen(file_name):
    fp = None
    try:
        fp = open(file_name, "w")
    except IOError as e:
        print("can't open file:{}({})".format(file_name, e))
        sys.exit()
    fp.write(f'template <typename T, index_t N>\n')
    fp.write(f'struct vector_type;\n')
    fp.write(f'\n')
    fp.write(f'// clang-format off\n')
    for n in [1, 2, 4, 8, 16, 32, 64, 128, 256]:
        vector_type(n)(fp)
        fp.write(f'\n')
    fp.write(f'// clang-format on\n')

if __name__ == '__main__':
    output_file = OUTPUT_FILE
    if len(sys.argv) >= 2:
        output_file = sys.argv[1]
    gen(output_file)


# -*- coding: utf-8 -*-
import numpy as np

def moranI(W,X):

    '''
    W:空间权重矩阵
    X:观测值矩阵
    归一化空间权重矩阵后进行moran检验
    '''
    W = np.array(W)
    X = np.array(X)
    X = X.reshape(1,-1)
    print('===========w:{}',W)
    print('===========x:{}',X)
    #归一化
    print('W.sum:{}',W.sum(axis=1))
    W = W/W.sum(axis=1)
    print('===========W归一化：{}',W)
    #空间单元数
    n = W.shape[0]
    print('===========空间单元数：{}',n)
    #离差阵
    Z = X - X.mean()
    print('===========离差证：{}',Z)
    S0 = W.sum()
    S1 = 0
    for i in range(n):
        for j in range(n):
            S1 += 0.5*(W[i,j]+W[j,i])**2
    S2 = 0
    for i in range(n):
        S2 += (W[i,:].sum()+W[:,i].sum())**2
    #全局moran指数
    I = np.dot(Z,W)
    I = np.dot(I,Z.T)
    I = n/S0*I/np.dot(Z,Z.T)
    #在正太分布假设下的检验数
    EI_N = -1/(n-1)
    VARI_N = (n**2*S1-n*S2+3*S0**2)/(S0**2*(n**2-1))-EI_N**2
    ZI_N = (I-EI_N)/(VARI_N**0.5)
    #在随机分布假设下检验数
    EI_R = -1/(n-1)
    b2 = 0
    for i in range(n):
        b2 += n*Z[0,i]**4
    b2 = b2/((Z*Z).sum()**2)
    VARI_R = n*((n**2-3*n+3)*S1-n*S2+3*S0**2)-b2*((n**2-n)*S1-2*n*S2+6*S0**2)
    VARI_R = VARI_R/(S0**2*(n-1)*(n-2)*(n-3))-EI_R**2
    ZI_R = (I-EI_R)/(VARI_R**0.5)
    #计算局部moran指数
    Ii = list()
    for i in range(n):
        Ii_ = n*Z[0,i]
        Ii__ = 0
        for j in range(n):
            Ii__ += W[i,j]*Z[0,j]
        Ii_ = round(Ii_*Ii__/((Z*Z).sum()),3)
        Ii.append(Ii_)
    Ii = np.array(Ii)
    #局部检验数
    ZIi = list()
    EIi = Ii.mean()
    VARIi = Ii.var()
    for i in range(n):
        ZIi_ = (Ii[i]-EIi)/(VARIi**0.5)
        ZIi.append(round(ZIi_,3))
    ZIi = np.array(ZIi)

    result={}
    # 全局moran指数
    result["I"]=round(I[0,0],3)
    #正太分布假设下检验数
    result["ZI_N"]=round(ZI_N[0,0],3)
    #随机分布假设下检验数
    result["ZI_R"]=round(ZI_R[0,0],3)
    #局部moran指数
    result["Ii"]=Ii.tolist()
    #局部检验数
    result["ZIi"]=ZIi.tolist()

    return result

    # return {
    #         "I":{"value":I[0,0],"desc":"全局moran指数"},
    #         "ZI_N":{"value":ZI_N[0,0],"desc":"正太分布假设下检验数"},
    #         "ZI_R":{"value":ZI_R[0,0],"desc":"随机分布假设下检验数"},
    #         "Ii":{"value":Ii,"desc":"局部moran指数"},
    #         "ZIi":{"value":ZIi,"desc":"局部检验数"},
    #         "img":{"path":imgPath,"desc":"莫兰散点图路径"}
    #         }

if __name__ == "__main__":
    w = [
         [0,1,1,0,0],
         [1,0,1,1,0],
         [1,1,0,1,0],
         [0,1,1,0,1],
         [0,0,0,1,0]
        ]
    w = np.array(w)
    x = [
         [8,6,6,3,2]
         ]
    x = np.array(x)
    print(moranI(w,x))


import argparse
import datetime
import pycloudlib

CI_DEFAULT_TAG = "uaclient"

def get_parser():
    parser = argparse.ArgumentParser()
    parser.add_argument(
        "-t", "--tag", dest="tag", action="store",
        default=CI_DEFAULT_TAG,
        help=(
            "Tag to determine which instances will be deleted."
            "If the tag is present in the instance name, it will "
            "be marked for deletion. "
            "Default: {}".format(CI_DEFAULT_TAG))
    )
    parser.add_argument(
        "-b", "--before-date", dest="before_date", action="store",
        help=("Resources created before this date will be deleted."
              " Format: MM/DD/YY")
    )
    parser.add_argument(
        "--credentials-path", dest="credentials_path",
        help="""
            Path to json file representing the GCP credentials. That file
            must a be a json dict containing all the necessary credentials
            to manage GCP resources."""
        )
    parser.add_argument(
        "--project-id", dest="project_id",
        help="Name of the project id this script will operate on"
    )
    parser.add_argument(
        "--region", dest="region",
        help="Name of the region this script will operate on"
    )
    parser.add_argument(
        "--zone", dest="zone",
        help="Name of the zone this script will operate on"
    )

    return parser

def clean_gcp(credentials_path, project_id, tag, before_date, region, zone):
    gce = pycloudlib.GCE(
        tag='cleanup',
        credentials_path=credentials_path,
        project=project_id,
        region=region,
        zone=zone
    )

    all_instances = gce.compute.instances().list(
        project=gce.project,
        zone=gce.zone
    ).execute()

    for instance in all_instances.get('items', []):
        created_at = datetime.datetime.strptime(
            instance["creationTimestamp"].split("T")[0], "%Y-%M-%d"
        )

        # If the machine is running for more than 2 days, we should
        # delete it, regardless of the name tag
        if created_at < before_date - datetime.timedelta(days=2):
            print("Deleting instance {} ...".format(
                instance['name']))
            instance = gce.get_instance(
                instance_id=instance['name']
            )

            instance.delete()
        elif tag in instance['name'] and created_at < before_date:
            print("Deleting instance {} ...".format(
                instance['name']))
            instance = gce.get_instance(
                instance_id=instance['name']
            )

            instance.delete()

if __name__ == '__main__':
    parser = get_parser()
    args = parser.parse_args()

    if args.before_date:
        before_date = datetime.datetime.strptime(
            args.before_date, "%m/%d/%Y"
        )
    else:
        before_date = datetime.datetime.today() - datetime.timedelta(days=1)

    clean_gcp(
        credentials_path=args.credentials_path,
        project_id=args.project_id,
        tag=args.tag,
        before_date=before_date,
        region=args.region,
        zone=args.zone
    )


import wttest
from suite_subprocess import suite_subprocess
from wtdataset import SimpleDataSet, ComplexDataSet
from wiredtiger import stat
from wtscenario import make_scenarios

# test_compact.py
#    session level compact operation
class test_compact(wttest.WiredTigerTestCase, suite_subprocess):
    name = 'test_compact'

    # We don't want to set the page size too small as compaction doesn't work on tables with many
    # overflow items, furthermore eviction can get very slow with overflow items. We don't want the
    # page size to be too big either as there won't be enough pages to rewrite.
    config = 'leaf_page_max=8KB,key_format=S'
    nentries = 50000

    # The table is a complex object, give it roughly 5 pages per underlying
    # file.
    types = [
        ('file', dict(type='file:', dataset=SimpleDataSet, maxpages=5)),
        ('table', dict(type='table:', dataset=ComplexDataSet, maxpages=50))
        ]
    compact = [
        ('method', dict(utility=0,reopen=0)),
        ('method_reopen', dict(utility=0,reopen=1)),
        ('utility', dict(utility=1,reopen=0)),
    ]
    scenarios = make_scenarios(types, compact)

    # Configure the connection so that eviction doesn't happen (which could
    # skew our compaction results).
    conn_config = 'cache_size=1GB,eviction_checkpoint_target=80,' +\
        'eviction_dirty_target=80,eviction_dirty_trigger=95,statistics=(all)'

    # Return stats that track the progress of compaction.
    def getCompactProgressStats(self, uri):
        cstat = self.session.open_cursor(
            'statistics:' + uri, None, 'statistics=(all)')
        statDict = {}
        statDict["pages_reviewed"] = cstat[stat.dsrc.btree_compact_pages_reviewed][2]
        statDict["pages_skipped"] = cstat[stat.dsrc.btree_compact_pages_skipped][2]
        statDict["pages_rewritten"] = cstat[stat.dsrc.btree_compact_pages_rewritten][2]
        cstat.close()
        return statDict

    # Test compaction.
    @wttest.skip_for_hook("timestamp", "removing timestamped items will not free space")
    def test_compact(self):
        # Populate an object
        uri = self.type + self.name
        ds = self.dataset(self, uri, self.nentries - 1, config=self.config)
        ds.populate()

        # Reopen the connection to force the object to disk.
        self.reopen_conn()

        # Confirm the tree starts big
        stat_cursor = self.session.open_cursor('statistics:' + uri, None, None)
        self.assertGreater(stat_cursor[stat.dsrc.btree_row_leaf][2], self.maxpages)
        stat_cursor.close()

        # Remove most of the object.
        c1 = ds.open_cursor(uri, None)
        c1.set_key(ds.key(5))
        c2 = ds.open_cursor(uri, None)
        c2.set_key(ds.key(self.nentries - 5))
        ds.truncate(None, c1, c2, None)
        c1.close()
        c2.close()

        # Compact it, using either the session method or the utility. Generated files are ~2MB, set
        # the minimum threshold to a low value to make sure compaction can be executed.
        compact_cfg = "free_space_target=1MB"
        if self.utility == 1:
            self.session.checkpoint(None)
            self.close_conn()
            self.runWt(["compact", "-c", compact_cfg, uri])
        else:
            # Optionally reopen the connection so we do more on-disk tests.
            if self.reopen == 1:
                self.session.checkpoint(None)
                self.reopen_conn()

            self.session.compact(uri, compact_cfg)

        # Verify compact progress stats. We can't do this with utility method as reopening the
        # connection would reset the stats.
        if self.utility == 0 and self.reopen == 0 and not self.runningHook('tiered'):
            statDict = self.getCompactProgressStats(uri)
            self.assertGreater(statDict["pages_reviewed"],0)
            self.assertGreater(statDict["pages_rewritten"],0)
            self.assertEqual(statDict["pages_rewritten"] + statDict["pages_skipped"],
                                statDict["pages_reviewed"])

        # Confirm compaction worked: check the number of on-disk pages
        self.reopen_conn()
        stat_cursor = self.session.open_cursor('statistics:' + uri, None, None)
        self.assertLess(stat_cursor[stat.dsrc.btree_row_leaf][2], self.maxpages)
        stat_cursor.close()

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


from torchvision import transforms
from torch.utils.data import dataset, dataloader
from torchvision.datasets.folder import default_loader
from utils.RandomErasing import RandomErasing
from utils.RandomSampler import RandomSampler
from opt import opt
import glob
import pandas as pd
import numpy as np
import os.path as osp

class Data(object):
    def __init__(self):
        # paper is (384, 128)
        train_transform = transforms.Compose([
            transforms.Resize((256, 256), interpolation=3),
            transforms.RandomHorizontalFlip(),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225]),
            RandomErasing(probability=0.5, mean=[0.0, 0.0, 0.0])
        ])
        test_transform = transforms.Compose([
            transforms.Resize((256, 256), interpolation=3),
            transforms.ToTensor(),
            transforms.Normalize(mean=[0.485, 0.456, 0.406], std=[0.229, 0.224, 0.225])
        ])

        self.trainset = EvaluationAICityCar(train_transform, 'train', opt.data_path)
        self.testset = EvaluationAICityCar(test_transform, 'test', opt.data_path)
        self.queryset = EvaluationAICityCar(test_transform, 'query', opt.data_path)
        self.train_loader = dataloader.DataLoader(self.trainset,
                                                  sampler=RandomSampler(self.trainset, batch_id=opt.batchid,
                                                                        batch_image=opt.batchimage),
                                                  batch_size=opt.batchid * opt.batchimage, num_workers=8,
                                                  pin_memory=True)
        self.test_loader = dataloader.DataLoader(self.testset, batch_size=opt.batchtest, num_workers=1, pin_memory=True)
        self.query_loader = dataloader.DataLoader(self.queryset, batch_size=opt.batchtest, num_workers=1,
                                                  pin_memory=True)

def process(data_path, dtype, num):
    img = []
    car_id = []
    id_list = np.array(pd.read_csv(data_path + '/train_label.csv', header=None))
    if dtype == 'train':
        for i in range(10):
            if i != num:
                path = data_path + '/folder' + str(i) + '/'
                dir_path = glob.glob(osp.join(path, '*.jpg'))
                for j in range(len(dir_path)):
                    img.append(dir_path[j])
                    tmp = str(dir_path[j])
                    car_id.append(id_list[int(tmp[-10:-4])-1][0])
    elif dtype == 'test':
        path = data_path + '/folder' + str(num) + '/test.txt'
        data = np.array(pd.read_csv(path, header=None))
        for i in range(data.shape[0]):
            tmp = data_path + '/folder' + str(num) + '/' + data[i]
            img.append(tmp[0])
            tmp = str(data[i])
            car_id.append(id_list[int(tmp[-12:-6]) - 1][0])
    elif dtype == 'query':
        path = data_path + '/folder' + str(num) + '/query.txt'
        data = np.array(pd.read_csv(path, header=None))
        for i in range(data.shape[0]):
            tmp = data_path + '/folder' + str(num) + '/' + data[i]
            img.append(tmp[0])
            tmp = str(data[i])
            car_id.append(id_list[int(tmp[-12:-6]) - 1][0])

    return img, car_id

class EvaluationAICityCar(dataset.Dataset):
    def __init__(self, transform, dtype, data_path):
        super(EvaluationAICityCar, self).__init__()
        self.transform = transform
        self.loader = default_loader
        self.data_path = data_path
        self.imgs, self.id = process(self.data_path, dtype, num=6)

    def __getitem__(self, index):
        path = self.imgs[index]
        if self.id[index] <= 95:
            target = self.id[index] - 1
        else:
            target = self.id[index] - 146
        img = self.loader(path)
        if self.transform is not None:
            img = self.transform(img)
        return img, target

    def __len__(self):
        return len(self.imgs)


def time_main():
    from mult_optim_cython import main
    import timeit
    import numpy as np
    time_arr = timeit.repeat(main, repeat=5, number=1)
    print('Times:', time_arr)
    print('Median:', np.median(time_arr))
    return

if __name__ == "__main__":
    time_main()


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

def read_info(file):
    while True:
        data = file.readline();
        if not data:
            break
        yield data

class Contact:
    def __init__(self, first_name = '', last_name = '', number = 0):
        self.first_name = first_name
        self.last_name = last_name
        self.number = number

    def __str__(self) -> str:
        return "{} {}: {}".format (self.first_name, self.last_name, self.number)

    def __gt__(self, another_contact):
        if self.last_name != another_contact.last_name:
            return self.last_name.__gt__(another_contact.last_name)
        else:
            return self.first_name.__gt__(another_contact.first_name)

    def add_from_console(self):
        self.first_name = input('Enter first name: ')
        self.last_name = input('Enter last name: ')
        self.number = input('Enter phone number: ')

    def __eq__(self, o: object) -> bool:
        return self.number == o.number

    def update(self, property):
        try:
            setattr(self, property, input("Enter " + property + ": "))
        except:
            print('Invalid property')

class PhoneBook:
    def __init__(self):
        self.records = []
        try:
            f = open('./phone_book.txt')
            for line in read_info(f):
                args = line.split()
                self.records.append(Contact(args[0], args[1], args[2]))
            f.close()
        except Exception as e:
            print("Something wrong!\n" + str(e))

    def add_to_file(self):
        f = open('./phone_book.txt', 'wt', encoding='utf-8')
        for item in self.records:
            f.write('{} {} {}\n'.format(item.first_name, item.last_name, item.number))
        f.flush()
        f.close()

    def add(self):
        record = Contact()
        record.add_from_console()
        self.records.append(record)

    def remove_by_id(self, id):
        self.records.pop(int(id))

    def search_by_name(self, name):
        result = ''
        for item in self.records:
            if (item.first_name + " " + item.last_name).__contains__(name):
                result += '{}\n'.format(item)
        return result

    def update(self, id):
        property = input('Enter property name (first_name, last_name, number): ')
        self.records[int(id)].update(property)

    def __str__(self) -> str:
        result = ''
        for idx, val in enumerate(self.records):
            result += '{} - {}\n'.format(idx, val)
        return result

phone_book = PhoneBook()
while True:
    action = input("1 - Add contact\n2 - Remove by id\n3 - Show contacts\n"
                   "4 - Update contact\n5 - Search by name\n6 - Exit\n")
    try:
        if action == '1':
            phone_book.add()
        elif action == '2':
            phone_book.remove_by_id(input('Enter id: '))
        elif action == '3':
            print(phone_book)
        elif action == '4':
            phone_book.update(input('Enter id: '))
        elif action == '5':
            print(phone_book.search_by_name(input('Enter name: ')))
        elif action == '6':
            phone_book.add_to_file()
            break
    except Exception as e:
        print("Something wrong!\n" + str(e))


import sys

def search_value(my_dict, elem):
    for key, value in my_dict.items():
        if value.lower() == elem.lower():
            return value
    return None

def search_key(my_dict, elem):
    for key, value in my_dict.items():
        if key.lower() == elem.lower():
            return key
    return None

def search(my_dict, val):
    for key, value in my_dict.items():
        if value == val:
            return key
    return None

def my_search(elem):
    states = {
    "Oregon" : "OR",
    "Alabama" : "AL",
    "New Jersey": "NJ",
    "Colorado" : "CO"
    }
    capital_cities = {
    "OR": "Salem",
    "AL": "Montgomery",
    "NJ": "Trenton",
    "CO": "Denver"
    }
    my_dict = dict(zip(capital_cities.values(), states.keys()))
    key = search_key(my_dict, elem)
    if key:
        print(f'{key} is the capital of {my_dict[key]}')
    if key == None:
        value = search_value(my_dict, elem)
        if value != None:
            key = search(my_dict, value)
            print(f'{key} is the capital of {my_dict[key]}')
        else:
            print(f'{elem} is neither a capital city nor a state')

def state():
    if len(sys.argv) != 2:
        return
    state = [elem.strip() for elem in sys.argv[1:][0].split(',') if elem.strip() != '']
    for elem in state:
        my_search(elem)

if __name__ == '__main__':
    state()


"""
Team 46
Haoyue Xie 1003068 @Melbourne
Jiayu Li 713551 @Melbourne
Ruqi Li 1008342 @Melbourne
Yi Zhang 1032768 @Melbourne
Zimeng Jia 978322 @Hebei, China
"""

import json
from shapely.geometry import shape, Point

#current_region is a dictionary
def streaming_region(current_region, tweet):
    if current_region != {}:
        return current_region
    else:
        area_list = []
        with open("City_geojson.json") as f:
            data = json.load(f)
        for area in data["features"]:
            if area["geometry"] != None:
                polygon = shape(area["geometry"])
                area_list.append([polygon,area["properties"]])

        if tweet["coordinates"] != None:
            point = Point(tweet["coordinates"]["coordinates"][0],tweet["coordinates"]["coordinates"][1])
            for plg in area_list:
                if plg[0].contains(point):
                    return plg[1]
            print("no sa4 area defined")
        elif tweet["place"] != None:
            coor1 = tweet["place"]["bounding_box"]["coordinates"][0][0]
            coor2 = tweet["place"]["bounding_box"]["coordinates"][0][2]
            point =  Point((coor1[0]+coor2[0])/2,(coor1[1]+coor2[1])/2)
            for plg in area_list:
                if plg[0].contains(point):
                    return plg[1]
            print("no sa4 area defined")
        else:
            print("no location info!")
            return {}


"""
URL: https://www.lintcode.com/problem/invert-binary-tree/description
Definition of TreeNode:
class TreeNode:
    def __init__(self, val):
        self.val = val
        self.left, self.right = None, None
"""

# My own solution, simple recursion.
class Solution:
    """
    @param root: a TreeNode, the root of the binary tree
    @return: nothing
    """
    def invertBinaryTree(self, root):
        # write your code here
        if root is None:
            return
        self.invertBinaryTree(root.left)
        self.invertBinaryTree(root.right)
        root.left, root.right = root.right, root.left

# I referred to a solution provided by a student on Jiuzhang.com. It uses BFS, very simple. Next time I should
# think about using BFS first when facing problems related to trees. I was always thinking about DFS and cannot
# figure out a way to do it non-recursively.
from collections import deque
class Solution:
    """
    @param root: a TreeNode, the root of the binary tree
    @return: nothing
    """
    def invertBinaryTree(self, root):
        # write your code here
        if root is None:
            return
        queue = deque()
        queue.append(root)
        while len(queue) > 0:
            node = queue.popleft()
            node.left, node.right = node.right, node.left
            if node.left:
                queue.append(node.left)
            if node.right:
                queue.append(node.right)


from django.shortcuts import render
from django.http import HttpResponse
from hello.models import User
import random
# Create your views here.
count = 0
def World(request):
    return HttpResponse('this is app2')

def Add_user(request):
    global count
    count += 1
    user = User()
    user.user_age = count
    user.user_name = random.choice(['Wang', 'Chan', 'Liu', 'Lin'])
    user.user_gender = not random.getrandbits(1)
    user.save()

    return render(request, ('add_user.html'))

def Get_user(request):

    user1 = User.objects.values()
    context = {
        "sqllist":user1
    }
    print(user1)
    return render(request, ('user_list.html'), context=context)
def Update_user(request):
    pkv = User.objects.values_list()
    # randompk = pkv[random.randint(0,len(pkv) -1)][0]
    # user = User.objects.get(pk = randompk)
    # user.user_name = 'Change'
    # user.save()
    # response = 'date has been updated'
    # return HttpResponse(response)
    pkv = len(User.objects.values_list())
    print(pkv)
    if(pkv > 1):
        pkv = User.objects.values_list()
        randompk = pkv[random.randint(0,len(pkv) -1)][0]
        user = User.objects.get(pk = randompk)
        user.user_name = 'Change'
        user.save()
        response = 'date has been updated'
        return HttpResponse(response)
    elif(pkv == 1) :
        a = User.objects.values_list()[0][0]
        user = User.objects.get(pk = a)
        user.user_name = 'Change'
        user.save()
        response = 'date has been updated'
        return HttpResponse(response)
    else:
        return HttpResponse('no information')
def Del_All(request):
    pkv = len(User.objects.values_list())
    print(pkv)
    if(pkv > 1):
        pkv = User.objects.values_list()
        randompk = pkv[random.randint(0,len(pkv) -1)][0]
        user = User.objects.get(pk = randompk)
        user.delete()
        response = 'PK ' + str(randompk) + ' has been delete'
        return HttpResponse(response)
    elif(pkv == 1) :
        a = User.objects.values_list()[0][0]
        user = User.objects.get(pk = a)
        user.delete()
        response = 'the ' +str(a)+ ' date has been delete'
        return HttpResponse(response)
    else:
        return HttpResponse('no information')


import sys
sys.path += ['.']  # noqa

from unittest.mock import Mock
from mycroft.services.paths_service import resolve_refs, StringGetter
from mycroft.services import paths_service
PathsManager = paths_service.PathsService
paths_service.resource_filename = lambda *args: ''

class TestResolver:
    def test_1(self):
        config = {
            'this': 'is',
            'a test': None
        }
        orig = config.copy()
        resolve_refs(config)
        assert orig == config

    def test_2(self):
        config = {
            'a': '$b',
            'b': 'c'
        }
        resolve_refs(config)
        assert config == {'a': 'c', 'b': 'c'}

    def test_3(self):
        config = {
            'a': '1',
            'b': '2$a',
            'c': '$a/$b:$d'
        }
        resolve_refs(config)
        assert config == {'a': '1', 'b': '21', 'c': '1/21:$d'}

class TestStringGetter:
    def test_1(self):
        s = StringGetter('$a:$b')
        assert s(a='1', b='2') == '1:2'
        assert s(3, 4) == '3:4'

class TestPathsManager:
    def setup(self):
        self.rt = Mock()
        self.rt.config = {'lang': 'en-us'}
        PathsManager._attr_name = 'paths'

    def test_1(self):
        self.rt.config['paths'] = {'a': '1', 'b': '2$a'}
        assert PathsManager(self.rt).b == '21'

    def test_2(self):
        self.rt.config['paths'] = {'a': '1', 'b': '2$a', 'c': '$b$d'}
        assert str(PathsManager(self.rt).c) == '21$d'
        assert PathsManager(self.rt).c(3) == '213'


from streamlit_webrtc import webrtc_streamer
import av
import cv2

cascade = cv2.CascadeClassifier("haarcascade_frontalface_default.xml")

class VideoProcessor:
    def recv(self, frame):
        frm = frame.to_ndarray(format="bgr24")

        CONFIDENCE = 0.5
        SCORE_THRESHOLD = 0.5
        IOU_THRESHOLD = 0.5
        font = cv2.FONT_HERSHEY_COMPLEX
        face_cascade = cv2.CascadeClassifier('haarcascade_frontalface_default.xml')
        rand_lvl = [random.randrange(70, 100) for i in range(0, 50)]
        frame_cntr = 0
        while True:

            ret, frame = frm
            gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)
            faces = face_cascade.detectMultiScale(gray, 1.1, 4)
            i = 0
            for (x, y, z, h) in faces:
                frame_cntr += 1

                cv2.rectangle(frm, (x, y), (x + z, y + h), (255, 0, 0), 2)
                if frame_cntr < 100:
                    cv2.putText(frame, f'Вы junior-разработчик на:{random.randrange(0, 100)}%', (x - 6, y), font, 0.7, (255, 255, 255), 2, cv2.LINE_AA)
                else:
                    i += 1
                    cv2.putText(frame, f'Вы junior-разработчик на:{rand_lvl[i]}%', (x - 6, y), font, 0.7, (255, 255, 255), 2, cv2.LINE_AA)

            x, imag = cv2.imencode('.jpg', frame)

            yield (b'--frame\r\n'
                b'Content-Type: image/jpeg\r\n\r\n' + imag.tobytes() + b'\r\n\r\n')

            for x, y, w, h in faces:
                cv2.rectangle(frm, (x, y), (x + w, y + h), (0, 255, 0), 3)

            return av.VideoFrame.from_ndarray(frm, format='bgr24')

webrtc_streamer(key="key", video_processor_factory=VideoProcessor)


class Game:
    # def __init__(self):
    #     self.

    def run_game (self):
        self.display_title ()
        self.game_rules()
        self.display_winner()
        self.play_mode ()

    def display_title (self):
        print("\nWelcome to Rock, Paper, Scissors, Lizard, Spock \n")

    def game_rules (self):
        print ("""    The rules are simple:\n
    Scissors cuts Paper \n
    Paper covers Rock \n
    Rock crushes Lizard \n
    Lizard poisons Spock \n
    Spock smashes Scissors \n
    Scissors decapitates Lizard \n
    Lizard eats Paper \n
    Paper disproves Spock \n
    Spock vaporizes Rock \n
    and of course, \n
    Rock crushes Scissors""")

    def play_mode (self):
        print ("Play against a person or AI? 1 for Person or 2 for AI")
        self.input =()
        if self.play_mode == "1":
            self.use_ai = False
        if self.play_mode == "2":
            self.use_ai = True

    def display_winner (self):
        print (f"{self.winner} wins the set!")

        # loop back to start if selection is anything other than 0-4

# write input for player(s),
# write loop to return to top if 0-4 selection not made. make sure that this is for human player ONLY
# write what each number means when selected. i.e You choose 1 "paper",
# parent class, name, score, gesture list, and currently selected gesture.
# ai is diff by HOW they pick gestures
# human choose gesture and access gesture in game.py then we can have access to player moves and to compare the two.
# Three wins determine a winner of that match
# Declare winner

# GITBASH then work on above


#https://leetcode.com/problems/masking-personal-information/

class Solution:

    def solveEmail(self,s):
        print(s)
        name,domain=s.split("@")[0].lower(),s.split("@")[1].lower()
        print(name,domain)
        name=name[0:1]+"*****"+name[-1]
        return name+"@"+domain

    def solvePhone(self,s):
        tel=""
        for i in range(0,len(s),1):
            cr=s[i:i+1]
            if cr=="+" or cr=="-" or cr=="(" or cr==")" or cr==" ":
                tel=tel+""
            else:
                tel=tel+cr
        if len(tel)==10:
            return "***-***-"+tel[6:]

        elif len(tel)==11:
            return "+*-***-***-"+tel[7:]

        elif len(tel)==12:
            return "+**-***-***-"+tel[8:]

        elif len(tel)==13:
            return "+***-***-***-"+tel[9:]

    def maskPII(self, s: str) -> str:
        if "@" in s:
            ans=self.solveEmail(s)
            return ans
        else:
            ans=self.solvePhone(s)
            return ans


# Description: 2. project 'Bulls and cows' in Engeto Online Python Academy
# Author: Jiri Gloza

# Define basic variables
nums = [1, 2, 3, 4, 5, 6, 7, 8, 9, 0]
Welcome_message = '''
Hi there !
I've generated a random 4 digit number for you.
Let's play a bulls and cows game.
Enter a number'''
import random

# Define main function and generating random number.
# While cycle checks for user inputs and compare with random number using function user input
# Function Bulls_and_cows checks the position of numbers and return number of bulls and cows for each guess
def main():
    print(Welcome_message)
    rand_number = list(map(int, random.sample(nums, 4)))
    guess_counter = 0
    user_word_score = ""
    while True:
        user_guess = user_input(rand_number)
        bulls, cows = bulls_and_cows(user_guess, rand_number)
        print(f" {bulls} Bulls, {cows} Cows")
        guess_counter = guess_counter + 1
        if bulls == 4:
            if guess_counter < 2:
                user_word_score = "Amazing"
            elif guess_counter < 10:
                user_word_score = "Average"
            else:
                user_word_score = "Not so good"
            print(f"Correct, you've guessed the right number in {guess_counter} guesses! \nThats {user_word_score}")
            break

# Function which takes user input and check the formatting, if it is ok, then it return the user input back to main()
def user_input(rand_number):
    guess_list = []
    while True:
        guess_num = input(" -> ")
        try:
            if len(str(guess_num)) == 4:
                for i in str(guess_num):
                    guess_list.append(int(i))
                return guess_list
            else:
                print("Please enter 4 digits only")
        except ValueError:
            print("Bad formatting -> only digits are allowed")

# function which takes, random number and user input and return the number of 'bulls' and 'cows' for the round
def bulls_and_cows(guess_num, rand_num):
    bulls = 0
    cows = 0
    for i, x in enumerate((rand_num)):
        for j, y in enumerate((guess_num)):
            if i == j and x == y:
                bulls = bulls + 1
            elif y == x and not j == i:
                cows = cows + 1
    return bulls, cows

main()


from typing import Iterable
import torch
import numpy as np
from scipy.spatial.distance import cdist
from tqdm import tqdm
import ot

def cost_matrix(
  data: np.ndarray, cost: str = 'correlation',
  normalize_features: bool = True) -> np.ndarray:
  """Compute an empirical ground cost matrix, i.e. a pairwise distance matrix
  between the rows of the dataset (l1-normalized by default). Accepted
  distances are the ones compatible with Scipy's `cdist`.

  Args:
      data (np.ndarray):
        The input data, samples as columns and features as rows.
      cost (str):
        The metric use. Defaults to `correlation`.
      normalize_features (bool, optional):
        Whether to divide the rows by their sum before
        computing distances. Defaults to True.

  Returns:
      np.ndarray: The pairwise cost matrix.
  """
  if normalize_features:
    sums = data.sum(1).reshape(-1, 1)
    C = cdist(data/sums, data/sums, metric=cost)
  else:
    C = cdist(data, data, metric=cost)
  return C/C.max()

def OT_distance_matrix(
  data: np.ndarray,
  cost: np.ndarray,
  eps: float = .1,
  dtype: torch.dtype = torch.double,
  device: str = 'cuda',
  divide_max: bool = False,
  numItermax: int = 500,
  stopThr: float = 1e-5,
  batch_size: int = 200) -> np.ndarray:
  """Compute the pairwise Optimal Transport distance matrix. We compute
  Sinkhorn Divergences using POT's implementation of the Sinkhorn algorithm.
  Computations are done using PyTorch on a specified device. But the result is
  a numpy array. This allows not saturating the GPU for large matrices.

  Args:
      data (np.ndarray):
        The input data, as a numpy array.
      cost (np.ndarray):
        The ground cost between features.
      eps (float, optional):
        The entropic regularization parameter. Small regularization requires
        more iterations and double precision. Defaults to .1.
      dtype (torch.dtype, optional):
        The torch dtype used for computations. Double is more precise but
        takes up more space. Defaults to torch.double.
      device (str, optional):
        The torch device to compute on, typically 'cpu' or 'cuda'.
        Defaults to 'cuda'.
      divide_max (bool, optional):
        Whether to divide the resulting matrix by its maximum value.
        This can be useful to compare matrices. Defaults to False.
      numItermax (int, optional):
        Used by POT, maximum number of Sinkhorn iterations. Defaults to 500.
      stopThr (float, optional):
        Used by POT, tolerance for early stopping in the Sinkhorn iterations.
        Defaults to 1e-5.
      batch_size (int, optional):
        The batch size, i.e. how many distances can be computed at the same
        time. Should be as large as possible on your hardware. Defaults to 200.

  Returns:
      np.ndarray: The pairwise OT distance matrix.
  """

  # Move the cost to PyTorch.
  C = torch.from_numpy(cost)
  C = C.to(device=device, dtype=dtype)

  # Compute the kernel
  K = torch.exp(-C/eps)

  data_tensor = torch.from_numpy(data)
  data_tensor = data_tensor.to(device=device, dtype=dtype)

  D = torch.zeros(data_tensor.shape[1], data_tensor.shape[1], device='cpu', dtype=dtype)

  pbar = tqdm(total=data_tensor.shape[1]*(data_tensor.shape[1] - 1)//2, leave=False)

  errors = []

  # Iterate over the lines.
  for i in range(data_tensor.shape[1]):
    for ii in np.split(range(i+1), np.arange(batch_size, i+1, batch_size)):

      # Compute the Sinkhorn dual variables
      _, wass_log = ot.sinkhorn(
          data_tensor[:,i].contiguous(), # This is the source histogram.
          data_tensor[:,ii].contiguous(), # These are the target histograms.
          C, # This is the ground cost.
          eps, # This is the regularization parameter.
          log=True, # Return the dual variables
          stopThr=stopThr,
          numItermax=numItermax
      )

      # Compute the exponential dual potentials.
      f, g = eps*wass_log['u'].log(), eps*wass_log['v'].log()

      if len(wass_log['err']) > 0:
        errors.append(wass_log['err'][-1])

      # Compute the Sinkhorn costs.
      # These will be used to compute the Sinkhorn divergences
      wass = (
          f*data_tensor[:,[i]*len(ii)] +
          g*data_tensor[:,ii] -
          eps*wass_log['u']*(K@wass_log['v'])
      ).sum(0)

      # Add them in the distance matrix (including symmetric values).
      D[i,ii] = D[ii,i] = wass.cpu()

      pbar.update(len(ii))

  pbar.close()

  # Get the diagonal terms OT_eps(a, a).
  d = torch.diagonal(D)

  # The Sinkhorn divergence is OT(a, b) - (OT(a, a) + OT(b, b))/2.
  D = D - .5*(d.view(-1, 1) + d.view(1, -1))

  # Make sure there are no negative values.
  assert((D < 0).sum() == 0)

  # Make sure the diagonal is zero.
  D.fill_diagonal_(0)

  if divide_max:
    D /= torch.max(D)

  return D.numpy(), errors

def C_index(D: np.ndarray, clusters: np.ndarray) -> float:
  """Compute the C index, a measure of how well the pairwise distances reflect
  ground truth clusters. Implemented here for reference, but the silhouette
  score (aka Average Silhouette Width) is a more standard metric for this.

  Args:
      D (np.ndarray): The pairwise distances.
      clusters (np.ndarray): The ground truth clusters.

  Returns:
      float: The C index.
  """
  Sw = Nw = 0
  for c in np.unique(clusters):
    idx = np.where(clusters == c)[0]
    Sw += D[idx][:,idx].sum()/2
    Nw += int(len(idx)*(len(idx) - 1)/2)

  els = []
  for i in range(len(D)):
    for j in range(i):
      els.append(D[i, j])
  Smin = np.sort(np.array(els))[:Nw].sum()
  Smax = np.sort(np.array(els))[::-1][:Nw].sum()

  return (Sw - Smin)/(Smax - Smin)