import torch
from torch import cat, einsum, argmax, unsqueeze, FloatTensor
import torch.nn as nn
from torch.nn import init
from scipy.ndimage import zoom
from torch.nn.functional import softmax
from numpy import array, float32, expand_dims, average, sqrt, argwhere, zeros, shape, pad
from skimage import measure, morphology, io
import skimage
from skimage.color import rgba2rgb, rgb2gray
from os import makedirs
import matplotlib.pyplot as plt

class unetConv2(nn.Module):
    def __init__(self, in_size, out_size, is_batchnorm, n=2, ks=3, stride=1, padding=1):
        super(unetConv2, self).__init__()
        self.n = n
        self.ks = ks
        self.stride = stride
        self.padding = padding
        s = stride
        p = padding
        if is_batchnorm:
            for i in range(1, n + 1):
                conv = nn.Sequential(nn.Conv2d(in_size, out_size, ks, s, p),
                                     nn.BatchNorm2d(out_size),
                                     nn.ReLU(inplace=True), )
                setattr(self, 'conv%d' % i, conv)
                in_size = out_size

        else:
            for i in range(1, n + 1):
                conv = nn.Sequential(nn.Conv2d(in_size, out_size, ks, s, p),
                                     nn.ReLU(inplace=True), )
                setattr(self, 'conv%d' % i, conv)
                in_size = out_size

        for m in self.children():
            init_weights(m, init_type='kaiming')

    def forward(self, inputs):
        x = inputs
        for i in range(1, self.n + 1):
            conv = getattr(self, 'conv%d' % i)
            x = conv(x)
        return x

class unetUp(nn.Module):
    def __init__(self, in_size, out_size, is_deconv, n_concat=2):
        super(unetUp, self).__init__()
        self.conv = unetConv2(out_size*2, out_size, False)
        if is_deconv:
            self.up = nn.ConvTranspose2d(in_size, out_size, kernel_size=4, stride=2, padding=1)
        else:
            self.up = nn.UpsamplingBilinear2d(scale_factor=2)
        for m in self.children():
            if m.__class__.__name__.find('unetConv2') != -1: continue
            init_weights(m, init_type='kaiming')

    def forward(self, inputs0, *input):
        outputs0 = self.up(inputs0)
        for i in range(len(input)):
            outputs0 = cat([outputs0, input[i]], 1)
        return self.conv(outputs0)

def weights_init_normal(m):
    classname = m.__class__.__name__
    if classname.find('Conv') != -1:
        init.normal_(m.weight.data, 0.0, 0.02)
    elif classname.find('Linear') != -1:
        init.normal_(m.weight.data, 0.0, 0.02)
    elif classname.find('BatchNorm') != -1:
        init.normal_(m.weight.data, 1.0, 0.02)
        init.constant_(m.bias.data, 0.0)

def weights_init_xavier(m):
    classname = m.__class__.__name__
    if classname.find('Conv') != -1:
        init.xavier_normal_(m.weight.data, gain=1)
    elif classname.find('Linear') != -1:
        init.xavier_normal_(m.weight.data, gain=1)
    elif classname.find('BatchNorm') != -1:
        init.normal_(m.weight.data, 1.0, 0.02)
        init.constant_(m.bias.data, 0.0)

def weights_init_kaiming(m):
    classname = m.__class__.__name__
    if classname.find('Conv') != -1:
        init.kaiming_normal_(m.weight.data, a=0, mode='fan_in')
    elif classname.find('Linear') != -1:
        init.kaiming_normal_(m.weight.data, a=0, mode='fan_in')
    elif classname.find('BatchNorm') != -1:
        init.normal_(m.weight.data, 1.0, 0.02)
        init.constant_(m.bias.data, 0.0)

def weights_init_orthogonal(m):
    classname = m.__class__.__name__
    if classname.find('Conv') != -1:
        init.orthogonal_(m.weight.data, gain=1)
    elif classname.find('Linear') != -1:
        init.orthogonal_(m.weight.data, gain=1)
    elif classname.find('BatchNorm') != -1:
        init.normal_(m.weight.data, 1.0, 0.02)
        init.constant_(m.bias.data, 0.0)

def init_weights(net, init_type='normal'):
    if init_type == 'normal':
        net.apply(weights_init_normal)
    elif init_type == 'xavier':
        net.apply(weights_init_xavier)
    elif init_type == 'kaiming':
        net.apply(weights_init_kaiming)
    elif init_type == 'orthogonal':
        net.apply(weights_init_orthogonal)
    else:
        raise NotImplementedError('initialization method [%s] is not implemented' % init_type)

class UNet(nn.Module):
    def __init__(self, in_channels=1, n_classes=3, feature_scale=4, is_deconv=True, is_batchnorm=True):
        super(UNet, self).__init__()
        self.is_deconv = is_deconv
        self.in_channels = in_channels
        self.is_batchnorm = is_batchnorm
        self.feature_scale = feature_scale
        filters = [64, 128, 256, 512, 1024]

        # downsampling
        self.conv1 = unetConv2(self.in_channels, filters[0], self.is_batchnorm)
        self.maxpool1 = nn.MaxPool2d(kernel_size=2)
        self.conv2 = unetConv2(filters[0], filters[1], self.is_batchnorm)
        self.maxpool2 = nn.MaxPool2d(kernel_size=2)
        self.conv3 = unetConv2(filters[1], filters[2], self.is_batchnorm)
        self.maxpool3 = nn.MaxPool2d(kernel_size=2)
        self.conv4 = unetConv2(filters[2], filters[3], self.is_batchnorm)
        self.maxpool4 = nn.MaxPool2d(kernel_size=2)
        self.center = unetConv2(filters[3], filters[4], self.is_batchnorm)

        # upsampling
        self.up_concat4 = unetUp(filters[4], filters[3], self.is_deconv)
        self.up_concat3 = unetUp(filters[3], filters[2], self.is_deconv)
        self.up_concat2 = unetUp(filters[2], filters[1], self.is_deconv)
        self.up_concat1 = unetUp(filters[1], filters[0], self.is_deconv)
        self.outconv1 = nn.Conv2d(filters[0], n_classes, 1, padding=0)

        # initialise weights
        for m in self.modules():
            if isinstance(m, nn.Conv2d):
                init_weights(m, init_type='kaiming')
            elif isinstance(m, nn.BatchNorm2d):
                init_weights(m, init_type='kaiming')

    def dotProduct(self,seg,cls):
        B, N, H, W = seg.size()
        seg = seg.view(B, N, H * W)
        final = einsum("ijk,ij->ijk", [seg, cls])
        final = final.view(B, N, H, W)
        return final

    def forward(self, inputs):
        conv1 = self.conv1(inputs)  # 16*512*1024
        maxpool1 = self.maxpool1(conv1)  # 16*256*512

        conv2 = self.conv2(maxpool1)  # 32*256*512
        maxpool2 = self.maxpool2(conv2)  # 32*128*256

        conv3 = self.conv3(maxpool2)  # 64*128*256
        maxpool3 = self.maxpool3(conv3)  # 64*64*128

        conv4 = self.conv4(maxpool3)  # 128*64*128
        maxpool4 = self.maxpool4(conv4)  # 128*32*64

        center = self.center(maxpool4)  # 256*32*64

        up4 = self.up_concat4(center, conv4)  # 128*64*128
        up3 = self.up_concat3(up4, conv3)  # 64*128*256
        up2 = self.up_concat2(up3, conv2)  # 32*256*512
        up1 = self.up_concat1(up2, conv1)  # 16*512*1024
        d1 = self.outconv1(up1)  # 256
        return d1

class pub(nn.Module):

    def __init__(self, in_channels, out_channels, batch_norm=True):
        super(pub, self).__init__()
        inter_channels = int(in_channels/2 if in_channels > out_channels else out_channels/2)
        layers = [
                    nn.Conv3d(in_channels, inter_channels, 3, stride=1, padding=1),
                    nn.ReLU(True),
                    nn.Conv3d(inter_channels, out_channels, 3, stride=1, padding=1),
                    nn.ReLU(True)
                 ]
        if batch_norm:
            layers.insert(1, nn.BatchNorm3d(inter_channels))
            layers.insert(len(layers)-1, nn.BatchNorm3d(out_channels))
        self.pub = nn.Sequential(*layers)

    def forward(self, x):
        return self.pub(x)

class unet3dDown(nn.Module):

    def __init__(self, in_channels, out_channels, batch_norm=True):
        super(unet3dDown, self).__init__()
        self.pub = pub(in_channels, out_channels, batch_norm)
        self.pool = nn.MaxPool3d(2, stride=2)

    def forward(self, x):
        x = self.pool(x)
        x = self.pub(x)
        return x

class unet3dUp(nn.Module):
    def __init__(self, in_channels, out_channels, batch_norm=True, sample=True):
        super(unet3dUp, self).__init__()
        self.pub = pub(int(in_channels/2+in_channels), out_channels, batch_norm)
        if sample:
            self.sample = nn.Upsample(scale_factor=2, mode='nearest')
        else:
            self.sample = nn.ConvTranspose3d(in_channels, in_channels, 2, stride=2)

    def forward(self, x, x1):
        x = self.sample(x)
        x = torch.cat((x, x1), dim=1)
        x = self.pub(x)
        return x

class unet3d(nn.Module):
    def __init__(self, init_channels=1, class_nums=3, batch_norm=True, sample=True):
        super(unet3d, self).__init__()
        self.down1 = pub(init_channels, 64, batch_norm)
        self.down2 = unet3dDown(64, 128, batch_norm)
        self.down3 = unet3dDown(128, 256, batch_norm)
        self.down4 = unet3dDown(256, 512, batch_norm)
        self.up3 = unet3dUp(512, 256, batch_norm, sample)
        self.up2 = unet3dUp(256, 128, batch_norm, sample)
        self.up1 = unet3dUp(128, 64, batch_norm, sample)
        self.con_last = nn.Conv3d(64, class_nums, 1)
        self.sigmoid = nn.Sigmoid()

    def forward(self, x):
        x1 = self.down1(x)
        x2 = self.down2(x1)
        x3 = self.down3(x2)
        x4 = self.down4(x3)
        x = self.up3(x4, x3)
        x = self.up2(x, x2)
        x = self.up1(x, x1)
        x = self.con_last(x)
        return x

    def _initialize_weights(self):
        for m in self.modules():
            if isinstance(m, nn.Conv3d):
                nn.init.kaiming_uniform(m.weight.data)
                if m.bias is not None:
                    m.bias.data.zero_()
            elif isinstance(m, nn.BatchNorm3d):
                m.weight.data.fill_(1)
                m.bias.data.zero_()

def common_mitotic_cell_regions_3d(img):
    img_shape = shape(img)
    images_cells = zeros(img_shape)
    images_mitotic_cells = zeros(img_shape)
    locations = argwhere(img == 2)
    locations_mitotic = argwhere(img == 1)
    for temp in locations:
        images_cells[temp[0], temp[1], temp[2]] = 1
    for temp in locations_mitotic:
        images_mitotic_cells[temp[0], temp[1], temp[2]] = 1
    return images_cells, images_mitotic_cells

def measure_region(mask, connectivity=1):
    label_img, num = measure.label(mask, return_num=True, connectivity=connectivity)
    return label_img, num

def distance_between_points(point1, point2):
    if len(point2) != len(point1):
        print('Error, the length of two points is different')
    else:
        temp = 0
        for i in range(len(point1)):
            d_j = point1[i] - point2[i]
            temp += float(d_j ** 2)
        return sqrt(temp)

def remove_overlapped_cells(all_cells, threshold=4):
    tracked_index = []
    new_all_cells = []
    for i, cell in enumerate(all_cells):
        if i not in tracked_index:
            temp_i = []
            temp_i.append(cell)
            for j, cell_1 in enumerate(all_cells):
                if j not in tracked_index:
                    if i != j:
                        dist = distance_between_points(cell, cell_1)
                        if dist <= threshold:
                            temp_i.append(cell_1)
                            tracked_index.append(j)
            temp_i = average(array(temp_i), 0)
            new_all_cells.append([temp_i[0], temp_i[1], temp_i[2]])
    return new_all_cells

# def remove_overlapped_cells_x(all_cells, threshold=3, threshold2=5):
#     tracked_index = []
#     new_all_cells = []
#     for i, cell in enumerate(all_cells):
#         if i not in tracked_index:
#             temp_i = []
#             temp_i.append(cell)
#             for j, cell_1 in enumerate(all_cells):
#                 if j not in tracked_index:
#                     if i != j:
#                         dist = abs(cell[1] - cell_1[1])
#                         if dist <= threshold:
#                             if abs(cell[2] - cell_1[2]) < threshold2:
#                                 temp_i.append(cell_1)
#                                 tracked_index.append(j)
#             temp_i = average(array(temp_i), 0)
#             new_all_cells.append([temp_i[0], temp_i[1], temp_i[2]])
#     return new_all_cells

def detect_middle_slice(model, path, idx, slice, device):
    makedirs(f'{path}/images', exist_ok=True)
    slice = slice[0:848, 0:480]
    plt.imsave(r'{0}/images/{1}_middle.png'.format(path, idx), slice)
    data = io.imread(r'{0}/images/{1}_middle.png'.format(path, idx))
    data = rgba2rgb(data)
    data = rgb2gray(data)
    data = expand_dims(data, -1)
    data = data.transpose((2, 0, 1))
    data = expand_dims(data, 0)
    slice_torch = torch.FloatTensor(data)
    pred = model(slice_torch.to(device))
    pred_softmax = softmax(pred, dim=1)
    pred_mask = argmax(pred_softmax, dim=1)
    pred_mask_numpy = pred_mask[0].cpu().data.numpy()
    plt.imsave(r'{0}/images/{1}_middle_mask.png'.format(path, idx), pred_mask_numpy)
    pred_mask_final = morphology.remove_small_objects(array(pred_mask_numpy, dtype=bool), 0.5)
    return pred_mask_final

def pad_image(volume, height=1024, width=512):
    if shape(volume)[1] != height or shape(volume)[2] != width:
        if shape(volume)[1] != height:
            if shape(volume)[2] != width:
                padding_h = int((height-shape(volume)[1])/2)
                padding_x = int((width -shape(volume)[2]) / 2)
                volume = pad(volume, ((0, 0),
                                      (padding_h, height-shape(volume)[1]-padding_h),
                                      (padding_x, width-shape(volume)[2]-padding_x)),
                             'constant')
            else:
                padding_h = int((height - shape(volume)[1]) / 2)
                padding_x = 0
                volume = pad(volume, ((0, 0),
                                      (padding_h, height - shape(volume)[1] - padding_h),
                                      (0, 0)),
                             'constant')
        else:
            padding_x = int((width - shape(volume)[2]) / 2)
            padding_h = 0
            volume = pad(volume, ((0, 0),
                                  (0, 0),
                                  (padding_x, width - shape(volume)[2] - padding_x)),
                         'constant')
    else:
        padding_h = 0
        padding_x = 0

    return volume, padding_h, padding_x

def pred_img(data, model, device):
    data = expand_dims(data, -1)
    data = data.transpose((2, 0, 1))
    data = expand_dims(data, 0)
    slice_torch = torch.FloatTensor(data)
    pred = model(slice_torch.to(device))
    pred_softmax = softmax(pred, dim=1)
    pred_mask = argmax(pred_softmax, dim=1)
    return pred_mask[0].cpu().data.numpy()

def test_model(model, path, idx, imgs, device, whether_transpose):
    h_ratio = shape(imgs)[-2] // 1024
    w_ratio = shape(imgs)[-1] // 512
    temp_masks = []
    common_centroids = []
    mitotic_centroids = []

    if h_ratio > 1 and w_ratio > 1:
        volume = imgs[idx][:, 0:h_ratio * 1024, 0:w_ratio * 512]
        padding_h = padding_x = 0
        for k in range(len(volume)):
            for i in range(h_ratio):
                for j in range(w_ratio):
                    temp = volume[k][i * 1024:(i + 1) * 1024, j * 512:(j + 1) * 512]
                    temp = temp / 255
                    temp_mask = pred_img(temp, model, device)
                    temp_masks.append(temp_mask)
        pred_masks = zeros((len(volume), h_ratio * 1024, w_ratio * 512))
        for k in range(len(volume)):
            for i in range(h_ratio):
                for j in range(w_ratio):
                    pred_masks[k, i * 1024:(i + 1) * 1024, j * 512:(j + 1) * 512] = temp_masks[k * h_ratio * w_ratio + i * w_ratio + j]
    elif h_ratio > 1 and w_ratio <=1:
        volume = imgs[idx][:, 0:h_ratio * 1024, 0:512]
        volume, padding_h, padding_x = pad_image(volume, h_ratio*1024, 512)
        for k in range(len(volume)):
            for i in range(h_ratio):
                temp = volume[k][i * 1024:(i + 1) * 1024, 0:512]
                temp = temp / 255
                temp_mask = pred_img(temp, model, device)
                temp_masks.append(temp_mask)
        pred_masks = zeros((len(volume), h_ratio * 1024, 512))
        for k in range(len(volume)):
            for i in range(h_ratio):
                pred_masks[k, i * 1024:(i + 1) * 1024, 512] = temp_masks[k * h_ratio+i]
    elif h_ratio<=1 and w_ratio >1:
        volume = imgs[idx][:, 0:1024, 0:w_ratio * 512]
        volume, padding_h, padding_x = pad_image(volume, 1024, w_ratio * 512)
        for k in range(len(volume)):
            for j in range(w_ratio):
                temp = volume[k][0:1024, j * 512:(j + 1) * 512]
                temp = temp / 255
                temp_mask = pred_img(temp, model, device)
                temp_masks.append(temp_mask)
        pred_masks = zeros((len(volume), 1024, w_ratio * 512))
        for k in range(len(volume)):
            for j in range(w_ratio):
                pred_masks[k, 1024,  j * 512:(j + 1) * 512] = temp_masks[k * w_ratio + j]
    else:
        volume = imgs[idx][:, 0:1024, 0:512]
        volume, padding_h, padding_x = pad_image(volume)
        for k in range(len(volume)):
            temp = volume[k]
            temp = temp/255
            temp_mask = pred_img(temp, model, device)
            temp_masks.append(temp_mask)
        pred_masks = zeros((len(volume), 1024, 512))
        for k in range(len(volume)):
            pred_masks[k] = temp_masks[k]

    p_c, p_m = common_mitotic_cell_regions_3d(pred_masks)
    p_c = morphology.remove_small_objects(array(p_c, dtype=bool), 1)  # 3.5
    p_m = morphology.remove_small_objects(array(p_m, dtype=bool), 3)  # 50
    region_c, _ = measure_region(p_c)
    region_m, _ = measure_region(p_m)
    common_regions = measure.regionprops(region_c)
    mitotic_regions = measure.regionprops(region_m)

    for props in common_regions:
        z0, y0, x0 = props.centroid
        if whether_transpose:
            common_centroids.append([z0, x0 - padding_x, y0 - padding_h])
        else:
            common_centroids.append([z0, y0 - padding_h, x0 - padding_x])

    for props in mitotic_regions:
        z0, y0, x0 = props.centroid
        if whether_transpose:
            mitotic_centroids.append([z0, x0 - padding_x, y0 - padding_h])
        else:
            mitotic_centroids.append([z0, y0-padding_h, x0-padding_x])
    return remove_overlapped_cells(common_centroids), remove_overlapped_cells(mitotic_centroids)

def test_3d(model, path, idx, imgs, device, whether_transpose):
    h_ratio = shape(imgs)[-2] // 1024
    w_ratio = shape(imgs)[-1] // 512
    temp_masks = []
    common_centroids = []
    mitotic_centroids = []

    if h_ratio > 1 and w_ratio > 1:
        volume = imgs[idx][:, 0:h_ratio * 1024, 0:w_ratio * 512]
        padding_h = padding_x = 0
        for i in range(h_ratio):
            for j in range(w_ratio):
                temp = volume[:, i * 1024:(i + 1) * 1024, j * 512:(j + 1) * 512]
                temp = temp / 255
                temp_mask = pred_img(temp, model, device)
                temp_masks.append(temp_mask)
        pred_masks = zeros((len(volume), h_ratio * 1024, w_ratio * 512))
        for k in range(len(volume)):
            for i in range(h_ratio):
                for j in range(w_ratio):
                    pred_masks[k, i * 1024:(i + 1) * 1024, j * 512:(j + 1) * 512] = temp_masks[
                        k * h_ratio * w_ratio + i * w_ratio + j]
    elif h_ratio > 1 and w_ratio <= 1:
        volume = imgs[idx][:, 0:h_ratio * 1024, 0:512]
        volume, padding_h, padding_x = pad_image(volume, h_ratio * 1024, 512)
        for k in range(len(volume)):
            for i in range(h_ratio):
                temp = volume[k][i * 1024:(i + 1) * 1024, 0:512]
                temp = temp / 255
                temp_mask = pred_img(temp, model, device)
                temp_masks.append(temp_mask)
        pred_masks = zeros((len(volume), h_ratio * 1024, 512))
        for k in range(len(volume)):
            for i in range(h_ratio):
                pred_masks[k, i * 1024:(i + 1) * 1024, 512] = temp_masks[k * h_ratio + i]

    if shape(imgs)[-2] > 1100 or shape(imgs)[-1] > 600:
        if shape(imgs)[-2] > 1100 and shape(imgs)[-1] > 600:
            resize_parameter_h = shape(imgs)[-2]/1100
            resize_parameter_w = shape(imgs)[-1]/600
            crop_h = int(1100 * resize_parameter_h)
            crop_w = int(600 * resize_parameter_w)
            volume = imgs[idx][:, 0:crop_h, 0:crop_w]
            volume = zoom(volume, [1, 1/resize_parameter_h, 1/resize_parameter_w])
            volume = volume[:, 0:1024, 0:512]
        elif shape(imgs)[-2] > 1024:
            resize_parameter_h = shape(imgs)[-2] / 1024
            resize_parameter_w = 1
            crop_h = int(1024 * resize_parameter_h)
            volume = imgs[idx][:, 0:crop_h, :]
            volume = zoom(volume, [1, 1 / resize_parameter_h, 1])
            volume = volume[:, 0:1024, 0:512]
        else:
            resize_parameter_h = 1
            resize_parameter_w = shape(imgs)[-1] / 512
            crop_w = int(512 * resize_parameter_w)
            volume = imgs[idx][:, :, 0:crop_w]
            volume = zoom(volume, [1, 1, 1 / resize_parameter_w])
            volume = volume[:, 0:1024, 0:512]
    else:
        volume = imgs[idx][:, 0:1024, 0:512]
        resize_parameter_h = 1
        resize_parameter_w = 1

    if shape(volume)[1] != 1024 or shape(volume)[2] != 512:
        if shape(volume)[1] != 1024:
            if shape(volume)[2] != 512:
                padding_h = int((1024 - shape(volume)[1]) / 2)
                padding_x = int((512 - shape(volume)[2]) / 2)
                volume = pad(volume, ((0, 0),
                                      (padding_h, 1024 - shape(volume)[1] - padding_h),
                                      (padding_x, 512 - shape(volume)[2] - padding_x)),
                             'constant')
            else:
                padding_h = int((1024 - shape(volume)[1]) / 2)
                padding_x = 0
                volume = pad(volume, ((0, 0),
                                      (padding_h, 1024 - shape(volume)[1] - padding_h),
                                      (0, 0)),
                             'constant')
        else:
            padding_x = int((512 - shape(volume)[2]) / 2)
            padding_h = 0
            volume = pad(volume, ((0, 0),
                                  (0, 0),
                                  (padding_x, 512 - shape(volume)[2] - padding_x)),
                         'constant')
    else:
        padding_h = 0
        padding_x = 0

    z_number = len(volume)
    start_slice = int((z_number-24)/2)+1
    end_slice = int((z_number-24)/2)+25
    volume = volume[start_slice:end_slice, :, :]
    volume = zoom(volume, (1, 0.5, 0.5))
    volume_torch = torch.unsqueeze(torch.unsqueeze(torch.FloatTensor(volume / 255), 0), 0)
    pred = model(volume_torch.to(device))
    pred_softmax = softmax(pred, dim=1)
    pred_mask = torch.argmax(pred_softmax, dim=1)
    pred_mask_cpu = pred_mask[0].cpu().data.numpy()

    p_c, p_m = common_mitotic_cell_regions_3d(pred_mask_cpu)
    p_c = morphology.remove_small_objects(array(p_c, dtype=bool), 1)  # 3.5
    p_m = morphology.remove_small_objects(array(p_m, dtype=bool), 6)  # 50
    region_c, _ = measure_region(p_c)
    region_m, _ = measure_region(p_m)
    common_regions = measure.regionprops(region_c)
    mitotic_regions = measure.regionprops(region_m)

    mitotic_centroids = []
    common_centroids = []
    for props in common_regions:
        z0, y0, x0 = props.centroid
        common_centroids.append([z0 + start_slice, (y0 * 2 - padding_h)*resize_parameter_h, (x0 * 2 -padding_x)*resize_parameter_w])

    for props in mitotic_regions:
        z0, y0, x0 = props.centroid
        mitotic_centroids.append([z0 + start_slice, (y0 * 2 - padding_h)*resize_parameter_h, (x0 * 2 - padding_x)*resize_parameter_w])
    return common_centroids, mitotic_centroids


# -*- coding: utf-8 -*-
"""
Created on Fri May  8 16:30:40 2020

@author: matis
"""

import networkx as nx
import matplotlib.pyplot as plt

G=nx.DiGraph()

#Añadiendo vértices

G.add_node('1', pos=(2,1))
G.add_node('2', pos=(2,3))
G.add_node('3', pos=(0,4))
G.add_node('4', pos=(4,4))
G.add_node('5', pos=(1,5))
G.add_node('6', pos=(3,5))
G.add_node('7', pos=(2,6))

#Añadiendo artistas/arcos

G.add_edge('1','2', weight=2)
G.add_edge('1','3', weight=4)
G.add_edge('2','3', weight=1)
G.add_edge('2','4', weight=1)
G.add_edge('3','5', weight=5)
G.add_edge('4','3', weight=-1)
G.add_edge('4','6', weight=-1)
G.add_edge('5','4', weight=-2)
G.add_edge('5','7', weight=1)
G.add_edge('6','5', weight=2)
G.add_edge('6','7', weight=3)

weight = nx.get_edge_attributes(G,'weight')
pos = nx.get_node_attributes(G,'pos')

nx.draw_networkx(G,pos)
nx.draw_networkx_edge_labels(G,pos, edge_labels=weight)

#Código para dibujar las aristas del árbol de cobertura mínimo

MST=set()
for i in G.nodes():
    camino = nx.bellman_ford_path(G, '1' , i)
    camino_aristas = zip(camino, camino[1:])
    for j in camino_aristas:
        MST.add(j)
nx.draw_networkx_edges(G,pos,edgelist=MST,edge_color='r',width=5)
plt.axis('off')
plt.show()

Optimización/NetworkX/Bellmanford negative cost cycle.py


import pytesseract
import os
import time
from PIL import ImageGrab
import keyboard
import csv
import threading
import os
import sys

tesseract_path = os.path.join(os.path.dirname(os.path.abspath(sys.executable)), 'Tesseract-OCR')
pytesseract.pytesseract.tesseract_cmd = os.path.join(tesseract_path, 'tesseract.exe')

def grab_image_from_clipboard(output_file, prev_img_hash):

    #setze den hash falls schon ein Bild in der zwischenablage existiert
    img = ImageGrab.grabclipboard()
    if img is not None:
        prev_img_hash[0] = hash(img.tobytes())
    while True:
        # Bild aus Zwischenablage holen
        img = ImageGrab.grabclipboard()

        if img is not None:
            # Bild-Hash berechnen, um Änderungen in der Zwischenablage zu erkennen
            img_hash = hash(img.tobytes())

            if prev_img_hash[0] != img_hash:
                prev_img_hash[0] = img_hash
                # OCR-Anwendung auf das Bild
                text = pytesseract.image_to_string(img, lang='deu')
                print("Erkannter Text: ", text)

                # Speichern des erkannten Textes in der Textdatei
                with open(output_file, 'a', encoding='utf-8') as f:
                    f.write(text)
                    f.write('\n')
            # else:
            #     print("Keine Änderung in der Zwischenablage erkannt.")
        # else:
        #     print("Kein Bild in der Zwischenablage gefunden.")

        time.sleep(2)

def main():
    output_file_base = "documents/" + input("Geben Sie den Basisdateinamen für das Text-Dokument ein (ohne Dateierweiterung): ")
    # csv_file = "documents/" + input("Geben Sie den Dateinamen für die CSV-Datei ein (ohne Dateierweiterung): ") + '.csv'

    prev_img_hash = [None]
    file_count = 1
    output_file = output_file_base + "_" + str(file_count) + '.txt'

    print("Drücken Sie 'Ctrl+C' oder 'Ctrl+Break', um das Programm zu beenden.")
    print("mache screenshots und der Text wird automatisch in das Textdokument geschrieben\n")
    print("zusatzoption: drücke # um ein neues dokument zu erzeugen\n(du hast ein unterkapitel gelesen)\n")
    # print("Drücke + um die speicherung in csv zu starten\n(einfach den Text von chatgpt in die Konsole anfügen und anschließend enter drücken)\n")

        # Anfangstext zum Textdokument hinzufügen
    anfangs_text =  """\
Lieber ChatGPT,

ich habe folgende aufgaben für dich:

-bitte erstelle mir Karteikarten für anki
-bitte im csv format
-bitte mit semikolon als trennzeichen
-bitte so das man es in anki importieren kann:)
-bitte in einem codeblock

vielen dank :)
der Text:\

"""
    with open(output_file, 'a', encoding='utf-8') as f:
        f.write(anfangs_text + '\n')

    # Füge hier den restlichen Code ein, der parallel ausgeführt werden soll

    t = threading.Thread(target=grab_image_from_clipboard, args=(output_file, prev_img_hash))
    t.start()

    try:
        while True:
            # Wenn die 1 gedrückt wird, erstellen Sie eine neue Datei
            if keyboard.is_pressed('#'):
                file_count += 1
                output_file = output_file_base + str(file_count) + '.txt'
                with open(output_file, 'a', encoding='utf-8') as f:
                    f.write(anfangs_text + '\n')
                print(f"Neue Datei erstellt: {output_file}")
                time.sleep(0.5)

            # # Wenn die Taste "2" gedrückt wird, warten Sie auf eine Eingabe und speichern Sie sie in der CSV-Datei
            # if keyboard.is_pressed('+'):
            #     time.sleep(0.5)
            #     input_lines = []
            #     while True:
            #         user_input = input("Bitte geben Sie eine Frage und Antwort ein (oder 'q' zum Beenden): ")
            #         if user_input.lower() == 'q':
            #             break
            #         input_lines.append(user_input.split(";"))

            #     with open(csv_file, 'a', encoding='utf-8') as csvfile:
            #         writer = csv.writer(csvfile)
            #         for line in input_lines:
            #             writer.writerow([line])
            #     print("Daten in die CSV-Datei geschrieben.")

    except KeyboardInterrupt:
        print("Skript beendet.")

if __name__ == '__main__':
    main_thread = threading.Thread(target=main)
    main_thread.start()
    main_thread.join()


from __future__ import annotations

import re
from collections import defaultdict
from typing import NamedTuple
from typing import NewType

RE = re.compile(r"(\d+)-(\d+)")

class Range(NamedTuple):
    min: int  # noqa: A003
    max: int  # noqa: A003

    def valid(self, n: int) -> bool:
        return self.min <= n <= self.max

class Rule(NamedTuple):
    name: str
    ranges: list[Range]

    def valid(self, n: int) -> bool:
        return any(r.valid(n) for r in self.ranges)

Ticket = NewType("Ticket", list[int])

def parse(filename: str) -> tuple[list[Rule], Ticket, list[Ticket]]:
    with open(filename) as f:
        raw_rules, raw_yours, raw_nearby = f.read().split("\n\n")

    rules = []
    for r in raw_rules.split("\n"):
        raw_name, _, raw_ranges = r.partition(":")
        ranges = [Range(int(mn), int(mx)) for mn, mx in RE.findall(raw_ranges)]

        rules.append(Rule(raw_name.strip(), ranges))

    yours = Ticket([int(t) for t in raw_yours.splitlines()[-1].split(",")])

    nearby = [
        Ticket([int(t) for t in ticket.split(",")])
        for ticket in raw_nearby.splitlines()[1:]
    ]

    return rules, yours, nearby

def part1(filename: str) -> int:
    rules, _, nearby = parse(filename)

    return sum(
        t
        for ticket in nearby
        for t in ticket
        if not any(rule.valid(t) for rule in rules)
    )

def part2(filename: str) -> int:
    rules, yours, nearby = parse(filename)

    valid_tickets = [ticket for ticket in nearby if valid(ticket, rules)]

    names = defaultdict(set)
    for i in range(len(yours)):
        for rule in rules:
            if all(rule.valid(ticket[i]) for ticket in valid_tickets):
                names[rule.name].add(i)

    out = {}
    while names:
        positions_to_pop = []
        names_to_pop = []
        for name, positions in names.items():
            if len(positions) == 1:
                p = positions.pop()
                positions_to_pop.append(p)
                names_to_pop.append(name)
                out[name] = p

        for positions in names.values():
            if p in positions:
                positions.remove(p)

        for name in names_to_pop:
            del names[name]

    product = 1
    for name, position in out.items():
        if name.startswith("departure"):
            product *= yours[position]

    return product

def valid(ticket: Ticket, rules: list[Rule]) -> bool:
    return any(all(rule.valid(t) for t in ticket) for rule in rules)

if __name__ == "__main__":
    from advent_of_code.common.main import main

    raise SystemExit(main(part1, part2))


import pandas as pd
import numpy as np
import scipy
from matplotlib import pyplot as plt
from scipy import stats
import math
import scipy.optimize
from New_Function_set import *
import tqdm
import sys
import os
import pickle

def get_results(df_data, cancer_type, k=0, j=50):
    print('>>>>>>>>> code start!')

    #if cancer_type == 'Lung Squamous':
    #    patient_list = df_data[0].value_counts()[k+22:j].index.tolist()
    #else:
    #    patient_list = df_data[0].value_counts()[k:j].index.tolist()
    # Get top k to J patients with the most mutations
    patient_list = df_data[0].value_counts()[k:j].index.tolist()

    counter = len(patient_list)
    if not os.path.exists('Correct_'+cancer_type):
        os.makedirs('Correct_'+cancer_type)
    #initial the dictionary
    PLVD = {} ### create dictionary to save the predicted lambda values
    PLVD_new = {}

    for patient_id in patient_list:# iterate with patient.
        print("now is the patient_{}!".format(patient_id))
        # create file to save the results and figures
        if not os.path.exists('Correct_' + cancer_type + '/{}'.format(patient_id)):
            os.makedirs('Correct_' + cancer_type + '/{}'.format(patient_id))

        if not os.path.exists('Correct_' + cancer_type + '/new_{}'.format(patient_id)):
            os.makedirs('Correct_' + cancer_type + '/new_{}'.format(patient_id))

        path = 'Correct_' + cancer_type+'/{}'.format(patient_id)
        path_2 = 'Correct_' + cancer_type
        path_3 = 'Correct_' + cancer_type + '/new_{}'.format(patient_id)

        df_1 = df_data[(df_data[0]==patient_id) & (df_data[1]=='subs')] # get the data with only substitution mutations
        df_sort = df_1.sort_values(by=[3])
        distance, df_bucket = window_sliding(df_1,2,3,4,50000000,7000000,autosomal=False)
        threshold_list = {k: [] for k in distance.keys()}
        for c in tqdm.tqdm(distance.keys()): #iterate by chromosome
            for i in range(0, 29):
                threshold_can, dict_can = maxlikelihood(distance[c], i, range(3000, 10000, 100))
                threshold_list[c] = threshold_list[c] + [int(threshold_can)]

        dic_chr = {}
        dic_chr_new = {}
        for c in distance.keys():
            filter_col = [s for s in list(df_bucket.columns) if s.endswith('chr' + c)]
            dic_chr['chr' + c] = fit_function(df_bucket[filter_col], distance[c], c, False, False, threshold_list[c])

        ### plot distribution exchange ###
        D = locals()
        l = locals()
        for c in distance.keys():
            D['dict_chr' + c] = {}

            se_, sp_, le_, lp_ = parameter_conclude_1(dic_chr['chr' + c])
            parameter_conclude_2(se_, sp_, le_, lp_, patient_id, c, path, False, False, plot_withDistance=True)

            D['dict_chr' + c]['shrot_exp'] = se_
            D['dict_chr' + c]['shrot_pow'] = sp_
            D['dict_chr' + c]['long_exp'] = le_
            D['dict_chr' + c]['long_pow'] = lp_

        for c in distance.keys():
            ### short expon ###
            try:
                se_ = D['dict_chr' + c]['shrot_exp']
                plt.plot(list(zip(*se_))[0], -1 * np.array(list(zip(*se_))[1]))
                plt.scatter(list(zip(*se_))[0], -1 * np.array(list(zip(*se_))[1]), color='palevioletred')
                plt.title("short_expon_{}".format(patient_id))
                plt.savefig(path+'/shot_expon_{}.jpg'.format(c))
                plt.close()

            except IndexError:
                pass

            ### short powerlaw ###
            try:
                sp_ = D['dict_chr' + c]['shrot_pow']
                plt.plot(list(zip(*sp_))[0], -1 * np.array(list(zip(*sp_))[1]))
                plt.scatter(list(zip(*sp_))[0], -1 * np.array(list(zip(*sp_))[1]), color='palevioletred')
                plt.title("short_powerlaw_{}".format(patient_id))
                plt.savefig(path+'/shot_powerlaw_{}.jpg'.format(c))
                plt.close()

            except IndexError:
                pass

            ### long expon ###
            try:
                le_ = D['dict_chr' + c]['long_exp']
                plt.plot(list(zip(*le_))[0], -1 * np.array(list(zip(*le_))[1]))
                plt.scatter(list(zip(*le_))[0], -1 * np.array(list(zip(*le_))[1]), color='palevioletred')
                plt.title("long_expon_{}".format(patient_id))
                plt.savefig(path+'/long_expon_{}.jpg'.format(c))
                plt.close()

            except IndexError:
                pass

            ### long powerlaw ###
            try:
                lp_ = D['dict_chr' + c]['long_pow']
                plt.plot(list(zip(*lp_))[0], -1 * np.array(list(zip(*lp_))[1]))
                plt.scatter(list(zip(*lp_))[0], -1 * np.array(list(zip(*lp_))[1]), color='palevioletred')
                plt.title("long_powerlaw_{}".format(patient_id))
                plt.savefig(path+'/long_powerlaw_{}.jpg'.format(c))
                plt.close()

            except IndexError:
                pass

        ### add each chromosome together to plot:
        P = locals()
        pos_chr = {}
        max_length = 0
        # align the position of each chromosome and add all chromosome sequentially for 1 to 23
        for c in distance.keys():
            pos_chr[c] = {}
            pos_chr[c]['min'] = df_1[3][df_1[2] == c].min()
            pos_chr[c]['max'] = df_1[3][df_1[2] == c].max()
            pos_chr[c]['mlength'] = pos_chr[c]['max'] - pos_chr[c]['min']
            if pos_chr[c]['max'] > max_length:
                max_length = pos_chr[c]['max']

        df_empty = pd.DataFrame()
        for i in df_1[2].unique():
            df_kk = df_1[df_1[2] == i].sort_values(by=[3])
            df_kk['distance'] = df_1[df_1[2] == i].sort_values(by=[3])[3].diff()

            df_empty = pd.concat([df_empty, df_kk], axis=0)
        df_k = df_empty

        ### normalized each chromosome to make them plot in sequnence
        l = [str(a) for a in range(1, 23)] + ['X']
        l_chr = ['chr_' + x for x in l]
        chr_bound = []
        max_val = 0

        new_l = []
        for i in l:
            if i in distance.keys():
                new_l = new_l + [i]

        new_l_chr = ['chr_' + x for x in new_l]

        for c in new_l:
            val = df_k[3][df_k[2] == c]
            idx = df_k[df_k[2] == c].index
            df_k.loc[idx, 3] = val - pos_chr[c]['min'] + max_val
            max_val = pos_chr[c]['max'] - pos_chr[c]['min'] + max_val
            chr_bound = chr_bound + [max_val]

        ######## set each mutation type with particular color #######
        ### C>A
        x_bule = df_k[(df_k[6]=='C')&(df_k[5]=='A')][3]
        y_bule = df_k[(df_k[6]=='C')&(df_k[5]=='A')]['distance']

        x_bule_1 = df_k[(df_k[6]=='G')&(df_k[5]=='T')][3]
        y_bule_1 = df_k[(df_k[6]=='G')&(df_k[5]=='T')]['distance']
        ### C>G
        x_black = df_k[(df_k[6]=='C')&(df_k[5]=='G')][3]
        y_black = df_k[(df_k[6]=='C')&(df_k[5]=='G')]['distance']

        x_black_1 = df_k[(df_k[6]=='G')&(df_k[5]=='C')][3]
        y_black_1 = df_k[(df_k[6]=='G')&(df_k[5]=='C')]['distance']
        ### C>T
        x_red = df_k[(df_k[6]=='C')&(df_k[5]=='T')][3]
        y_red = df_k[(df_k[6]=='C')&(df_k[5]=='T')]['distance']

        x_red_1 = df_k[(df_k[6]=='G')&(df_k[5]=='A')][3]
        y_red_1 = df_k[(df_k[6]=='G')&(df_k[5]=='A')]['distance']
        ### T>A
        x_puple = df_k[(df_k[6]=='T')&(df_k[5]=='A')][3]
        y_puple = df_k[(df_k[6]=='T')&(df_k[5]=='A')]['distance']

        x_puple_1 = df_k[(df_k[6]=='A')&(df_k[5]=='T')][3]
        y_puple_1 = df_k[(df_k[6]=='A')&(df_k[5]=='T')]['distance']
        ### T>C
        x_yellow = df_k[(df_k[6]=='T')&(df_k[5]=='C')][3]
        y_yellow = df_k[(df_k[6]=='T')&(df_k[5]=='C')]['distance']

        x_yellow_1 = df_k[(df_k[6]=='A')&(df_k[5]=='G')][3]
        y_yellow_1 = df_k[(df_k[6]=='A')&(df_k[5]=='G')]['distance']
        ### T>G
        x_green = df_k[(df_k[6]=='T')&(df_k[5]=='G')][3]
        y_green = df_k[(df_k[6]=='T')&(df_k[5]=='G')]['distance']

        x_green_1 = df_k[(df_k[6]=='A')&(df_k[5]=='C')][3]
        y_green_1 = df_k[(df_k[6]=='A')&(df_k[5]=='C')]['distance']

        # now plot the mutation graph!
        plt.figure(figsize=(15,6))
        plt.scatter(x_bule,y_bule,c='blue',label='C>A')
        plt.scatter(x_black,y_black,c='black',label='C>G')
        plt.scatter(x_red,y_red,c='red',label='C>T')
        plt.scatter(x_puple,y_puple,c='purple',label='T>A')
        plt.scatter(x_yellow,y_yellow,c='yellow',label='T>C')
        plt.scatter(x_green,y_green,c='lime',label='T>G')

        plt.scatter(x_bule_1,y_bule_1,c='royalblue',label='G>T')
        plt.scatter(x_black_1,y_black_1,c='dimgray',label='G>C')
        plt.scatter(x_red_1,y_red_1,c='firebrick',label='G>A')
        plt.scatter(x_puple_1,y_puple_1,c='fuchsia',label='A>T')
        plt.scatter(x_yellow_1,y_yellow_1,c='gold',label='A>G')
        plt.scatter(x_green_1,y_green_1,c='limegreen',label='A>C')

        plt.vlines(x=chr_bound, ymax=10 ** 6, ymin=0, linestyles='dashed', colors='lightgray')
        plt.yscale('log')
        plt.yticks([1, 10 ** 1, 10 ** 2, 10 ** 4, 10 ** 6])
        plt.xticks(chr_bound, new_l_chr, rotation=45)
        plt.xlabel('Genomic position')
        plt.legend(bbox_to_anchor=(0.5, -0.2), loc='center', ncol=12, edgecolor='w')
        plt.title("patient_{}".format(patient_id))
        plt.savefig(path_2+'/Kataegis_{}.jpg'.format(patient_id))
        plt.close()
        print("patient_{} is finished!".format(patient_id))
        print("---------- {} patients left ----------".format(counter-1))
        counter = counter-1

        PLVD[patient_id] = dic_chr
    f = open('/home/lthpc/MHY/New_DNA/ParaDct/file_{}.pkl'.format(cancer_type), 'wb')
    pickle.dump(PLVD, f)
    f.close()

if __name__ == "__main__":

    type_list = ['Breast','Lung Squamous', 'Prostate', 'Pilocytic Astrocytoma','Neuroblastoma','Melanoma','Medulloblastoma',\
                'Lung Adeno','ALL','Lymphoma B-cell','Colorectum','Stomach','Esophageal','Head and Neck','AML',\
                'Bladder','Glioma Low Grade','Kidney Clear Cell','Uterus','Kidney Papillary','Glioblastoma','Myeloma',\
                'Thyroid','Kidney Chromophobe','Pancreas','Cervix','Liver','Ovary','CLL','Lung Small Cell']

    for i in type_list:
        print('>>>>>>>>>Hello,the code access to type '+i+'>>>>>>>>>')
        df_data = pd.read_csv('/home/lthpc/MHY/DNA_mutation/somatic_mutation_data/'+i+'/'+i+'_raw_mutations_data.txt', \
                                delimiter="\t", header=None)

        get_results(df_data, i, 0, 50)


"""
This class has the responsibility to manage display of menu
and navigation inside menu.
"""
import os
import json
import tablib
import Bdd as database

class Display():
    """
    This class has the responsibility to manage display of menu
    and navigation inside menu.
    """
    def __init__(self):
        self.first_menu_list = ["Quels aliments souhaitez-vous remplacer ?",
                                "Retrouver mes aliments substitués.",
                                "Quitter le programme."]

        self.category_list = ["Produits laitiers", "Boissons", "Petit-déjeuners",
                              "Viandes", "Desserts"]
        self.sub_category_list = [
            ["Laits", "Beurres", "Boissons lactées", "Fromages"],
            ["Sodas", "Boissons au thé", "Boissons énergisantes"],
            ["Céréales pour petit-déjeuner", "Pâtes à tartiner", "Confitures et marmelades"],
            ["Charcuteries", "Volailles"],
            ["Desserts au chocolat", "Compotes", "Desserts lactés", "Snacks sucrés"]
            ]
        self.bdd = database.Bdd()
        self.command = None # this attribute will be initialized in 'import_json_data' method

    def import_json_data(self):
        """
        Method that imports datas contained into json file
        """
        # we use method of module json
        with open("config.json", "r") as file:
            config = json.load(file)
            self.command = config["Command"]

    def welcome(self):
        """
        Method wich makes an "introduction" of program
        """
        self.import_json_data()
        sentences = ("Bonjour et bienvenue sur le programme de la startup 'PurBeurre'.",
                     "Ce programme vous permet de récupérer directement les données de ",
                     "la (gigantesque) base de données 'OpenFoodFacts'. Pour plus ",
                     "d'informations sur l'utilisation de ce logiciel, n'hésitez pas ",
                     "à lire le fichier 'README.md'. Bonne utilisation !",
                     "")
        for sentence in sentences:
            print(sentence)
        input("Appuyez sur 'enter' pour continuer")

    def menu(self):
        """
        Method wich manages travel inside menu and allows to called method wich corresponds
        of user's choice.
        """
        index, intern_index, name = 0, 0, 0
        functions_list = [self.first_menu, self.category_menu, self.sub_cat_menu,
                          self.products_menu, self.user_menu]
        launched = True
        while launched:
            os.system(self.command)
            # needed parameters for each function
            parameters_list = [[index], [index], [index, intern_index],
                               [index, name, intern_index], []]
            launched, index, intern_index, name = functions_list[index](*parameters_list[index])

    def validate_answer_int(self, product_list, sentence=0):
        """
        Method wich attends to validate an 'int' user's answer. This method verifies if
        response of user is an integer, if this response is possible...
        """
        self.create_space()
        validate = False
        sentences = ["Quel choix voulez-vous ?: ",
                     "Sur quel produit voulez-vous plus d'information ?: ",
                     "Plus d'information ?: "]
        while not validate:
            answer = input(sentences[sentence]) # we display the good question
            try:
                answer = int(answer) #checking if it is a int
            except:
                print("Ce n'est pas un chiffre")
                continue # we raise the question again.
            if 0 <= answer <= len(product_list):
                validate = True # if answer is a possible choice.
            else:
                print("Ce chiffre ne correspond à aucun choix")
        return answer - 1

    def validate_answer_yes_no(self, question):
        """
        Method wich attends to validate an answer of user of type 'Yes/No'.
        This method verify if the answer is 'O' or 'N'.
        """
        self.create_space()
        questions = ["Voulez-vous valider votre choix ? (O/N): ",
                     "Voulez-vous enregistrer votre choix ? (O/N): "]
        while True:
            answer = input(questions[question])
            if answer == "O":
                return True
            elif answer == "N":
                return False
            else:
                print("Ce n'est pas une réponse valide\n"+
                      "les seuls réponses possibles étant 'O' (='Oui') ou 'N' (='Non')")

    def make_choice(self, liste):
        """
        Method wich displays elements of a list and
        returns the chosen element by user and its position inside
        this list.
        """
        for i, element in enumerate(liste):
            print(str(i + 1), "-", str(element))
        answer = self.validate_answer_int(liste)
        element = liste[answer]
        return answer, element

    def first_menu(self, index):
        """
        Method wich attends to manage the first menu and allows to
        dispatch to other menus or stops the menu
        (depending on user's choice)
        """
        answer, name = self.make_choice(self.first_menu_list)
        launched = True
        if answer == 0:
            index += 1 # go to category_menu
        elif answer == 1:
            index += 4 # go to user_menu
        elif answer == 2:
            print("Merci et à bientôt !")
            launched = False # close the program
        return launched, index, answer, name

    def category_menu(self, index):
        """
        Method wich attends to manage choice of categories.
        """
        answer, name = self.make_choice(self.category_list)
        if answer == -1:
            index -= 1 # go back to first menu
        else:
            index += 1 # go to sub_category menu
        return True, index, answer, name

    def sub_cat_menu(self, index, intern_index):
        """
        Method wich attends to manage choice of sub-categories.
        """
        answer, name = self.make_choice(self.sub_category_list[intern_index])
        if answer == -1:
            index -= 1 # go back to category menu
        else:
            index += 1 # go to products menu

        return True, index, intern_index, name

    def create_tablib(self, products_list, headers_list):
        """
        Method wich allows to create and display an object of library tablib.
        It displays a list of products.
        This method returns user's choice
        """
        data = tablib.Dataset()
        data.headers = headers_list # name of columns
        keys_list, index = ["product_name", "brand", "nutrition_score"], 1
        for dictionnary in products_list: # for each product
            value_to_append = []
            for key in keys_list:
                value_to_append.append(dictionnary[key]) # we find value
            value_to_append.insert(0, index) # we insert at the beginning its (index + 1)
            index += 1
            data.append(value_to_append) # we append to Tablib object
        print(data) # we displays data table
        # user has to make a choice
        answer = self.validate_answer_int(products_list, 1)
        return answer

    def display_informations_product(self, product):
        """
        Method wich displays all the informations about a given product.
        It returns datas wich are needed if the user wants to record his choice
        into database.
        """
        self.create_space()
        tuple_keys_list = [("barcode", "Code barre produit"), ("product_name", "Nom du produit"),
                           ("brand", "Marque"), ("nutrition_grade", "Grade nutritionnel"),
                           ("nutrition_score", "Score nutritionnel"), ("stores", "Magasins"),
                           ("url", "Url")]
        # we displays each information contained into tuple_keys_list
        for key, value in tuple_keys_list:
            print(value, "=", product[key])
        answer = self.validate_answer_yes_no(0) # the answer must be validate
        return answer, (product["barcode"], product["nutrition_score"])

    def product(self, index, name, products_list):
        """
        Method wich attends to manage and display products of a sub-category.
        It allows to access to substitutes of product the user has chosen.
        """
        if products_list == 0: # If we has not already communicated with database
            products_list = self.bdd.find_products(name) # we find products of a sub-category
        # we will displays a 'summary' of each product
        headers_list = ["Touche", "Nom produit", "Marque", "Score"]
        while True:
            os.system(self.command)
            print("Tableau Produits:\n", " ")
            answer = self.create_tablib(products_list, headers_list)
            if answer == -1: # we go back to sub-category menu
                return False, index, products_list, 0
            # else
            sub_answer, value_product = self.display_informations_product(products_list[answer])
            if sub_answer:
                index += 1 # we go to substitutes of the chosen product
                return True, index, products_list, value_product
            continue

    def recording_into_user(self, value_product, value_substitute):
        """
        Method wich deals with request for recording into database. Method
        use bdd object wich allows to communicate with database.
        """
        answer = self.validate_answer_yes_no(1)
        if answer: # if answer is yes (=True)
            self.bdd.record_table_user(value_product, value_substitute)
        else: # if answer is no (=False)
            print("Vous allez être redirigé vers le menu")
            input("Appuyez sur 'enter' pour continuer: ")

    def substitute(self, index, name, products_list, value):
        """
        Method wich attends to manage and display substitute products.
        At the end, if user want it, method uses a method that allows
        recording into database.
        """
        # substitute list of a given product (and a given nutriscore)
        substitute_list = self.bdd.find_products(name, value[1])
        headers_list = ["Touche", "Nom produit", "Marque", "Score"]
        while True:
            os.system(self.command)
            print("Tableau Substituts:\n", " ")
            answer = self.create_tablib(substitute_list, headers_list)
            if answer == -1:
                index -= 1 # we go back to product menu
                return True, index, products_list, 0
            sub = substitute_list[answer] # the substitute user has chosen
            # we displays all informations about this substitute
            sub_answer, value_substitute = self.display_informations_product(sub)
            if sub_answer: # if the user wants to record into database
                self.recording_into_user(value, value_substitute)
                # we go back to sub_category menu
                return False, index, products_list, value
            continue

    def products_menu(self, index, name, index_2):
        """
        Method wich allows to manage navigation through choice of products and choice
        of substitutes.
        """
        intern_index, products_list, value = 0, 0, 0
        # list of functions : first = manage products
        #                     second = manage substitutes of the chosen product
        functions_list = [self.product, self.substitute]
        launched = True
        while launched:
            # parameters needed for functions contained in functions_list
            parameters_list = [[intern_index, name, products_list],
                               [intern_index, name, products_list, value]]
            launched, intern_index, products_list, value = \
            functions_list[intern_index](*parameters_list[intern_index])
        index -= 1 # we go back to the sub-category menu
        return True, index, index_2, 0

    def user_menu(self):
        """
        Method wich allows to display and manage the user's menu (= list of all recordings the user
        made while he was using the program). This method allows to consults details of
        each recording).
        """
        # method wich returns a list of datas contained into table 'user'
        prod_sub_list = self.bdd.find_substitute()
        headers_list = ["Touche", "Nom produit", "Nutriscore produit",
                        "Nom substitut", "Nutriscore substitut"]
        while True:
            os.system(self.command)
            answer = self.create_tablib_user(prod_sub_list, headers_list)
            if answer == -1:
                break # we go back to first menu
            # we display informations about a line user has chosen
            self.display_informations_user(prod_sub_list[answer])

        return True, 0, 0, 0

    def create_tablib_user(self, user_list, headers_list):
        """
        Method wich allows to create and display an object of librairie tablib.
        It displays a list of products previously recorded by user.
        This method returns the choice of user.
        """
        data = tablib.Dataset()
        data.headers = headers_list
        # informations of products and substitutes we will display
        keys_list, index = ["name_product", "nutrition_score_product",
                            "name_substitute", "nutrition_score_sub"], 1
        for dictionnary in user_list: # for each line into table user
            value_to_append = [] # datas we will append in Dataset
            for key in keys_list: # for each information we will display
                value_to_append.append(dictionnary[key])
            value_to_append.insert(0, index)
            index += 1
            data.append(value_to_append)
        print(data) # we display dataset
        # we ask to user wich line he wants details
        answer = self.validate_answer_int(user_list, 2)
        return answer

    def create_space(self):
        """
        Method wich allows to properly separate two 'displays'
        """
        print("")
        print("#"*60)
        print("")

    def display_informations_user(self, product):
        """
        Method wich allows to completely display
        details of a product and its substitute.
        """
        self.create_space()
        # we create a list of tuples that contained a key and
        # its "display" name
        tuple_keys_product_list = [
            ("id_product", "code barre produit"), ("name_product", "nom produit"),
            ("brand_product", "marque produit"), ("url_product", "url produit"),
            ("nutrition_grade_product", "grade produit"),
            ("nutrition_score_product", "score produit"),
            ("stores_product", "magasins où trouver le produit"),
            ("name_category", "nom catégorie"), ("name_sub_category", "nom sous_catégorie")]

        tuple_keys_sub_list = [
            ("id_substitute", "code barre substitut"), ("name_substitute", "nom substitut"),
            ("brand_substitute", "marque substitut"), ("url_substitute", "url substitut"),
            ("nutrition_grade_sub", "grade substitut"), ("nutrition_score_sub", "score substitut"),
            ("stores_substitute", "magasins où trouver le substitut"),
            ("name_category", "nom catégorie"), ("name_sub_category", "nom sous_catégorie")]
        # we display each information about a product
        for key, value in tuple_keys_product_list:
            print(value, "=", product[key])
        self.create_space()
        print("Substitué par :")
        self.create_space()
        # then we display each information about its substitute
        for key, value in tuple_keys_sub_list:
            print(value, "=", product[key])

        input("Appuyez sur entrée :")


from cell import Cell
import pygame

class Board:

    def __init__(self, game, id):
        self.game = game
        self.window = game.window
        self.amount_of_cols = game.amount_of_cols
        self.id = id
        self.boats = []
        self.cells = []
        self.cell_size = pygame.display.get_surface().get_width() / game.amount_of_cols
        self.create_cells() # skapa celler

    def create_cells(self):
        for i in range(self.amount_of_cols):
            tempList = []
            for j in range(self.amount_of_cols):
                cell = Cell(i, j, self.window, self.cell_size, self.game)
                tempList.append(cell)
            self.cells.append(tempList)

    def render(self):
        self.window.fill([255,255,255])
        for list in self.cells:
            for cell in list:
                cell.render()
        font = pygame.font.SysFont('Comic Sans MS', 30)
        if self.game.current_gamestate == "setup":
            player_area_text = "Spelare " + str(self.game.current_player.id)
        else:
            if self.game.current_player.id == 1:
                player_area_text = "Spelare " + str(2)
            else:
                player_area_text = "Spelare " + str(1)
        text = font.render(player_area_text, False, (0, 0, 0))
        w, h = pygame.display.get_surface().get_size()
        text_rect = text.get_rect(center=(w/2, w + ((h-w)/2)))
        self.window.blit(text, text_rect)
        pygame.display.flip()

    def check_cell(self, pos, boat=None):
        px, py = pos
        #print(boat)
        x = int(px / self.cell_size)
        y = int(py / self.cell_size)
        if self.game.current_gamestate == "setup":
            return boat.check(x, y, boat)
        else:
            return self.cells[x][y].trigger_click()

    def render_winner_text(self, player):
        font = pygame.font.SysFont('Comic Sans MS', 30)
        self.window.fill([255, 255, 255])
        winner_text = "Spelare " + str(player.id) + " vinner!"
        text = font.render(winner_text, False, (0, 0, 0))
        w, h = pygame.display.get_surface().get_size()
        text_rect = text.get_rect(center=(w / 2, w + ((h - w) / 2)))
        self.window.blit(text, text_rect)
        pygame.display.flip()


import pygame

class DropDown():

    def __init__(self):
        self.color_menu = (255, 255, 255)
        self.color_option = (0, 0, 0)
        self.rect_combo = pygame.Rect(500, 50, 100, 25)
        self.font = pygame.font.Font(None, 32)
        self.main = "Hola"
        self.options = ['jiji', 'ijii', 'njnjnni']
        self.draw_menu = False
        self.menu_active = False
        self.active_option = -1
        self.terminar_combo = False
        self.rectas_options = []
        self.eleccion = None
        alto = 500
        ancho = 910
        self.base_font = pygame.font.Font(None, 32)
        self.win = pygame.display.set_mode((ancho, alto))
        self.win.fill((0,0,0))

    def combo_draw(self):
        pygame.draw.rect(self.win, self.color_menu, self.rect_combo, 0)
        self.img = pygame.image.load("descarga.png")
        self.rect_2 = pygame.Rect(500, 50, 100, 25)
        self.rect_2.left += 100
        self.win.blit(self.img, self.rect_2)

    def draw(self):
        self.combo_draw()
        cont = 0

        while not self.terminar_combo:
            for event in pygame.event.get():
                if event.type == pygame.QUIT: self.terminar_combo = True
                if event.type == pygame.MOUSEBUTTONDOWN and event.button == 1:
                    mouse_pos = pygame.mouse.get_pos()
                    if mouse_pos[0] >= self.rect_2.left and mouse_pos[0] <= self.rect_2.left+25:
                        if cont == 0 or cont%2 == 0:
                            self.draw_menu = True
                        else:
                            self.win.fill((0,0,0))
                            self.draw_menu = False
                        cont+= 1

                    else:
                        if self.draw_menu == True:
                            for i in range(len(self.rectas_options)):
                                actual = self.rectas_options[i]
                                if mouse_pos[1] <= actual.top+20 and mouse_pos[1] >= actual.top and mouse_pos[0] <= actual.left+90 and mouse_pos[0] >= actual.left:
                                    self.eleccion = self.options[i]
                                    self.win.fill((0,0,0))
                                    self.borrar_informacion_combobox(True)

                    print(self.eleccion)

            if self.draw_menu:
                for i, text in enumerate(self.options):
                    rect = self.rect_combo.copy()

                    rect.y += (i+1) * self.rect_combo.height
                    self.rectas_options.insert(i, rect)
                    if len(self.rectas_options) > i+1:
                        self.rectas_options.pop(i+1)

                    pygame.draw.rect(self.win, self.color_menu, rect, 0)
                    msg = self.font.render(text, 1, self.color_option)
                    self.win.blit(msg, rect)
            else:
                self.borrar_informacion_combobox(False)

            pygame.display.flip()

    def borrar_informacion_combobox(self, desplegado):
        self.combo_draw()

        if desplegado == True:
            for i, text in enumerate(self.options):
                rect = self.rect_combo.copy()

                rect.y += (i+1) * self.rect_combo.height
                self.rectas_options.insert(i, rect)
                if len(self.rectas_options) > i+1:
                    self.rectas_options.pop(i+1)

                pygame.draw.rect(self.win, self.color_menu, rect, 0)
                msg = self.font.render(text, 1, self.color_option)
                self.win.blit(msg, rect)

        if self.eleccion != None:
            msg = self.base_font.render(self.eleccion, 1, (0, 0, 0))
            self.win.blit(msg, self.rect_combo)


"""
    Module to initialize the 2D Riemann Problem
"""

import numpy as np

from CentralUpwindScheme.initlaize_riemann_variables import(
    get_initial_conditions,
    get_one_dimensional_grids,
    get_conserved_variables
)

from CentralUpwindScheme.plot import plot

import CentralUpwindScheme.constants as CTS
import CentralUpwindScheme.utility as UTL

from CentralUpwindScheme.cu_flux import *

class CentralUpwindScheme:
    """
        Class representing the Riemann problem
        and run the Central Upwind Scheme
    """

    def __str__(self):
        """
            Special function to represent the class object
        """
        return f"<{self.data['problem']}({self.data['mode']})>"

    def __init__(self, problem_name, run_mode):
        """
            Constructor to initialize the class variables
        """

        # Initializing the problem variables in a dictionary
        self.data = {
            "problem" : problem_name,
            "mode" : run_mode
        }

        # Initialize the Starting conditions for the Central Upwind Scheme to run
        # get the initial conditions and merge them to the class variable dictionary
        initial_conditions = get_initial_conditions(self.data["mode"], self.data["problem"])
        self.data = UTL.merge_dicts(self.data, initial_conditions)

        # Function to initialize the One dimensional grids for the problem
        oned_grids = get_one_dimensional_grids(self.data)
        self.data = UTL.merge_dicts(self.data, oned_grids)

        # Function to initialize the conserved variable grids for the problem
        # initialize the main grid and then extend the boundaries with the given conditions
        conserved_variables = get_conserved_variables(self.data)
        self.data = UTL.merge_dicts(self.data, conserved_variables)

        self.run_cu_partial()

    def run_cu_partial(self) -> None:
        """
            Function to run the Partial Central Upwind Scheme storing the state
            at the first and the last iteration only used for static plots only
        """

        F1,F2,F3,F4,G1,G2,G3,G4 = get_cu_flux(self.data)

    def run_cu_complete(self) -> None:
        """
            Function to run the Complete Central Upwind Scheme storing the state
            at every 5th iteration for animating the evolution
        """


"""
preproc_param.py:  Methods for parametrizing sklearn pre-processing classes
"""

import numpy as np
import sklearn.preprocessing

def preproc_to_param(preproc, preproc_type):
    """
    Extracts the parameters of certain sklearn objects to a dictionary.
    This is used if sklearn objects are serialized, they may not be
    compatible across different versions.  So, instead we convert
    to a parameter dictionary and serialize that.

    Parameters
    ----------
    preproc : sklearn object
        Pre-processor to serialize
    preproc_type : 'StandardScaler', 'OneHotEncoder' or 'MinMaxScaler'
        Type of pre-processing object

    Returns
    -------
    param : dictionary
        Dictionary with the parameters of the object

    """
    param = dict()
    if preproc_type == 'StandardScaler':
        param['mean'] = preproc.mean_
        param['scale'] = preproc.scale_
    elif preproc_type == 'OneHotEncoder':
        param['categories'] = preproc.categories_
    elif preproc_type == 'MinMaxScaler':
        param['data_min'] = preproc.data_min_
        param['data_max'] = preproc.data_max_
    else:
        raise ValueError('Unknown preprocessor %s' % preproc_type)

    return param

def param_to_preproc(param, preproc_type):
    """
    Creates an sklearn pre-processor from a set of saved parameters.
    This is used for de-serializing he object.

    Parameters
    ----------
    param : dictionary
        Dictionary with the parameters of the object
    preproc_type : 'StandardScaler', 'OneHotEncoder' or 'MinMaxScaler'
        Type of pre-processing object

    Returns
    -------
    preproc : sklearn object
        Pre-processor to serialize

    """
    if preproc_type == 'StandardScaler':
        mean = param['mean']
        scale = param['scale']

        # Create ficticious data with that mean and scale
        nsamp = 100
        u = np.linspace(-1,1,nsamp)
        u = u - np.mean(u)
        u = u / np.std(u)
        X = mean[None,:] + u[:,None]*scale[None,:]

        # Create a new scaler and fit it with the fake data to get
        # the same parameters as the old scaler
        p = sklearn.preprocessing.StandardScaler()
        p.fit(X)
    elif preproc_type == 'OneHotEncoder':

        # Create ficticious data with the categories
        cat = param['categories']
        u = cat[0][:,None]

        p = sklearn.preprocessing.OneHotEncoder(sparse=False)
        p.fit(u)

    elif preproc_type == 'MinMaxScaler':
        dmin = param['data_min']
        dmax = param['data_max']
        drange = dmax - dmin

        # Create ficticious data with that mean and scale
        nsamp = 100
        u = np.linspace(0,1,nsamp)
        X = u[:,None]*drange[None,:] + dmin[None,:]

        # Create a new scaler and fit it with the fake data to get
        # the same parameters as the old scaler
        p = sklearn.preprocessing.MinMaxScaler()
        p.fit(X)

    else:
        raise ValueError('Unknown preprocessor %s' % preproc_type)

    return p


from sys import stdin
def sort_value(x):
    return x[1]
case = int(stdin.readline())
while case:
    times = list(stdin.readline().split())
    times.sort()
    sort_times = []
    for idx in range(len(times)):
        hour,minute = map(int, times[idx].split(":"))
        if hour>=12:
            hour -= 12
        degree = 30*hour + 0.5*minute - 6*minute if 30*hour + 0.5*minute> 6*minute else 6*minute-30*hour - 0.5*minute
        if degree>180:
            degree = 360-degree
        sort_times.append((idx, degree))
    sort_times.sort(key=sort_value)
    idx, degree = sort_times[2]
    print(times[idx])
    case -= 1


# sourcery skip: aug-assign, for-index-underscore, merge-list-append, move-assign-in-block

import random
from Card import Card, Deck, Player

#Game Setup

Player1 = Player('Hardik')
Player2 = Player('Jay')

new_deck = Deck()
new_deck.shuffle()
#print(new_deck)

for x in range(26):
    Player1.add_cards(new_deck.deal_one())
    Player2.add_cards(new_deck.deal_one())

Game_ON = True

round = 0

while Game_ON:

    round = round + 1
    print(f'I am in round {round}')

    if len(Player1.all_cards) == 0:
        print('Player1 lost')
        Game_ON = False
        break

    if len(Player2.all_cards) == 0:
        print('Player2 lost')
        Game_ON = False
        break

    Player1_cards = []
    Player2_cards = []

    Player1_cards.append(Player1.remove_one())
    Player2_cards.append(Player2.remove_one())

    at_war = True

    while at_war:

        if Player1_cards[-1].value > Player2_cards[-1].value:
             Player1.add_cards(Player2_cards)
             Player1.add_cards(Player1_cards)
             at_war = False

        elif Player1_cards[-1].value < Player2_cards[-1].value:
             Player2.add_cards(Player2_cards)
             Player2.add_cards(Player1_cards)
             at_war = False

        else:
            print('WAR!')

            if len(Player1.all_cards) < 5:
                print('Player1 lost')
                Game_ON = False
                break

            elif len(Player2.all_cards) < 5:
                print('Player2 lost')
                Game_ON = False
                break

            else:
                for add_new_cards in range(5):
                    Player1.all_cards.append(Player1.remove_one())
                    Player2.all_cards.append(Player1.remove_one())


#!/usr/bin/env python
# -*- coding: utf-8 -*- #
from __future__ import unicode_literals

AUTHOR = 'Matt Spraggs'
SITENAME = 'Matt Spraggs'
SITEURL = ''

PATH = 'content'

TIMEZONE = 'Europe/London'

DEFAULT_LANG = 'en'

# Feed generation is usually not desired when developing
FEED_DOMAIN = SITEURL
CATEGORY_FEED_RSS = 'feeds/{slug}.rss.xml'

# Blogroll
LINKS = (('Pelican', 'http://getpelican.com/'),
         ('Python.org', 'http://python.org/'),
         ('Jinja2', 'http://jinja.pocoo.org/'),
         ('You can modify those links in your config file', '#'),)

# Social widget
SOCIAL = (
    ('linkedin.png', 'https://www.linkedin.com/in/matt-spraggs'),
    ('github.png', 'https://github.com/mspraggs/'),
    ('rss.png', f'{SITEURL}/feeds/matt-spraggs.rss.xml'),
)

SITEMAP = {
    'exclude': ['drafts/'],
}

DEFAULT_PAGINATION = 10
SUMMARY_MAX_LENGTH = 150

# Uncomment following line if you want document-relative URLs when developing
#RELATIVE_URLS = True

THEME = '.'

STRAPLINE = 'Software engineer. Ex-physicist. Funny surname.'

AUTHOR_SAVE_AS = ''

PLUGIN_PATHS = ['plugins']
PLUGINS = [
    'read_more_link',
    'sort_tags',
    'pelican.plugins.sitemap',
]

# "Read more" link configuration
SUMMARY_MAX_LENGTH = 150
READ_MORE_LINK_TEXT = 'Read more'
READ_MORE_LINK_TEMPLATE = (
    '{{ text }}'
)


#!/usr/bin/env python3

import xml.etree.ElementTree as ET
#from xml.etree.ElementTree import tostring
from xml.dom import minidom

cstCDATA:str = '<![CDATA[{0}]]>'
#Surcharge de fontionnalité - CDATA parsing values -> Sample: '<![CDATA[<root><tag>YourValue</tag></root>]]>'
def _escape_cdata(text):
    try:
        if "&" in text:
            text = text.replace("&", "&")
        # if "<" in text:
            # text = text.replace("<", "<")
        # if ">" in text:
            # text = text.replace(">", ">")
        return text
    except TypeError:
        raise TypeError(
            "cannot serialize %r (type %s)" % (text, type(text).__name__)
        )
#ET._escape_cdata = _escape_cdata       #use setCDATA() Method for apply this fonctionality

#Other CDATA function
#def CDATA(text=None):
#    element = ET.Element(CDATA)
#    element.text = text
#    return element
#
#class ElementTreeCDATA(ET.ElementTree):
#    def _write(self, file, node, encoding, namespaces):
#        if node.tag is CDATA:
#            text = node.text.encode(encoding)
#            file.write("\n<![CDATA[%s]]>\n" % text)
#        else:
#            ET.ElementTree._write(self, file, node, encoding, namespaces)

class Xml:

    def __init__(self)-> None:
        self.oRoot:ET.Element = None
        return

    @property
    def root(self):
        return self.oRoot

    #Define context for use CDATA in your XML files
    def setCDATA(self) -> None:
        ET._escape_cdata = _escape_cdata
        return

    #Method for convert string in CDATA format
    #  sample: in = '<root version="1""><content>value</content></root>' --> out = "'<![CDATA[<root version="1""><content>value</content></root>]]>'"
    def letCDATA(self, sValue:str) -> None:
        self.setCDATA()                         #Swap context in CDATA mode
        sCDATA = cstCDATA.format(sValue)
        return sCDATA

    #Method for get string in CDATA format
    #  sample: in = '<![CDATA[<root version="1""><content>value</content></root>]]>' --> out = '<root version="1""><content>value</content></root>'
    def getCDATA(self, sCDATA:str) -> str:
        sValue:str = sCDATA
        if sCDATA[0:9]==cstCDATA[0:9] and sCDATA[-3:]==cstCDATA[-3:]:
            sValue = sCDATA[10:-4]
        return sValue

    def dump(self):
        return ET.dump(self.oRoot)

    def toString(self, indent="") -> str:
        if indent:
            return minidom.parseString(ET.tostring(self.oRoot)).toprettyxml(indent=indent)
        else:
            return ET.tostring(self.oRoot, method='xml')

    def createRoot(self, sTagName:str, sXmlns:str=None, sId:str=None, sValue:str=None):
        self.oRoot = ET.Element(sTagName)
        if sXmlns:
            self.oRoot.set("xmlns", sXmlns)
        if sId:
            self.oRoot.set("id", sId)
        if sValue:
            self.oRoot.text = sValue
        return self.oRoot

    def addAttrib(self, oTag, sAttName:str, sValue:str=None):
        if sAttName:
            oTag.set(sAttName, sValue)
        return

    def addTag(self, oParent, sTagName:str, sXmlns:str=None, sId:str=None, sValue:str=None):
        #if sValue and sValue[0:9]=="<![CDATA[":
        #    oTag = CDATA(sValue)
        #    oParent.append(oTag)
        #else:
        oTag = ET.SubElement(oParent, sTagName)
        if sXmlns:
            oTag.set("xmlns", sXmlns)
        if sId:
            oTag.set("id", sId)
        if sValue:
            oTag.text = sValue
        return oTag

    def addComment(self, oParent, sValue:str=None):
        if sValue:
            oTag = ET.Comment(sValue)
            #oParent.insert(1, oTag)
            oParent.append(oTag)
        return

    def write(self, sFileName:str, sEncoding:str="utf-8", bExpand=0):
        if bExpand:
            oXmlStr:str = self.toString("\t")
            with open(sFileName, "w", encoding=sEncoding) as file:
                file.write(oXmlStr)
        else:
            oTree = ET.ElementTree(self.oRoot)
            oTree.write(sFileName, encoding=sEncoding, xml_declaration=True)
        return

if __name__ == '__main__':
    sPath = "../../output/Tests/"
    oXml:Xml = Xml()
    sXmlns = "www:yournamespace.com"
    oRoot = oXml.createRoot("kml", sXmlns=sXmlns)
    oXml.addAttrib(oRoot, "xmlns:xsi", "http://www.w3.org/2001/XMLSchema-instance")
    oXml.addAttrib(oRoot, "xsi:schemaLocation", sXmlns + " http://yournamespace.com/1.1.0/yourschemer.xsd")
    oDoc = oXml.addTag(oRoot, "doc", sId="5612a")
    oXml.addAttrib(oDoc, "att1", "value1")
    oXml.addAttrib(oDoc, "att2", "value2")
    oXml.addTag(oDoc, "name", sId="123", sValue="Frist")
    oXml.addTag(oDoc, "name", sId="456").text = "Two"
    oXml.write(sPath + "__Test.xml", bExpand=1)


#!python2
# Tui Popenoe
# Challenge36E.py - 1000 Lockers

def one_thousand_lockers():
    lockers = [False] * 1000
    for i in range(1, 1000):
        for j in range(1, 1000):
            if i % j == 0:
                lockers[i] = not lockers[i]
    return (lockers.count(True),
        [x for x in range(len(lockers)) if lockers[x] == True])

def main():
    print(one_thousand_lockers())

if __name__ == '__main__':
    main()