from struct import pack,unpack

class DDS_HEADER:
    def __init__(self,tex):
        self.dwMagic=b"DDS "
        self.dwSize=124
        self.dwFlags=0x1|0x2|0x4|0x1000
        if tex.type==2: self.dwFlags|=0x800000
        if tex.numMipMaps>1: self.dwFlags|=0x20000
        self.dwHeight=tex.height
        self.dwWidth=tex.width
        self.dwPitchOrLinearSize=0
        self.dwDepth=tex.depth if tex.type==2 else 1
        self.dwMipMapCount=tex.numMipMaps
        self.dwReserved1=bytes(11*0x04)
        self.ddspf=DDS_PIXELFORMAT(tex)
        self.dwCaps=0x1000
        if tex.type in [1,2]: self.dwCaps|=0x8
        if tex.numMipMaps>1: self.dwCaps|=0x8|0x400000
        self.dwCaps2=0
        if tex.type==1:
            #Cubemap
            self.dwCaps2|=0x200
            for i in range(6):
                self.dwCaps2|=(1<<(10+i))
        elif tex.type==2:
            #Volume texture
            self.dwCaps2|=0x200000
        self.dwCaps3=0
        self.dwCaps4=0
        self.dwReserved2=0

    def encode(self):
        data=pack("<4s7I44s",
                    self.dwMagic,
                    self.dwSize,
                    self.dwFlags,
                    self.dwHeight,
                    self.dwWidth,
                    self.dwPitchOrLinearSize,
                    self.dwDepth,
                    self.dwMipMapCount,
                    self.dwReserved1)
        data+=self.ddspf.encode()
        data+=pack("<5I",
                    self.dwCaps,
                    self.dwCaps2,
                    self.dwCaps3,
                    self.dwCaps4,
                    self.dwReserved2)

        return data

class DDS_PIXELFORMAT:
    def __init__(self,tex):
        self.dwSize=32
        enum=getFormatEnum(tex.version)
        values=remapFormat(enum,tex.format)
        self.dwFlags=values[0]

        if self.dwFlags & 0x04:
            self.dwFourCC=values[1]
            self.dwRGBBitCount=0
            self.dwRBitMask=0
            self.dwGBitMask=0
            self.dwBBitMask=0
            self.dwABitMask=0
        else:
            self.dwFourCC=bytes(4)
            self.dwRGBBitCount=values[1]
            self.dwRBitMask=values[2]
            self.dwGBitMask=values[3]
            self.dwBBitMask=values[4]
            self.dwABitMask=values[5]

    def encode(self):
        return pack("<2I4s5I",
                    self.dwSize,
                    self.dwFlags,
                    self.dwFourCC,
                    self.dwRGBBitCount,
                    self.dwRBitMask,
                    self.dwGBitMask,
                    self.dwBBitMask,
                    self.dwABitMask)

def getFormatEnum(version):
    if version==0x0a:
        return TextureFormat_v10
    elif version==0x6e:
        return TextureFormat_v110
    else:
        return None

#Info on DDS_PIXELFORMAT struct presets taken from here:
# https://github.com/microsoft/DirectXTex/blob/master/DirectXTex/DirectXTexDDS.cpp
# https://github.com/microsoft/DirectXTex/blob/master/DirectXTex/DDS.h
def remapFormat(fmt,val):
    formatMap = {
        fmt.TextureFormat_DXT1:             (0x04,b"DXT1"),
        fmt.TextureFormat_DXT1A:            (0x04,b"DXT1"),
        fmt.TextureFormat_DXT3:             (0x04,b"DXT3"),
        fmt.TextureFormat_DXT5:             (0x04,b"DXT5"),
        fmt.TextureFormat_DXT5A:            (0x04,b"ATI1"),
        fmt.TextureFormat_DXN:              (0x04,b"ATI2"),
        fmt.TextureFormat_RGB565:           (0x40,16,0xf800,0x07e0,0x001f,0),
        fmt.TextureFormat_RGB888:           (0x40,24,0xff0000,0x00ff00,0x0000ff,0),
        fmt.TextureFormat_ARGB1555:         (0x41,16,0x7c00,0x03e0,0x001f,0x8000),
        fmt.TextureFormat_ARGB4444:         (0x41,16,0x0f00,0x00f0,0x000f,0xf000),
        fmt.TextureFormat_ARGB8888:         (0x41,32,0x00ff0000,0x0000ff00,0x000000ff,0xff000000),
        fmt.TextureFormat_L8:               (0x20000,8,0xff,0,0,0),
        fmt.TextureFormat_L16:              (0x20000,16,0xffff,0,0,0),
        fmt.TextureFormat_ABGR16:           (0x04,b"\x24\0\0\0"),
        fmt.TextureFormat_ABGR16F:          (0x04,b"\x71\0\0\0"),
        fmt.TextureFormat_ABGR32F:          (0x04,b"\x74\0\0\0"),
        fmt.TextureFormat_NormalDXN:        (0x04,b"ATI2"),
        fmt.TextureFormat_NormalDXT1:       (0x04,b"DXT1"),
        fmt.TextureFormat_NormalDXT5:       (0x04,b"DXT5"),
        fmt.TextureFormat_NormalDXT5RGA:    (0x04,b"DXT5"),
    }

    if val not in formatMap or val==0xFFFFFFFF:
        return None

    return formatMap[val]

#Standard FB2 list, found in BF3 debug strings
class TextureFormat_v10:
    TextureFormat_DXT1 = 0x0
    TextureFormat_DXT3 = 0x1
    TextureFormat_DXT5 = 0x2
    TextureFormat_DXT5A = 0x3
    TextureFormat_DXN = 0x4
    TextureFormat_RGB565 = 0x5
    TextureFormat_RGB888 = 0x6
    TextureFormat_ARGB1555 = 0x7
    TextureFormat_ARGB4444 = 0x8
    TextureFormat_ARGB8888 = 0x9
    TextureFormat_L8 = 0x0A
    TextureFormat_L16 = 0x0B
    TextureFormat_ABGR16 = 0x0C
    TextureFormat_ABGR16F = 0x0D
    TextureFormat_ABGR32F = 0x0E
    TextureFormat_R16F = 0x0F
    TextureFormat_R32F = 0x10
    TextureFormat_NormalDXN = 0x11
    TextureFormat_NormalDXT1 = 0x12
    TextureFormat_NormalDXT5 = 0x13
    TextureFormat_NormalDXT5RGA = 0x14
    TextureFormat_RG8 = 0x15
    TextureFormat_GR16 = 0x16
    TextureFormat_GR16F = 0x17
    TextureFormat_D16 = 0x18
    TextureFormat_D24S8 = 0x19
    TextureFormat_D24FS8 = 0x1A
    TextureFormat_D32F = 0x1B
    TextureFormat_ABGR32 = 0x1C
    TextureFormat_GR32F = 0x1D
    TextureFormat_A2R10G10B10 = 0x1E

    TextureFormat_DXT1A = 0xFFFFFFFF

    def __init__(self):
        pass

#Found in MOH:WF
class TextureFormat_v110:
    TextureFormat_DXT1 = 0x0
    TextureFormat_DXT1A = 0x1
    TextureFormat_DXT3 = 0x2
    TextureFormat_DXT5 = 0x3
    TextureFormat_DXT5A = 0x4
    TextureFormat_DXN = 0x5
    TextureFormat_RGB565 = 0x6
    TextureFormat_RGB888 = 0x7
    TextureFormat_ARGB1555 = 0x8
    TextureFormat_ARGB4444 = 0x9
    TextureFormat_ARGB8888 = 0x0A
    TextureFormat_L8 = 0x0B
    TextureFormat_L16 = 0x0C
    TextureFormat_ABGR16 = 0x0D
    TextureFormat_ABGR16F = 0x0E
    TextureFormat_ABGR32F = 0x0F
    TextureFormat_R16F = 0x10
    TextureFormat_R32F = 0x11
    TextureFormat_NormalDXN = 0x12
    TextureFormat_NormalDXT1 = 0x13
    TextureFormat_NormalDXT5 = 0x14
    TextureFormat_NormalDXT5RGA = 0x15
    TextureFormat_RG8 = 0x16
    TextureFormat_GR16 = 0x17
    TextureFormat_GR16F = 0x18
    TextureFormat_D16 = 0x19
    TextureFormat_D24S8 = 0x1A
    TextureFormat_D24FS8 = 0x1B
    TextureFormat_D32F = 0x1C
    TextureFormat_ABGR32 = 0x1D
    TextureFormat_GR32F = 0x1E
    TextureFormat_A2R10G10B10 = 0x1F

    def __init__(self):
        pass


from typing import List

class Solution:
    """"""

    """my dfs sol, modified from qishi"""
    def subsets(self, nums: List[int]) -> List[List[int]]:
        ans = []

        def dfs(path, idx):
            ans.append(path.copy())
            for i in range(idx, len(nums)):
                dfs(path + [nums[i]], i + 1)

        dfs([], 0)
        return ans

    """my recursive sol, 2nd attempt"""
    def subsets(self, nums: List[int]) -> List[List[int]]:

        if not nums:
            return [[]]

        sub = self.subsets(nums[1:])
        return [[nums[0]] + s for s in sub] + sub

    """my iterative sol, 2nd attempt"""
    def subsets(self, nums: List[int]) -> List[List[int]]:

        ans = [[]]

        for num in nums:
            ans += [[num] + sub for sub in ans]

        return ans

    """recursion answer, time n * 2**n"""
    def subsets(self, nums: List[int]) -> List[List[int]]:
        output = [[]]

        for num in nums:
            output += [curr + [num] for curr in output]

        return output

    """binary solution"""
    # def subsets(self, nums: List[int]) -> List[List[int]]:
    #     n = len(nums)
    #     output = []
    #
    #     for i in range(2 ** n, 2 ** (n + 1)):
    #         # generate bitmask, from 0..00 to 1..11
    #         bitmask = bin(i)[3:]
    #
    #         # append subset corresponding to that bitmask
    #         output.append([nums[j] for j in range(n) if bitmask[j] == '1'])
    #
    #     return output


import statapp
import os
import json
import datetime
import numpy as np
import pandas as pd
from scipy.stats import rankdata

class NumpyEncoder(json.JSONEncoder):
    """Special json encoder for numpy types. Useful for logging numpy arrays.
    """
    def default(self, obj):
        if isinstance(obj, (np.int_, np.intc, np.intp, np.int8,
            np.int16, np.int32, np.int64, np.uint8,
            np.uint16, np.uint32, np.uint64)):
            return int(obj)
        elif isinstance(obj, (np.float_, np.float16, np.float32,
            np.float64)):
            return float(obj)
        elif isinstance(obj,(np.ndarray,)): #### This is the fix
            return obj.tolist()
        return json.JSONEncoder.default(self, obj)

def add_to_log(entry, path=None, auto_add=["id", "date"]):
    """Add to the training log file the specified entry.
    By default, adds a few automatically generated fields to the entry.

    Args:
        entry (dict): Entry to add to the log.
        path (str): Path to the log file.
            Default: "folder_containing_statapp_package/logs/tensorflow_transformer/log.json"
        auto_add (list of str): Keys to automatically add to the entry before logging.
            Supported keys:
                "id": A number equal to 1 + the maximum id in the current log.
                "date": A string representing the current date and time.
            Default: ["id", "date"].
        add_id (bool): Whether to add "id" key to entry.
            Default: True.
    """
    # Implement default path
    if path is None:
        path = os.path.join(os.path.dirname(statapp.__name__), "logs",  "tensorflow_transformer", "log.json")

    # Read log file
    with open(path, "r") as file:
        log = json.load(file)

    # Add auto fields
    if "id" in auto_add:
        current_max_id = max([el.get("id", 0) for el in log])
        entry["id"] = current_max_id + 1
    if "date" in auto_add:
        entry["date"] = datetime.datetime.today().strftime("%Y-%m-%dT%H:%M:%S")

    log.append(entry)

    # Write log file
    with open(path, "w") as file:
        json.dump(log, file, indent=4, sort_keys=True, cls=NumpyEncoder)

def pad_or_cut(seq, seq_length, padder=[0]):
    """Pad or cut a sequence to the specified length.
    Typically used for lists or strings.

    Args:
        seq (iterable): Sequence to pad (if too short) or cut (if too long).
        seq_length (int): Length to pad or cut the sequence to.
        padder: Object to use for padding.
            Must support addition with original sequence and multiplication by an int.
            Default: [0]

    Returns:
        iterable: padded or cut sequence of length seq_length.

    Examples:
        >>> pad_or_cut([1, 2, 3], 4, [0])
        [1, 2, 3, 0]
        >>> pad_or_cut([1, 2, 3], 2, [0])
        [1, 2]
        >>> pad_or_cut("abc", 5, ".")
        "abc.."
    """
    return seq[:seq_length] + padder * max(seq_length - len(seq), 0)

def array_to_multi_indexed_series(array, names=None, val_name=None, number_from_1=False):
    """Convert a numpy array with an arbitrary number of dimensions to a pd.Series object with
    a MultiIndex representing all the dimensions of the input array. Can be easily reshaped into a
    DataFrame with desired columns using reset_index.

    Args:
        array (np.array): Multi-dimensional array to turn into a Series.
        names (list of strings): Names of the created index levels.
            If not None, must be of the same length as the number of dimensions of the input array.
            If None, leave unnamed.
            Default: None.
        val_name (str): Name of the returned Series.
            Will be the name of the value column if reset_index is used on the returned Series.
            If None, leave unnamed.
            Default: None.
        number_from_1 (bool): Whether to number the index starting from 1 instead of 0.
            This may make it more human-readable at the cost of losing indexing equivalence with the
            input array.
            Default: False.

    Examples:
        >>> a = np.array([[0.1, 0.9], [0.5, 0.5]])
        >>> array_to_multi_indexed_series(a, ["f", "s"], "val")
        f  s
        0  0    0.1
           1    0.9
        1  0    0.5
           1    0.5
       Name: val, dtype: float64

       >>> a = np.random.randn(2, 2, 2, 2)
       >>> a[0, 0, 1, 1]
       2.1682415236887196
       >>> array_to_multi_indexed_series(a)[0, 0, 1, 1]
       2.1682415236887196
    """
    if names is not None:
        assert len(names) == len(array.shape)

    start = 1 if number_from_1 else 0

    iterables = [range(start, dim+start) for dim in array.shape]
    index = pd.MultiIndex.from_product(iterables, names=names)

    srs = pd.Series(array.reshape(-1), index=index)

    if val_name is not None:
        srs = srs.rename(val_name)

    return srs

def survival_function(srs):
    """Return the survival probabilities of a data series.

    Args:
        srs (array-like): Series to analyze. Index is irrelevant

    Returns:
        pd.Series: Index: Ordered unique values in the original series.
                   Values: Probability of being >= corresponding index value.
    """
    srs = pd.Series(srs).dropna()

    n = len(srs)
    ranks = rankdata(srs, method="min") - 1
    survival = 1 - (ranks / (n))

    survival = pd.Series(survival, index=srs).sort_index()
    survival = survival.loc[~survival.index.duplicated()]
    return survival


from apt import utils
from pathlib import Path
import filecmp

def test_merge_static_column_file(tmp_path):
    fixture_dir = Path(
        __name__).parents[0] / 'fixture_merge_static_column_file'
    default_file = fixture_dir / 'default.tsv'
    mod_file = fixture_dir / 'mod.tsv'
    expected_file = fixture_dir / 'merged.tsv'
    expected_filtered_file = fixture_dir / 'merged_filtered.tsv'

    actual_file = tmp_path / 'merged.tsv'

    utils.merge_static_column_file(
        default_file,
        mod_file,
        actual_file,
    )

    assert filecmp.cmp(expected_file, actual_file, shallow=False)

    actual_filtered_file = tmp_path / 'merged_filtered.tsv'

    utils.merge_static_column_file(
        default_file,
        mod_file,
        actual_filtered_file,
        target_probesets={'AX-200', 'AX-300'},
    )
    assert filecmp.cmp(
        expected_filtered_file,
        actual_filtered_file,
        shallow=False,
    )


import bpy

import bmesh
from mathutils import *
from mathutils.bvhtree import BVHTree

import json

# bpy.ops.wm.open_mainfile(filepath="D:\\blender-2-minecraft\\sample-scene.blend")
OUTPUTFILE_PATH = "D:\\blender-2-minecraft\\output-data.json"

MC_CUBE_NAME = "mc-cube"

RANGE_LIMIT_X = 32
RANGE_LIMIT_Y = 45
RANGE_LIMIT_Z = 20

D = bpy.data
C = bpy.context

# todo this will eventually be a list of objects to test the cube against.

# I need to know:
#   how to move or set the object position
#   how to get the vertices of the the mesh
#   does moving the object position change the postition
#   of the vertices - or do we need some kind of local
#   to world transform?

# 50 * .6 is 30m x3  in Blender

objsToExport = []

for o in D.objects:
    if o.name.startswith("mc-cube") is False and o.type == 'MESH':
        target_obj = D.objects[o.name]
        target_mesh = target_obj.data

        target_bmesh = bmesh.new()
        target_bmesh.from_mesh(target_mesh)
        target_bmesh.transform(target_obj.matrix_world)
        target_bvhtree = BVHTree.FromBMesh(target_bmesh)

        objsToExport.append(
            {'bMesh': target_bvhtree, 'mat': target_obj.material_slots[0].name})

cubes = []

for b in objsToExport:
    for z in range(0, RANGE_LIMIT_Z):
        print(b, z)
        for y in range(0, RANGE_LIMIT_Y):
            for x in range(0, RANGE_LIMIT_X):
                # find the mc-cube object
                mc_id = D.objects.find(MC_CUBE_NAME)
                mc_object = D.objects[MC_CUBE_NAME]
                # I think the first data block is the mesh - for mesh obj
                mc_mesh = mc_object.data

                mc_object.location.x = x
                mc_object.location.y = y
                mc_object.location.z = z

                layer = bpy.context.view_layer
                layer.update()

                mc_bmesh = bmesh.new()
                mc_bmesh.from_mesh(mc_mesh)
                mc_bmesh.transform(mc_object.matrix_world)

                mc_bvhtree = BVHTree.FromBMesh(mc_bmesh)

                intersection_bmesh = mc_bvhtree.overlap(b['bMesh'])

                if intersection_bmesh:

                    # count the number of uniqure cube verts intersecting
                    v = {}
                    for i in intersection_bmesh:
                        v[i[0]] = 1
                    n = len(v)

                    mat = b['mat']
                    cubes.append({'x': x, 'y': y, 'z': z, 'mat': mat,
                                  'overlap': intersection_bmesh is not None, 'vCount': n})
                else:
                    continue

            mc_object.location.x = 0
            mc_object.location.y = 0
            mc_object.location.z = 0

f = open(OUTPUTFILE_PATH, "w")
f.write(json.dumps(cubes))
f.close()


DATA = []
with open('problem011_data.txt') as in_file:
    for line in in_file.readlines():
        DATA.append([int(t, 10) for t in line[:-1].split(' ')])
H, W = len(DATA), len(DATA[0])

def get_max_product(row, column):
    east, southeast, south, southwest = 1, 1, 1, 1
    for i in range(4):
        if column <= W - 4:
            east *= DATA[row][column + i]
        if column <= W - 4 and row <= H - 4:
            southeast *= DATA[row + i][column + i]
        if row <= H - 4:
            south *= DATA[row + i][column]
        if row <= H - 4 and column >= 4:
            southwest *= DATA[row + i][column - i]
    return max(east, southeast, south, southwest)

max_product = 0
for r in range(H):
    for c in range(W):
        max_product = max(max_product, get_max_product(r, c))
print(max_product)


# https://leetcode.com/problems/add-two-numbers/

# Definition for singly-linked list.
# class ListNode(object):
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution(object):
    def addTwoNumbers(self, l1, l2):
        """
        :type l1: ListNode
        :type l2: ListNode
        :rtype: ListNode
        """
        n1 = ""
        n2 = ""
        a1 = l1
        a2 = l2
        while(a1 != None):
            n1 += str(a1.val)
            a1 = a1.next
        # print(n1)
        while(a2 != None):
            n2 += str(a2.val)
            a2 = a2.next

        n1 = n1[::-1]
        n2 = n2[::-1]
        add = int(n1) +int(n2)
        add2 = str(add)[::-1]
        k = ListNode(0)
        l3 = k
        for i in range(len(add2)):
            l3.next = ListNode(int(add2[i]))
            l3 = l3.next

        return k.next


from django.http import HttpResponse
from functools import wraps

#ACÁ GESTIONAMOS QUE SI EXISTE USER_INFO EN LA SESIÓN SE ME PERMITE EL ACCESO A LA VISTA
#DE LO CONTRARIO SE MUESTRA UN MENSAJE DE ERROR..

#Luego el decorators lo aplicamos en las vistas que deseamos proteger en nuestro caso, son
#las vistas privadas de cada usuario, ya que ahi estan sus datos personales y etc.
def user_info_required(view_func):
    @wraps(view_func)
    def _wrapped_view(request, *args, **kwargs):
        if 'user_info' in request.session:
            return view_func(request, *args, **kwargs)
        else:
            return HttpResponse("Usted no está logueado, por tanto no puede acceder a esta página", status=401)  # Puedes personalizar el mensaje y el código de estado según tus necesidades
    return _wrapped_view


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Stack GRID2D results and plot them over a given time window.
"""

import datetime
import glob
import numpy as np
import math
import matplotlib.pyplot as plt
from bisect import bisect_left

def takeClosest(myList, myNumber):
    """
    Assumes myList is sorted. Returns closest value to myNumber.

    If two numbers are equally close, return the smallest number.
    From Lauritz V. Thaulow on stackoverflow
    """
    pos = bisect_left(myList, myNumber)
    if pos == 0:
        return myList[0], 0
    if pos == len(myList):
        return myList[-1], -1
    before = myList[pos - 1]
    after = myList[pos]
    if after - myNumber < myNumber - before:
       return after, pos
    else:
       return before, pos - 1

def distance(p1, p2):

    '''
    Calculate 2D distance between two points
    '''

    distance = math.sqrt((p2[0] - p1[0])**2 + (p2[1] - p1[1])**2)

    return distance

# Give parameters

## Numpy grid output location

event_output_directory = '/home/sam/EVENTS_IT3/TYPE_A/4/'

## Start and end dates for processing of day-long seismic streams

start_year = '2016'
start_month = '01'
start_day = '04'
start_hour = '00'

end_year = '2016'
end_month = '08'
end_day = '04'
end_hour = '23'

min_date = datetime.datetime.strptime(start_year + '-' + start_month + '-' + start_day + 'T' + start_hour,
                                      '%Y-%m-%dT%H')

max_date = datetime.datetime.strptime(end_year + '-' + end_month + '-' + end_day + 'T' + end_hour,
                                      '%Y-%m-%dT%H')

## Station positions

station_positions = [[1374.062, 5164.009, 0.821],
                     [1374.498, 5166.080, 0.904],
                     [1374.261, 5163.408, 0.816],
                     [1374.783, 5165.049, 0.857],
                     [1373.533, 5163.353, 0.801],
                     [1373.689, 5165.150, 0.857]]

## Grid shape

xmin = 1373.0
xmax = 1375.0
ymin = 5163.0
ymax = 5166.5
xstep = 0.05
ystep = 0.05

# Amount to shift position along bearing line every iteration
# Note: finer amounts are better,

step = 0.01

## Location and uncertainty details

long_axis_direction = [0.1995, 0.9799]
bearing = math.atan(long_axis_direction[0] / long_axis_direction[1])
delta_E = math.sin(bearing) * step
delta_N = math.cos(bearing) * step

grid_files = glob.glob(event_output_directory + '*.xcorrvaluegrid.npy')
grid_files.sort()

gridx, gridy = np.meshgrid(np.linspace(xmin, xmax, (xmax - xmin + 1) / xstep), np.linspace(ymin, ymax, (ymax - ymin + 1) / ystep))

# Create coordinate axis lists for matching values to

xvals = gridx[0].tolist()
yvals  = []
for x in gridy:
    yvals.append(x[0])

grid_values = np.zeros(gridx.shape)

for d in range(int(math.ceil((max_date - min_date).total_seconds()/86400))):

    locations = []
    last_date = 0

    new_min_date = min_date + datetime.timedelta(days = d)
    new_max_date = min_date + datetime.timedelta(days = d + 1)

    for grid_file in grid_files:

        # Apply date controls

        date = datetime.datetime.strptime(grid_file.split('/')[-1][:19], '%Y-%m-%dT%H:%M:%S')

        if new_min_date <= date <= new_max_date:
            pass
        elif date > new_max_date:
            break
        else:
            continue

#        last_date = date

        xcorr_value_grid = np.load(grid_file)

        max_value = np.max(xcorr_value_grid)
        max_value_indices = np.where(xcorr_value_grid == xcorr_value_grid.max())

        # Find location of max value (by convention, if two values are the same
        # take the one farthest from the origin)

        E = gridx[max_value_indices][-1]
        N = gridy[max_value_indices][-1]

        E_1 = E
        E_2 = E
        N_1 = N
        N_2 = N

        transect_data = [[max_value, E, N]]

        c = -1
        while (xmin <= E_1 <= xmax) and (ymin <= N_1 <= ymax):
            c += 1

            # shift position forward and round to nearest grid cell

            E_1 = round(float(E + c * delta_E) / step) * step
            N_1 = round(float(N + c * delta_N) / step) * step

            # get the value for new coords from the xcorr value grid

            a = takeClosest(xvals, E_1)[-1]
            b = takeClosest(yvals, N_1)[-1]

            try:

                transect_data.append([xcorr_value_grid[b][a], xvals[a], yvals[b]])

            except:

                break

        # The same, but backwards

        c = 0
        while (xmin <= E_2 <= xmax) and (ymin <= N_2 <= ymax):
            c += 1

            E_2 = round(float(E - c * delta_E) / step) * step
            N_2 = round(float(N - c * delta_N) / step) * step
            a = takeClosest(xvals, E_2)[-1]
            b = takeClosest(yvals, N_2)[-1]

            try:

                transect_data.insert(0, [xcorr_value_grid[b][a], xvals[a], yvals[b]])

            except:

                break

        # Remove any duplicate values

        unique_transect_data = []

        for i in range(len(transect_data)):
            try:
                unique_transect_data.index(transect_data[i][1])
                unique_transect_data.index(transect_data[i][2])
            except:
                unique_transect_data.append(transect_data[i])

        transect_data = unique_transect_data

        # Calculate the second derivative of the transect values

        transect_second_derivative = []

        if len(transect_data) > 1:

            for i in range(1, len(transect_data) - 1):

                # Calculate the second derivative using the second order
                # central difference and taking the separation as the mean
                # separation between the three points on the transect

                transect_second_derivative.append((abs(transect_data[i + 1][0] - 2 *
                               transect_data[i][0] + transect_data[i - 1][0])
                / (np.mean([distance(transect_data[i][1:], transect_data[i - 1][1:]),
                            distance(transect_data[i][1:], transect_data[i + 1][1:])]))))

        # Handle edge points

        transect_second_derivative.insert(0, 0)
        transect_second_derivative.append(0)

        # Find plateau limits

        if len(transect_second_derivative) >= 7:

        # NOTE: this requirement means events with max values near the
        # grid edge do not produce a location. If the grid edge are outside
        # the seismic network, this is OK as events that locate outside the
        # network are generally network-external and thus any derived location
        # will be incorrect due to limitations in the cross-correlation method.

        # First find the points of max slope closest to the plateau centre

            plateau_edge_indices = []
            first_slope_max = None
            second_slope_max = None
            for i in range(len(transect_data)):
                if (transect_data[i][1] == E) and (transect_data[i][2] == N):
                    transect_centre_index = i

            for i in range(len(transect_second_derivative)):

                # Move outward from the transect centre

                a = transect_centre_index - i
                b = transect_centre_index + i

                try:
                    if ((transect_second_derivative[a + 1] < transect_second_derivative[a] > transect_second_derivative[a - 1]) and
                        (a >= 0)):
                        if not first_slope_max:
                            first_slope_max = True
                            plateau_edge_indices.append(a)
                except:
                    pass

                try:
                    if ((transect_second_derivative[b - 1] < transect_second_derivative[b] > transect_second_derivative[b + 1]) and
                        (b >= 0)):
                        if not second_slope_max:
                            second_slope_max = True
                            plateau_edge_indices.append(b)
                except:
                    pass

            # Define the plateau as all transect_data within the plateau edge indices

    #        if len(plateau_edge_indices) == 1:
    #
    #            # If there is only one edge, assume the other is at the same distance
    #
    #            plateau_edge_indices = [transect_centre_index - abs(transect_centre_index - plateau_edge_indices[0]),
    #                                    transect_centre_index + abs(transect_centre_index - plateau_edge_indices[0])]
    #
    #            plateau_edge_indices.sort()
    #
    #            if (plateau_edge_indices[0]) < 0:
    #                plateau_edge_indices[0] = 0
    #
    #            if (plateau_edge_indices[1] > len(transect_data) - 1):
    #                plateau_edge_indices[1] = len(transect_data) - 1

            try:

                plateau_data = transect_data[min(plateau_edge_indices): max(plateau_edge_indices)]

            except:

                # This fails when no plateau edge can be defined

                continue

            # Best location is taken as the centre of the plateau
            # with uncertainty as the half width of the plateau

            try:
                # Let all single-edged (or no-edged) plateaus fail

                if plateau_edge_indices[0] != plateau_edge_indices[1]:

                    location = transect_data[int(round(np.mean(plateau_edge_indices)))][1:]
                    uncertainty = distance(transect_data[min(plateau_edge_indices)][1:],
                                        transect_data[max(plateau_edge_indices)][1:]) / 2

                else:

                    # Uncertainty is over the grid cell itself

                    location = [E, N]

                    uncertainty = distance(transect_data[min(plateau_edge_indices) - 1][1:],
                                         transect_data[max(plateau_edge_indices) + 1][1:]) / 4

                locations.append([location[0], location[1], uncertainty, max_value])

            except:

                continue

    #        print(E, N)
    #        print(location, uncertainty, max_value)

#            if max_value < 0.7: continue

            plt.imshow(xcorr_value_grid, extent = [xmin, xmax, ymin, ymax], origin = 'lower')
            plt.colorbar()
            for station_position in station_positions:
                plt.scatter(station_position[0], station_position[1], color = 'k')
            plt.xlim(xmin, xmax)
            plt.ylim(ymin, ymax)
            for data in transect_data[min(plateau_edge_indices) : max(plateau_edge_indices)]:
                plt.scatter(data[1], data[2], color ='green')
            plt.scatter(E, N, color = 'purple')
            plt.scatter(location[0], location[1], color = 'red')
            plt.savefig(grid_file[:-4] + '.png', format='png')
            plt.close()

        #    date = datetime.datetime.strptime(grid_file.split('/')[-1][:13], '%Y-%m-%dT%H')
        #    if min_date <= date <= max_date:
        #
        #        xcorr_value_grid = np.load(grid_file)
        #
        #        if np.max(xcorr_value_grid) >= 0:
        #
        #            for i in range(len(xcorr_value_grid)):
        #                for j in range(len(xcorr_value_grid[i])):
        #
        #                        grid_values[i][j] += xcorr_value_grid[i][j]

        #plt.contour(grid_values)
        #plt.imshow(grid_values, extent = [xmin, xmax, ymin, ymax])
        #plt.colorbar()
        #for station_position in station_positions:
        #    plt.scatter(station_position[0], station_position[1], color = 'k')

        #plt.xlim(xmin, xmax)
        #plt.ylim(ymin, ymax)
        #plt.show()

    # Save data in csv form

    outfile = open('location_file.csv', 'w')
    outfile = open('location_file.csv', 'a')
    for location in locations:
        outfile.write(str(location[0]) + ',' + str(location[1]) + ',' + str(location[2]) + ',' + str(location[3]) + '\n')

    # Accumulate events in cells

    total_num = 0
    location_grid = [[0 for x in range(len(xvals))] for y in range(len(yvals))]
    for y in yvals:
        for x in xvals:
            for location in locations:
                if (location[0] == x) and (location[1] == y):
                    # X-corr value filtering
#                    if location[3] < 0.7: continue
                    total_num += 1
                    location_grid[yvals.index(y)][xvals.index(x)] += 1

#    print(last_date, total_num)

#    if last_date == 0: continue

    outfile = open(str(last_date) + '_location_grid.csv', 'w')
    outfile = open(str(last_date) + '_location_grid.csv', 'a')
    for y in yvals:
        for x in xvals:
            outfile.write(str(x) + ',' + str(y) +',' + str(location_grid[yvals.index(y)][xvals.index(x)]) + '\n')


from behave import given, then, when
from helper_functions import *

'''
TEST_DATA_PROJECT = {
    "title": "Test Project Title",
    "completed": False,
    "active": True,
    "description": "Test Project description",
}
'''

@given("The valid input for the id of a project")
def step_valid_project_id_to_amend(context):
    context.data = TEST_DATA_PROJECT
    context.URL = "projects"

    context.response = sendRequest("POST", context.URL, data=context.data, return_response_if_error=True)

    context.id = context.response.json()["id"]
    context.URL = f"projects/{context.id}"

@given("The id of a project instance that doesn't exist")
def step_invalid_project_id_to_amend(context):
    context.id = len(projectsGetEntries("projects"))+1
    context.URL = f"projects/{context.id}"

@when("I amend the body of the instance of the project with a PUT request")
def step_amend_project_with_put(context):
    projects_data_with_completed_and_active_status_and_description_amended = {
        "title": "New Project Title",
        "completed": True,
        "active": False,
        "description": "This is the description of a completed Test Project replaced with a PUT request",
    }

    context.response = sendRequest("PUT", context.URL, data=projects_data_with_completed_and_active_status_and_description_amended, return_response_if_error=True)

@when("I amend only the description of the instance of the project with a POST request")
def step_amend_project_with_post(context):
    new_description_data = {
        "description": "This is the final description of the Test Project with a POST request"
    }

    context.response = sendRequest("POST", context.URL, data=new_description_data, return_response_if_error=True)

@then("The existing project instance with the id will be replaced with the amended instance")
def step_verify_project_replaced(context):
    assert projectsGetEntries()[0].get("title") == "New Project Title"
    assert projectsGetEntries()[0].get("completed") == "true"
    assert projectsGetEntries()[0].get("active") == "false"
    assert projectsGetEntries()[0].get("description") == "This is the description of a completed Test Project replaced with a PUT request"

'''
The way PUT and POST requests are handled in the API is unexpected.
We expected PUT to amend the body of the project instance the way that POST actually does,
and we expected POST to create and/or replace a project instance the way that PUT actually does.
However, we found that we cannot make POST requests for any id for which a project instance doesn't exist.
'''
@then("The description field of the existing project is updated with all other fields remaining unchanged")
def step_verify_project_amended(context):
    assert projectsGetEntries()[0].get("title") == "Test Project Title"
    assert projectsGetEntries()[0].get("completed") == "false"
    assert projectsGetEntries()[0].get("active") == "true"
    assert projectsGetEntries()[0].get("description") == "This is the final description of the Test Project with a POST request"

@then("I get an error code 404")
def step_verify_project_failed_to_amend(context):
    assert context.response.status_code == 404


import base64
from io import BytesIO
from pathlib import Path
from PIL import Image
from service import TryonService
from utils import gdrive_download, url_download

CKPT_PATH = Path('model')
CKPT_PATH.mkdir(parents=True, exist_ok=True)

gdrive_download(
	url='https://drive.google.com/uc?id=1rbSTGKAE-MTxBYHd-51l2hMOQPT_7EPy',
	output=str(CKPT_PATH / 'u2netp.pt'),
)
gdrive_download(
	url='https://drive.google.com/uc?id=1KJNKjqBeUF9CLcCRFyjONmKzcqjNgj9z',
	output=str(CKPT_PATH / 'mobile_warp.pt'),
)
gdrive_download(
	url='https://drive.google.com/uc?id=1TP2OiEixy1WEjbJsdDYGL-214v_zkqUV',
	output=str(CKPT_PATH / 'mobile_gen.pt'),
)
url_download(
	url='https://github.com/WongKinYiu/yolov7/releases/download/v0.1/yolov7-w6-pose.pt',
	output=str(CKPT_PATH / 'yolov7-w6-pose.pt'),
)
url_download(
	url='https://storage.googleapis.com/mediapipe-models/image_segmenter/selfie_segmenter/float16/latest/selfie_segmenter.tflite',
	output=str(CKPT_PATH / 'mediapipe_segmenter.tflite'),
)

tryon_service = TryonService(
	tryon_ckpt={'warp': CKPT_PATH / 'mobile_warp.pt', 'gen': CKPT_PATH / 'mobile_gen.pt'},
	edge_detect_ckpt=CKPT_PATH / 'u2netp.pt',
	yolo_ckpt=CKPT_PATH / 'yolov7-w6-pose.pt',
	mediapipe_segment_ckpt=CKPT_PATH / 'mediapipe_segmenter.tflite',
	device='cuda:0',
)

person_image_path = "person.jpg"
garment_image_path = "cloth.jpg"

pil_img = Image.open(person_image_path).convert('RGB')
pil_clothes = Image.open(garment_image_path).convert('RGB')

tryon_cv = tryon_service.tryon_image(pil_img, pil_clothes)
if tryon_cv is not None:
	pil_tryon = Image.fromarray(tryon_cv)
else:
	pil_tryon = pil_img

image_buffer = BytesIO()
pil_tryon.save(image_buffer, 'JPEG')
image_buffer.seek(0)

base64_string = "data:image/jpeg;base64," + base64.b64encode(image_buffer.getvalue()).decode()

print(base64_string)


word = input().rstrip()  # 문자 입력
word_list = list(word)  # 입력단어리스트화
result_list = []
cnt = 0

# 소문자일 경우 대문자로 변환
for i in range(len(word_list)):
    if word_list[i] in 'abcdefghijklmnopqrstuvwxyz':
        num = ord(word_list[i])
        word_list[i] = chr(num - 32)
# print("word_list:", word_list)

# 딕셔너리 생성
dic = {}
for word in word_list:
    dic[word] = 0
for count in word_list:
    dic[count] += 1

# print("dic:", dic)

result_list = list(dic.values()) # 빈도값들을 따로 리스트화
mode = max(result_list) # 최빈값 저장

for i in range(len(result_list)): # 최빈값이 몇 개인지 세는 변수 cnt 채우기
    if result_list[i] == mode:
        cnt += 1

# print("cnt:", cnt)

if cnt == 1: # 최빈값이 1개이면
    print(max(dic, key=dic.get)) #해당 값을 가져오기
else: # 2개 이상이면
    print("?") # 물음표 출력


from math import *
# import matplotlib.pyplot as plt
from operator import itemgetter

table = {}
for i in range(1, 13):
    table[i] = [[], []]
n = int(input())
for i in range(n):
    index, ice_x, ice_y, drone_x, drone_y, height = input().split()
    index = int(index)
    ice_x = int(ice_x)
    ice_y = int(ice_y)
    drone_x = float(drone_x)
    drone_y = float(drone_y)
    height = float(height) - 4
    pixel_size = height/480
    # a = 2*height*tan(22.5*pi/180)  # стороны картинки в метрах
    # b = 2*height*tan(21.145*pi/180)
    # ice_x = drone_x + a*(ice_x - 640/2)/640  # координаты людин в м от точки отсчета базовой СК
    # ice_y = drone_y + b*(-ice_y + 480/2)/480
    ice_x = drone_x + (ice_x - 320)*pixel_size
    ice_y = drone_y + (240 - ice_y)*pixel_size
    table[index][0].append(ice_x)
    table[index][1].append(ice_y)

colors = ['bo', 'go', 'ro', 'co', 'mo', 'yo', 'ko', 'bs', 'gs', 'rs', 'cs', 'ms']

# отсекаем лишние точки
for p in range(1, 13):
    while max(table[p][0]) - min(table[p][0]) > 5 or max(table[p][1]) - min(table[p][1]) > 20:
        if len(table[p][0]) <= 6:
            break
        if max(table[p][0]) - min(table[p][0]) > 5:
            i_max = table[p][0].index(max(table[p][0]))
            i_min = table[p][0].index(min(table[p][0]))
            d_sum = 0
            for j in range(len(table[p][0])):
                d_sum += sqrt((table[p][0][i_max] - table[p][0][j]) ** 2 + (table[p][1][i_max] - table[p][1][j]) ** 2)
            d_avr = d_sum / len(table[p][0])
            for j in range(len(table[p][0])):
                d_sum += sqrt((table[p][0][i_min] - table[p][0][j]) ** 2 + (table[p][1][i_min] - table[p][1][j]) ** 2)
            d_avr1 = d_sum / len(table[p][0])
            if d_avr1 > d_avr:
                table[p][0].remove(table[p][0][i_min])
                table[p][1].remove(table[p][1][i_min])
            else:
                table[p][0].remove(table[p][0][i_max])
                table[p][1].remove(table[p][1][i_max])
        elif max(table[p][1]) - min(table[p][1]) > 20:
            i_max = table[p][1].index(max(table[p][1]))
            i_min = table[p][1].index(min(table[p][1]))
            d_sum = 0
            for j in range(len(table[p][0])):
                d_sum += sqrt((table[p][0][i_max] - table[p][0][j]) ** 2 + (table[p][1][i_max] - table[p][1][j]) ** 2)
            d_avr = d_sum / len(table[p][0])
            for j in range(len(table[p][0])):
                d_sum += sqrt((table[p][0][i_min] - table[p][0][j]) ** 2 + (table[p][1][i_min] - table[p][1][j]) ** 2)
            d_avr1 = d_sum / len(table[p][0])
            if d_avr1 > d_avr:
                table[p][0].remove(table[p][0][i_min])
                table[p][1].remove(table[p][1][i_min])
            else:
                table[p][0].remove(table[p][0][i_max])
                table[p][1].remove(table[p][1][i_max])

    # plt.plot(table[p][0], table[p][1], colors[p-1])
    # находим средние точки и выводим
    x_avr = sum(table[p][:][0])/len(table[p][:][0])
    y_avr = sum(table[p][:][1])/len(table[p][:][1])
    table[p] = [x_avr, y_avr]
    # plt.plot(x_avr, y_avr, colors[p-1][0] + '+')
    # plt.text(x_avr, y_avr, str(p))

# дальше пытаемся разбить точки по секторам
points = []
for i, [x, y] in table.items():
    points.append([i, x, y])
points.sort(key=lambda row: row[2], reverse=True)

lines = []
lines.append(sorted([points[0], points[1], points[2]], key=itemgetter(1)))
lines.append(sorted([points[3], points[4], points[5]], key=itemgetter(1)))
lines.append(sorted([points[6], points[7], points[8]], key=itemgetter(1)))
lines.append(sorted([points[9], points[10], points[11]], key=itemgetter(1)))
for i in range(4):
    print(lines[i][0][0], lines[i][1][0], lines[i][2][0])
    # for j in range(3):
    #     plt.text(lines[i][j][1], lines[i][j][2], str(lines[i][j][0]))
# plt.show()


# coding: utf-8
from django.conf import settings
from django.conf.urls import patterns
from django.conf.urls import url
from django.views.decorators.cache import cache_page

from .views import (QuoteDetailView, AuthorDetailView, TagDetailView,
                    AuthorListView, TagListView)

urlpatterns = patterns(
    'quotes.views',
    url(
        regex=r'^q/(?P<uuid>[\w]+)/$',
        view=cache_page(settings.DEFAULT_CACHE_TIME)(
            QuoteDetailView.as_view()
        ),
        name='quote'
    ),
    # url(r'^q/(?P<uuid>[\w]+)/$', 'detail', name='quote'),
    url(r'^quote/(?P<slug>[\w-]+)/$', 'quote_redirect'),

    url(
        regex=r'^authors/$',
        view=cache_page(settings.DEFAULT_CACHE_TIME)(
            AuthorListView.as_view()
        ),
        name='authors'
    ),
    url(
        regex=r'^quotes-by/(?P<slug>[\w-]+)/(page/(?P<page>\d+)/)?$',
        view=cache_page(settings.DEFAULT_CACHE_TIME)(
            AuthorDetailView.as_view()
        ),
        name='author'
    ),

    url(
        regex=r'^tags/$',
        view=cache_page(settings.DEFAULT_CACHE_TIME)(
            TagListView.as_view()
        ),
        name='tags'
    ),
    url(
        regex=r'^quotes-tagged-with/(?P<slug>[\w-]+)/(page/(?P<page>\d+)/)?$',
        view=cache_page(settings.DEFAULT_CACHE_TIME)(
            TagDetailView.as_view()
        ),
        name='tag'
    ),

    url(r'^random/$', 'random', name='random'),
    # url(r'^submit/$', 'submit_quote', name='submit'),

    url(
        r'^(page/(?P<page>\d+)/)?(format/(?P<format>\w+)/)?$',
        'index',
        name='root'
    ),
)


import numpy as np
from c_randomwalk import wrap_c_pixie_random_walk

class RandomWalk:
    def __init__(
        self,
        alpha=0.1,
        n_total_steps=100000,
        n_least_candidate_nodes=500,
        n_least_visited_cnt=4,
        use_boosting=False,
        dynamic_allocation=False,
        use_pixie_weighting=False,
        n_jobs=0,
    ):
        self._alpha = alpha
        self._n_total_steps = n_total_steps  # N
        self._n_least_candidate_nodes = n_least_candidate_nodes  # n_p
        self._n_least_visited_cnt = n_least_visited_cnt  # n_v
        self._use_boosting = use_boosting
        self._dynamic_allocation = dynamic_allocation
        self._use_pixie_weighting = use_pixie_weighting
        self._n_jobs = n_jobs

    def load_graph(self, adjacency, offsets, n_users, n_items):
        self._adjacency = adjacency
        self._offsets = offsets
        assert len(self._offsets) == n_users + n_items + 1
        self._offsets.setflags(write=False)
        self._adjacency.setflags(write=False)
        self.n_users = n_users
        self.n_items = n_items
        self.n_nodes = n_users + n_items
        self.max_item_degree = np.max(
            [self.get_degree(n) for n in range(n_users, self.n_nodes)]
        )
        return self

    def get_degree(self, node):
        return self._offsets[node + 1] - self._offsets[node]

    def get_neighbors(self, node):
        min_id = self._offsets[node]
        max_id = self._offsets[node + 1]
        return self._adjacency[min_id:max_id]

    def run_random_walk(self, query_items):
        self._all_steps_cnt = 0

        # the number of steps for a query
        if self._dynamic_allocation:
            scaling_factors = [self.scaling_factor(q) for q in query_items]
            summed_scaling_factors = np.sum(scaling_factors)
            steps_per_query = (
                self._n_total_steps
                * np.array(scaling_factors)
                / summed_scaling_factors
            ).astype(np.int)
        else:
            total_random_walks = len(query_items)
            steps_per_query = np.array(
                [int(self._n_total_steps / total_random_walks)]
                * total_random_walks,
                dtype=np.int,
            )

        sample_steps = np.random.geometric(
            self._alpha, size=(self._n_total_steps,)
        )

        return wrap_c_pixie_random_walk(
            self._adjacency,
            self._offsets,
            query_items,
            steps_per_query,
            self._n_least_candidate_nodes,
            self._n_least_visited_cnt,
            self._n_total_steps,
            sample_steps,
            self._use_boosting,
        )

    def scaling_factor(self, query_item):
        item_degree = self.get_degree(query_item)
        if item_degree == 0:
            return 0
        else:
            if self._use_pixie_weighting:
                return item_degree * (
                    self.max_item_degree - np.log(item_degree)
                )
            else:
                return item_degree * (
                    1 - np.log(item_degree) + np.log(self.max_item_degree)
                )


"""
Milan Murray 17/11/19
Additional Questions
"""

"""
# Other
import math

cycle = 0   # Used to maintain loop

main_menu = "\t\t¦===============================================¦\n" \
            "\t\t¦\tCalculation of volume for a solid object\t¦\n" \
            "\t\t¦¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¬¦\n" \
            "\t\t¦\t1. Cube\t\t\t\t\t\t\t\t\t\t¦\n" \
            "\t\t¦\t2. Cylinder\t\t\t\t\t\t\t\t\t¦\n" \
            "\t\t¦\t3. Sphere\t\t\t\t\t\t\t\t\t¦\n" \
            "\t\t¦\t4. Exit\t\t\t\t\t\t\t\t\t\t¦\n" \
            "\t\t¦===============================================¦\n"

# Constants
VOLUME_POWER = 3
SPHERE_MATH_ELEMENT = 4 / 3

# Inputs
print("\n---\t\tQuestion 1: A program that calculates the volumes of different solids.\t\t---\n")
print(main_menu)
option = int(input("Please chose an option from the menu: "))
print()

# Processes
while option != 4:
    cycle += 1
    if cycle > 1:
        print(main_menu)
        option = int(input("Please chose an option from the menu: "))
        print()
    while option < 0 or option > 4:
        option = int(input("Please re-enter a valid option: "))
        print()

    if option == 1:     # Cube: v = length ** 3
        side_length = float(input("Please enter the side length of the cube: "))
        cube_volume = side_length ** VOLUME_POWER
        cube_volume = round(cube_volume, 2)
        print("The volume of a cube of side length", side_length, "units is:", cube_volume, "units squared.")
        input("Press enter to continue...")
        print()

    elif option == 2:   # Cylinder: v = p * r2 * height
        radius = float(input("Please enter the radius of the cylinder: "))
        height = float(input("Please enter the height of the cylinder: "))
        cylinder_volume = math.pi * (radius ** 2) * height
        cylinder_volume = round(cylinder_volume, 2)
        print("The volume of a cylinder with radius", radius,
              "and height", height, "is", cylinder_volume, "units squared")
        input("Press enter to continue...")
        print()

    elif option == 3:   # Sphere: v = (4 / 3) * p * r3
        radius = float(input("Please enter the radius of the sphere:"))
        sphere_volume = SPHERE_MATH_ELEMENT * math.pi * (radius ** VOLUME_POWER)
        sphere_volume = round(sphere_volume, 2)
        print("The volume of a sphere of radius", radius, "is:", sphere_volume, "units squared.")
        input("Press enter to continue...")
        print()

print("Task failed successfully")
"""

# """
# Other

# Constants

# Inputs
print("\n---\tExercise 2: Format a URL\t---\n")
sentence = input("Please enter the desired URL for the website: ")
remainder_sentence = sentence

# Processes
while " " in remainder_sentence:
    space_loc = (remainder_sentence.index(" ") + 1)     # Find where the space is in the remainder of the sentence
    # remainder_sentence = remainder_sentence[space_loc:]     # Setup the remainder of the sentence for the next loop
    start_sentence = remainder_sentence[:sentence.index(" ")]   # Prepare the new sentence for adding 20%
    new_start = start_sentence + "%20"  # add 20% to the end of the string
    remainder_sentence = new_start + remainder_sentence     # The final is the original gaining a 20% each loop

    print(new_start)
    print(remainder_sentence)

# Outputs

# """


import genetique as gene
import fitnessSESSAD as fS
import time as ti

import json as js
import numpy as np
import fitnessEmployes as fE

import matplotlib.pyplot as plt

import population_initiale as pI

MATRICE_DISTANCE = []
INTERVENANTS = []
MISSIONS = []

SOLUTIONS = []

def charge_fichier_csv(dossier):
    """
    Charge le contenue du fichier csv dans les variables globales
    """
    with open(f"Instances/{dossier}/Distances.csv", 'r') as fichier:
        lignes = fichier.read().split('\n')
        if lignes[-1] == '':
            lignes = lignes[:-1]
        for ligne in lignes:
            MATRICE_DISTANCE.append(list(map(float, ligne.split(','))))

    with open(f"Instances/{dossier}/Intervenants.csv", 'r') as fichier:
        lignes = fichier.read().split('\n')
        if lignes[-1] == '':
            lignes = lignes[:-1]
        for ligne in lignes:
            INTERVENANTS.append(ligne.split(','))

    with open(f"Instances/{dossier}/Missions.csv", 'r') as fichier:
        lignes = fichier.read().split('\n')
        if lignes[-1] == '':
            lignes = lignes[:-1]
        for ligne in lignes:
            MISSIONS.append(ligne.split(','))

    # Changements des chiffres de types str en type int
    for i in range(len(INTERVENANTS)):
        for j in range(len(INTERVENANTS[i])):
            try:
                INTERVENANTS[i][j] = int(INTERVENANTS[i][j])
            except:
                pass

    for i in range(len(MISSIONS)):
        for j in range(len(MISSIONS[i])):
            try:
                MISSIONS[i][j] = int(MISSIONS[i][j])
            except:
                pass

    return (MATRICE_DISTANCE, INTERVENANTS, MISSIONS)

def charger_solution(dossier):
    with open(f"./{dossier}", 'r') as f:
        fich = f.read().split('\n\n')[:-1]
    SOLUTIONS = [js.loads(i) for i in fich]
    return SOLUTIONS

def duree(deb, nbPopMax, pas):
    """
    Fonction qui permet de calculer le temps d'exécution de X générations
    A chaque tour dans la boucle for on reprend la solution précédente et ainsi on évite de repartir du début
    On renvoit le temps d'exécution de la génération de X générations en secondes dans un tableau
    """
    sol = charger_solution("solutions.txt")
    print(len(sol[0]))
    temps = [0]
    x = [0]
    indice = 0
    debut = ti.time()
    for i in range(deb, nbPopMax + pas, pas):
        sol = gene.genetique(sol, i, 0.07, MATRICE_DISTANCE, INTERVENANTS, MISSIONS, 0.00, "employe")
        fin = ti.time()
        x.append(x[indice] + i)
        indice += 1
        temps.append(fin - debut)

    plt.plot(x, temps)
    plt.xlabel("Générations")
    plt.ylabel("Temps en secondes")
    plt.title("Evolution du temps de calcul en fonction du nombre de générations")
    plt.savefig('test' + '.pdf')
    plt.show()

    return x, temps

def evolutionFit(deb, nbPopMax, pas, type):
    """
    Fonction qui permet de calculer l'évolution de la fitness des générations
    A chaque tour dans la boucle for on reprend la solution précédente et ainsi on évite de repartir du début
    On renvoit la fitness de la génération de X générations dans un tableau
    """
    sol = charger_solution("solutions.txt")
    print(len(sol[0]))
    fit = [min(gene.choixFitness_tableau(type, MISSIONS, INTERVENANTS, sol, MATRICE_DISTANCE))]
    x = [0]
    indice = 0
    for i in range(deb, nbPopMax + pas, pas):
        sol = gene.genetique(sol, i, 0.07, MATRICE_DISTANCE, INTERVENANTS, MISSIONS, 0.00, type)
        finFit = min(gene.choixFitness_tableau(type, MISSIONS, INTERVENANTS, sol, MATRICE_DISTANCE))
        fit.append(finFit)
        x.append(x[indice] + i)
        indice += 1

    plt.plot(x, fit)
    plt.xlabel("Générations")
    plt.ylabel("Fitness")
    plt.title("Évolution de la fitness " + type + " en fonction du nombre de générations")
    plt.savefig('test' + '.pdf')
    plt.show()

    return x, fit

def nbSolutionnn(deb, nbPopMax, pas):
    """
    Fonction qui permet de calculer le nombre de génération en donnant le nombre minimal de génération, le pas entre chaque génération
    """
    x = [0]
    indice = 0
    for i in range(deb, nbPopMax + pas, pas):
        x.append(x[indice] + i)
        indice += 1

    return x[-1]

def tempsGenePopu (geneMin, geneMax, pas):
    x=[]
    temps=[]
    for i in range(geneMin, geneMax, pas):
        start_time = ti.time()
        pI.gen_n_solutions_uniques(i)
        end_time = ti.time()
        x.append(i)
        temps.append(end_time-start_time)

    plt.plot(x, temps)
    plt.xlabel("Taille de la population")
    plt.ylabel("Temps en secondes")
    plt.title("Évolution du temps pour générer une population initiale")
    plt.savefig('test' + '.pdf')
    plt.show()
    return x, temps

def main():
    charge_fichier_csv("45-4")
    #tempsGenePopu(5, 150, 10)
    SOLUTIONS = charger_solution("solutions.txt")
    deb, nbPopMax, pas = 10, 230, 2
    print(nbSolutionnn(deb, nbPopMax, pas))
    x, y = duree(deb, nbPopMax, pas)

if __name__ == "__main__":
    main()


xs = []
ys = []

for i in range(0, 3):
    x1, y1 = map(int, input().split())
    xs.append(x1)
    ys.append(y1)

def setCnt(list, dic):
    for x in list:
        if not x in dic.keys():
            dic[x] = 1
        else:
            dic[x] = dic[x] + 1

xdic = {}
ydic = {}
setCnt(xs, xdic)
setCnt(ys, ydic)

new_x = ""
new_y = ""
for key, value in xdic.items() :
    if value == 1:
        new_x = key

for key, value in ydic.items() :
    if value == 1:
        new_y = key

print(new_x, new_y)


import unittest
import pandas as pd

from feathub.common.types import String, Int64
from feathub.online_stores.memory_online_store import MemoryOnlineStore
from feathub.table.schema import Schema

class MemoryOnlineStoreTest(unittest.TestCase):
    def setUp(self):
        super().setUp()
        self.features = pd.DataFrame(
            [
                ["Alex", 100, 100, "2022-01-01 08:01:00"],
                ["Emma", 400, 250, "2022-01-01 08:02:00"],
                ["Alex", 300, 200, "2022-01-02 08:03:00"],
                ["Emma", 200, 250, "2022-01-02 08:04:00"],
                ["Jack", 500, 500, "2022-01-03 08:05:00"],
                ["Alex", 600, 800, "2022-01-02 08:02:30"],
            ],
            columns=["name", "cost", "distance", "time"],
        )
        self.schema = (
            Schema.new_builder()
            .column("name", String)
            .column("cost", Int64)
            .column("distance", Int64)
            .column("time", String)
            .build()
        )

    def tearDown(self) -> None:
        MemoryOnlineStore.get_instance().reset()

    def test_put_and_get(self):
        store = MemoryOnlineStore.get_instance()
        store.put(
            table_name="table_1",
            features=self.features,
            schema=self.schema,
            key_fields=["name"],
            timestamp_field="time",
            timestamp_format="%Y-%m-%d %H:%M:%S",
        )

        keys = pd.DataFrame([["Alex"], ["Emma"]], columns=["name"])
        result_df = store.get(
            table_name="table_1",
            input_data=keys,
            feature_names=["cost"],
            include_timestamp_field=True,
        )

        expected_result_df = pd.DataFrame(
            [
                ["Alex", 300, "2022-01-02 08:03:00"],
                ["Emma", 200, "2022-01-02 08:04:00"],
            ],
            columns=["name", "cost", "time"],
        )
        self.assertTrue(expected_result_df.equals(result_df))


from collections import defaultdict

def solution(today, terms, privacies):
    answer = []

    termDict = defaultdict()
    todayArr = today.split(".")
    todayInt = (((int(todayArr[0]) * 12) + int(todayArr[1])) * 28) + int(todayArr[2])

    for term in terms:
        temp = term.split(" ")
        termDict[temp[0]] = int(temp[1])

    for i in range(len(privacies)):
        privacy = privacies[i]

        temp = privacy.split(" ")
        year, month, day = temp[0].split(".")
        finishDayInt = (((int(year) * 12) + int(month)) * 28) + int(day) + (28 * termDict[temp[1]])

        if finishDayInt <= todayInt:
            answer.append(i+1)

    return answer

today = "2022.05.19"
terms = ["A 6", "B 12", "C 3"]
privacies = ["2021.05.02 A", "2021.07.01 B", "2022.02.19 C", "2022.02.20 C"]

today1 = "2020.01.01"
terms1 = ["Z 3", "D 5"]
privacies1 = ["2019.01.01 D", "2019.11.15 Z", "2019.08.02 D", "2019.07.01 D", "2018.12.28 Z"]
print(solution(today, terms, privacies))
print(solution(today1, terms1, privacies1))


import os

class os_fun():
    def search_ext(self, path, search_for_ext):
        for dirpath, dirnames, filenames in os.walk(r'c:\itay'):
            for one_file in filenames:
                if os.path.splitext(one_file)[1] ==\
                        search_for_ext:
                    print(one_file)

    def find_max(self, path):
        max = -1
        file_max_name = 'not found...'
        for dirpath, dirnames, filenames in os.walk(r'c:\itay'):
            for one_file in filenames:
                size_of_file = \
                    os.stat(os.path.join(dirpath, one_file)).st_size
                if size_of_file > max:
                    max = size_of_file
                    file_max_name = one_file
        print(f'Biggest file : {file_max_name} [{max}]')
        return file_max_name

    def print_processes(self):
        import psutil # install frmo Settings
        for proc in  psutil.process_iter():
            print(proc.name())


"""
Embed PAConv into PointNet
"""

import torch
import torch.nn as nn
import torch.nn.functional as F
from paconv_util.PAConv_util import get_scorenet_input, knn, feat_trans_pointnet, ScoreNet
from paconv_cuda_lib.functional import assign_score_withk_halfkernel as assemble_pointnet

class PAConv(nn.Module):
    def __init__(self,in_channel,out_channel,m=8):
        super(PAConv, self).__init__()
        self.calc_scores = 'softmax'

        self.m2 = m # m controls number of weight matrix, higher, more capacity to fit, 8 by default
        self.scorenet2 = ScoreNet(66, self.m2, hidden_unit=[64,32,16])

        i2 = in_channel  # channel dim of output_1st and input_2nd
        o2 = out_channel  # channel dim of output_2st and input_3rd

        tensor2 = nn.init.kaiming_normal_(torch.empty(self.m2, i2, o2), nonlinearity='relu') \
            .permute(1, 0, 2).contiguous().view(i2, self.m2 * o2)

        # convolutional weight matrices in Weight Bank:
        self.matrice2 = nn.Parameter(tensor2, requires_grad=True)

        self.bn1 = nn.BatchNorm1d(in_channel)
        self.bn2 = nn.BatchNorm1d(out_channel)

        self.conv1 = nn.Conv1d(in_channel, in_channel, kernel_size=1, bias=False)

    def forward(self, x,idx,xyz_score):

        x = self.conv1(x)
        x = F.relu(self.bn1(x),inplace=True)
        ##################
        # replace the intermediate 3 MLP layers with PAConv:
        """CUDA implementation of PAConv: (presented in the supplementary material of the paper)"""
        """feature transformation:"""
        # do conv with m kernel, project feature to m space
        x = feat_trans_pointnet(point_input=x, kernel=self.matrice2, m=self.m2)  # b,n,m1,o1

        score2 = self.scorenet2(xyz_score, calc_scores=self.calc_scores, bias=0)
        """assemble with scores:"""
        # point-wise conv
        x = assemble_pointnet(score=score2, point_input=x, knn_idx=idx, aggregate='sum')   # b,o1,n
        x = F.relu(self.bn2(x),inplace=True)

        return x

if __name__== "__main__":
    conv=PAConv(in_channel=64,out_channel=128).to("cuda:0")
    x=torch.ones(32,64,100).to("cuda:0")
    xyz=torch.ones(32,3,100).to("cuda:0")
    x=conv(x,xyz)
    print(x.shape)


import csv
csv_reader = csv.reader(open("marks.csv"))

good_answers = ['B', 'C', 'C', 'A', 'A', 'A', 'D', 'C', 'A', 'B', 'C', 'A', 'C', 'C']
scale = [1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 3, 3, 4]
domain = ['A', 'B', 'C', 'D', 'E', '0']
grade_M = 0
grade_F = 0
M = 0
F = 0

def evaluate(good_answers, stud_answers, domain, scale):
    if len(stud_answers) != 14:
        a = "Il n'y a pas le bon nombre de réponses"
        tuple_1 = ('1', a)
        print(tuple_1)
        quit()

    for element in stud_answers:
        if element in domain:
            print()
        else:
            c = "Il y a un caractère interdit."
            tuple_3 = ('1', c)
            print(tuple_3)
            quit()

    grade = 0

    for question_number in range(0, 14):
        if good_answers[question_number] == stud_answers[question_number]:
            grade = grade + scale[question_number]

    if grade > 20:
        grade = 20
        #print("Sans faute!")
    tuple_2 = ('0', grade)
    return (tuple_2)

for row in csv_reader:
    gender = row[1]
    stud_answers = row[2]
    num = row[0]
    grade = evaluate(good_answers, stud_answers, domain, scale)[1]
    if gender == "M":
        grade_M = grade_M + grade
        M = M + 1
    else:
        grade_F = grade_F + grade
        F = F + 1

average_F = grade_F / F
average_M = grade_M / M

print("La moyenne des filles est de:", average_F, "sur 20", "et la moyenne des garçons est de:", average_M, "sur 20.")


# 1. Print each item in the following list: ['The Walking Dead','Entourage','The Sopranos','The Vampire Diaries']
show_list = ['The Walking Dead','Entourage','The Sopranos','The Vampire Diaries']
for i in show_list:
    print(i)

# 2. Print all the numbers from 25 to 50
for i in range(25,51):
    print(i)

# 3. Print each item in the list from the first challenge and their indexes
for i, show in enumerate(show_list):
    print(str(i) + ':' + show)

# 4. Write a program with an infinite loop (with the option to type q to quit)
# and a list of numbers. Each time through the loop ask the user to guess a number
# on the list and tell them whether or not they guessed correctly.

numlst = [1,18,27,42]
while True:
    a = input('guess a number:')
    if a == 'q':
        break
    if int(a) in numlst:
        print('you guessed it, now get outta here!')
        break

# 5. Multiply all the numbers in the list [8,19,148,4] with all the numbers in the list
# [9,1,33,83] and append each result to a third list

first_list = [8,9,148,4]
second_list = [9,1,33,83]
third_list = list()
for i in first_list:
    for j in second_list:
        a = i * j
        third_list.append(a)

print(third_list)


class QuickSort:

    def __init__(self, elements=None):
        if not elements:
            raise Exception('Elements must not be null.')
        self.elements = elements
        self.left = 0
        self.right = len(elements) - 1

    def insertion_sort(self, elements, left, right):
        for ind in range(left, right):
            sub_ind = ind
            while sub_ind > left and elements[sub_ind - 1] > elements[sub_ind]:
                elements[sub_ind - 1], elements[sub_ind] = elements[sub_ind], elements[sub_ind - 1]
                sub_ind -= 1
        return

    def sort(self, elements=None, left=None, right=None):
        if elements is None:
            elements = list(self.elements)
        if left is None:
            left = self.left
        if right is None:
            right = self.right

        cutoff = 3
        if left + cutoff <= right:
            pivot = self.med3(elements, left, right)
            i = left
            j = right - 1
            while True:
                i += 1
                j -= 1
                while elements[i] < pivot:
                    i += 1
                while elements[j] > pivot:
                    j -= 1
                if i < j:
                    self.swap(elements, i, j)
                else:
                    break
            self.swap(elements, i, right - 1)
            self.sort(elements, left, i - 1)
            self.sort(elements, i + 1, right)
        else:
            self.insertion_sort(elements, left, right + 1)
        return elements

    def swap(self, e, ind1, ind2):
        e[ind1], e[ind2] = e[ind2], e[ind1]

    def med3(self, elements, left, right):
        """Median-of-three partitioning"""
        center = (left + right) // 2
        if elements[left] > elements[center]:
            self.swap(elements, left, center)
        if elements[left] > elements[right]:
            self.swap(elements, left, right)
        if elements[center] > elements[right]:
            self.swap(elements, center, right)
        self.swap(elements, center, right - 1)
        return elements[right - 1]

    def select(self, kth, elements=None, left=None, right=None):
        if kth <= 0 or kth > self.right:
            raise Exception('kth must be a positive number and not big than elements count.')
        if elements is None:
            elements = list(self.elements)
        if left is None:
            left = self.left
        if right is None:
            right = self.right
        cutoff = 3
        if left + cutoff <= right:
            pivot = self.med3(elements, left, right)
            i = left
            j = right - 1
            while True:
                i += 1
                j -= 1
                while elements[i] < pivot:
                    i += 1
                while elements[j] > pivot:
                    j -= 1
                if i < j:
                    self.swap(elements, i, j)
                else:
                    break
            self.swap(elements, i, right - 1)
            if kth <= i:
                self.select(kth, elements, left, i - 1)
            elif kth > i + 1:
                self.select(kth, elements, i + 1, right)
        else:
            self.insertion_sort(elements, left, right + 1)
        return elements[kth - 1]

if __name__ == "__main__":
    s = QuickSort([int(x) for x in input('Enter elements seperated by single space:\n').split()])
    kth = int(input('Enter the k-th:\nk: '))
    print(s.sort(), f'\n{kth}-th smallest:{s.select(kth)}')


import config
import matplotlib.pyplot as plt
import numpy as np

max_green = 21
image = np.ones((len(config.image), len(config.image[0]), 3))
green = 1 - (np.array(config.image) / max_green)
np.place(image[:, :, 0], green < 1, 0)
np.place(image[:, :, 2], green < 1, 0)
image[:, :, 1] = green
plt.imshow(image)
plt.show()


# -*- coding: utf-8 -*-
"""
    The decoding method between genotype
    and the parameters.

:Author: Yan Zhou

:License: BSD 3-Clause, see LICENSE file.
"""

from Brian2_scripts.sim_brian_paper.sim_brian_paper_MRML.src.core import BaseFunctions
from Brian2_scripts.sim_brian_paper.sim_brian_paper_MRML.src.optimizer.ga import dec2bin, bin2dec

import numpy as np

class Decoder(BaseFunctions):
    """
    This class offers the decoding function which convert the gen into the
    parameters used by generator.

    Parameters
    ----------
    config_group, config_keys, config_codes, config_ranges, config_borders,
    config_precisions, config_scales: list, the config of optimization methods.
    neurons_encoding: the number of encoding neurons.
    """

    def __init__(self, config_group, config_keys, config_SubCom, config_codes, config_ranges, config_borders,
                      config_precisions, config_scales, gen_group):
        super(Decoder).__init__()
        self.gen_group = gen_group
        self.config_group = config_group
        self.config_keys = config_keys
        self.config_codes = config_codes
        self.config_SubCom = config_SubCom
        self.config_ranges = config_ranges
        self.config_borders = config_borders
        self.config_precisions = config_precisions
        self.config_scales = config_scales

    @property
    def get_keys(self):
        '''
         Get the name of each variate.

         Parameters
         ----------
         '''

        keys = []
        for index, group_name in enumerate(self.config_group):
            for key in self.config_keys[index]:
                keys.append(group_name+'_'+key)
        return keys

    @property
    def get_SubCom(self):
        '''
         Get the SubCom in the config.

         Parameters
         ----------
         '''
        SubCom = []
        for gen_group in self.gen_group:
            sub_com = []
            for group in gen_group:
                sub_com += self.config_SubCom[group]
            SubCom.append(sub_com)
        return SubCom

    @property
    def get_dim(self):
        '''
         Get the total dimension of the variate.

         Parameters
         ----------
         '''

        return len(self.get_keys)

    @property
    def get_codes(self):
        '''
         Get the settings of encoding of the variate.

         Parameters
         ----------
         '''

        codes = []
        for group_codes in self.config_codes:
            codes.extend(group_codes)
        return np.array(codes)

    @property
    def get_ranges(self):
        '''
         Get the settings of ranges of the variate.

         Parameters
         ----------
         '''

        ranges = []
        for group_ranges in self.config_ranges:
            ranges.extend(group_ranges)
        return np.array(ranges).T

    @property
    def get_borders(self):
        '''
         Get the settings of borders of the variate.

         Parameters
         ----------
         '''

        borders = []
        for group_borders in self.config_borders:
            borders.extend(group_borders)
        return np.array(borders).T

    @property
    def get_precisions(self):
        '''
         Get the settings of precisions of the variate.

         Parameters
         ----------
         '''

        precisions = []
        for group_precisions in self.config_precisions:
            precisions.extend(group_precisions)
        return np.array(precisions)

    @property
    def get_scales(self):
        '''
         Get the settings of scales of the variate.

         Parameters
         ----------
         '''
        scales = []
        for group_scales in self.config_scales:
            scales.extend(group_scales)
        return np.array(scales)

    def _float2int(self, Gen):
        '''
         Register a gen for this decoder, which is ready to be decoded for the generator.

         Parameters
         ----------
         Gen: np.array, the gen generated by optimization algorithm with all float
         '''

        _Gen = []
        for index, p in enumerate(self.get_precisions):
            if p == 0:
                _Gen.append(int(Gen[index]))
            else:
                _Gen.append(Gen[index])
        return _Gen

    def register(self, Gen):
        '''
         Register a gen for this decoder, which is ready to be decoded for the generator.

         Parameters
         ----------
         Gen: list, the gen generated by optimization algorithm but the precision with '0' convert to int
         '''

        self.Gen = self._float2int(Gen)

    def search(self, target):
        '''
         Find the target index from the config group.

         Parameters
         ----------
         target: str, the name of target variate.
         '''

        return np.where(np.array(self.config_group) == target)[0][0]

    def decode(self, target):
        '''
         Decode the target variate from the registered gen.

         Parameters
         ----------
         target: str, the name of target variate.
         '''

        group = self.search(target)
        key = self.config_keys[group]
        SubCom = self.config_SubCom[group]
        codes = self.config_codes[group]
        ranges = self.config_ranges[group]
        parameter = {}
        for p,k,c,r in zip(self.sub_list(self.Gen, SubCom), key, codes, ranges):
            if c != None:
                l = len(dec2bin((r[1]-r[0]), 0))
                p = dec2bin(p, l)
            parameter[k] = p
        return parameter

class Decoder_Block(Decoder):
    def __init__(self, config_group, config_keys, config_SubCom, config_codes, config_ranges, config_borders,
                      config_precisions, config_scales, gen_group, neurons_encoding):
        super().__init__(config_group, config_keys, config_SubCom, config_codes, config_ranges, config_borders,
                      config_precisions, config_scales, gen_group)
        self.neurons_encoding = neurons_encoding
        self.optimal_block_gens = None

    def get_block_type(self):
        '''
         Decode the type of the block.

         Parameters
         ----------
         task_id: int, the id of the task.
        '''

        parameters = self.decode('Block')
        block_type = bin2dec(parameters['block'])
        return block_type

    def get_block_structure(self):
        '''
         Decode the structure information of the block.

         Parameters
         ----------
         task_id: int, the id of the task.
        '''
        parameters = self.decode('Block')
        sub_parameters = self.get_sub_dict(parameters, 'N', 'p_0', 'p_1', 'p_2')
        return sub_parameters

    def get_block_parameter(self):
        '''
         Decode the neurons and synapse parameters of the block.

         Parameters
         ----------
        '''

        parameters = self.decode('Block')
        sub_parameters = self.get_sub_dict(parameters, 'tau_plasticity', 'strength', 'tau', 'tau_I', 'type')
        return sub_parameters

    def get_encoding_structure(self):
        '''
         Decode the encoding structure, the parameters are come from the need of dataloader.

         Parameters
         ----------
         '''

        return self.neurons_encoding

    def get_readout_parameter(self):
        '''
         Decode the readout parameters.

         Parameters
         ----------
         '''

        parameters = self.decode('Encoding_Readout')
        return self.get_sub_dict(parameters, 'tau_I')

    def get_pathway_structure(self, component):
        '''
         Decode structure information of the reservoir and encoding_readout.

         Parameters
         ----------
         component: str, 'Reservoir_config' based on config
         '''
        parameters = self.decode(component)
        sub_parameters = self.get_sub_dict(parameters, 'p_connection')
        return sub_parameters

    def get_pathway_parameter(self, component):
        '''
         Decode parameters of the reservoir and encoding_readout.

         Parameters
         ----------
         component: str, 'Reservoir_config' based on config
         '''
        parameters = self.decode(component)
        sub_parameters = self.get_sub_dict(parameters, 'tau_plasticity', 'strength', 'type')
        return sub_parameters

class Decoder_Reservoir(Decoder):
    def __init__(self, config_group, config_keys, config_SubCom, config_codes, config_ranges, config_borders,
                      config_precisions, config_scales, gen_group):
        super().__init__(config_group, config_keys, config_SubCom, config_codes, config_ranges, config_borders,
                      config_precisions, config_scales, gen_group)

    def register_optimal_block_gens(self, optimal_block_gens):
        '''
         Register a gen for this decoder, which is ready to be decoded for the generator.

         Parameters
         ----------
         optimal_block_gens: dict, {task_id: [optimal block gens]}
         '''

        # load gens form file
        self.optimal_block_gens = optimal_block_gens

    def get_optimal_block_gens(self, task_id):
        '''
         Decode the neurons and synapse parameters of the block.

         Parameters
         ----------
        '''

        return self.optimal_block_gens[task_id]

    def increase_block_reservoir(self, block_current, block_max):
        '''
         Increase block for new task.

         Parameters
         ----------
         '''

        self.config_ranges[1] = \
            [[0, 2**block_current-1]] * block_current + [[0, 0]] * (block_max-block_current)
        self.config_codes[1] = \
            [1] * block_current + [None] * (block_max-block_current)

    def get_reservoir_adjacent_matrix(self):
        '''
         Decode the connection matrix of blocks in the reservoir.

         Parameters
         ----------
         '''

        parameter = self.decode('Reservoir_arc')
        adjacent_matrix = []
        for value, code in zip(parameter.values(), self.config_codes[self.search('Reservoir_arc')]):
            if code is not None:
                adjacent_matrix.append(value)
        for i in range(len(adjacent_matrix)): # remove self connections
            if adjacent_matrix[i][i] == 1:
                adjacent_matrix[i][i] = 0
        return adjacent_matrix

    def get_pathway_structure(self, component):
        '''
         Decode structure information of the reservoir and encoding_readout.

         Parameters
         ----------
         component: str, 'Reservoir_config' based on config
         '''
        parameters = self.decode(component)
        sub_parameters = self.get_sub_dict(parameters, 'p_connection')
        return sub_parameters

    def get_pathway_parameter(self, component):
        '''
         Decode parameters of the reservoir and encoding_readout.

         Parameters
         ----------
         component: str, 'Reservoir_config' based on config
         '''
        parameters = self.decode(component)
        sub_parameters = self.get_sub_dict(parameters, 'tau_plasticity', 'strength', 'type')
        return sub_parameters


def __init__(self, *args, **kwargs):
    _SignallingSession.__init__(
        self, *args, **kwargs)
    self._name = None

def using_bind(self, name):
    self._name = name
    return self

def get_bind(self, mapper, clause=None):
    if mapper is not None:
        info = getattr(mapper.mapped_table,
                       'info', {})
        bind_key = self._name or \
          info.get('bind_key')
    else:
        bind_key = self._name
    if bind_key is not None:
        state = get_state(self.app)
        return state.db.get_engine(
            self.app, bind=bind_key)
    else:
        return Session.get_bind(
            self, mapper, clause)


import pandas as pd
from datetime import datetime
from typing import List

class DataFrameProcessor:
    """Class for processing data frames.
    """

    def __init__(self, csv_path):
        """Initialize the class, generate and clean the data frame.
        """
        self.df = pd.read_csv(csv_path)
        df = self.df
        # convert Time column to datetime data type
        df['Time'] = pd.to_datetime(df['Time'], format='%Y-%m-%d-%H-%M-%S')
        # delete row if Rem is not a valid integer or CRN is not a valid integer
        df = df[df['Rem'].apply(lambda x: x.isdigit())]
        df = df[df['CRN'].apply(lambda x: x.isdigit())]
        # transform to int
        df['Rem'] = df['Rem'].astype(int)
        df['CRN'] = df['CRN'].astype(int)
        # sort by time
        self.df = df.sort_values(by=['Time'])

    def get_data_frame(self, crn_lst: List[int] = None,
                       start_time: datetime = None,
                       end_time: datetime = None) -> pd.DataFrame:
        """Return a subset of the data frame based on the given parameters.
        """
        df = self.df.copy()
        if crn_lst is not None:
            df = df[df['CRN'].isin(crn_lst)]
        if start_time:
            df = df[df['Time'] >= start_time]
        if end_time:
            df = df[df['Time'] <= end_time]
        return df

    def get_all_crn(self) -> List[int]:
        """Return a list of all CRNs in the data frame.
        """
        return self.df['CRN'].unique().tolist()

    def crn_lst_valid(self, crn_lst: List[int]) -> bool:
        """Return True if the given CRN list is valid, False otherwise.

        crn_lst is valid if
            - it is empty
            - it contains only integers
            - no repeated CRN
            - crn all exist in the data frame

        If any error, write to log and print it console
        """
        if crn_lst is None:
            return True
        if not all(isinstance(crn, int) for crn in crn_lst):
            print('CRN list contains non-integer values')
            return False
        if len(crn_lst) != len(set(crn_lst)):
            print('CRN list contains repeated CRN')
            return False
        if not all(crn in self.get_all_crn() for crn in crn_lst):
            print('CRN list contains non-existing CRN')
            return False
        return True


import torch.nn as nn
import torch
import torch.autograd as autograd
from torch.nn import init
from torch.nn.modules import conv, Linear
from torch.nn.modules.utils import _pair
import torch.nn.functional as F
import torch.optim as optim
from torch.nn import init
import time
import argparse
from torch.utils.data import DataLoader
from torch.autograd import Variable
import numpy as np
from torch.utils.data import DataLoader
from torch.optim import lr_scheduler
import torch.nn.parallel
import torch.nn.utils.spectral_norm as spectral_norm
import numbers
import math
import os
from torch import Tensor
from torch.nn import Parameter
import yaml

# network function

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

class Block(nn.Module):
    def __init__(self,inchannels,outchannels,dropout,kernel,bias,depth,mode,factor=2):
        super(Block,self).__init__()
        layers = []
        for i in range(int(depth)):
            layers += [
                       nn.Conv3d(inchannels,inchannels,kernel_size=kernel,padding=kernel//2,bias=bias),
                       nn.ReLU(inplace=True)]
            if dropout:
                layers += [nn.Dropout(0.5)]
        self.model = nn.Sequential(*layers)
        if factor == 2:
            self.stride = 2
            self.padding = 1
        elif factor == 4:
            self.stride = 1
            self.padding = 0
        if mode == 'down':
            self.conv1 = nn.Conv3d(inchannels,outchannels,4,stride=self.stride,padding=self.padding,bias=bias)
            self.conv2 = nn.Conv3d(inchannels,outchannels,4,stride=self.stride,padding=self.padding,bias=bias)
        elif mode == 'up':
            self.conv1 = nn.ConvTranspose3d(inchannels,outchannels,4,stride=self.stride,padding=self.padding,bias=bias)
            self.conv2 = nn.ConvTranspose3d(inchannels,outchannels,4,stride=self.stride,padding=self.padding,bias=bias)
        elif mode == 'same':
            self.conv1 = nn.Sequential(*[
                                       nn.Conv3d(inchannels,outchannels,kernel_size=kernel,padding=kernel//2,stride=1,bias=bias)
                                       ])

            self.conv2 = nn.Sequential(*[
                                       nn.Conv3d(inchannels,outchannels,kernel_size=kernel,padding=kernel//2,stride=1,bias=bias)
                                       ])
    def forward(self,x):
        y = self.model(x)
        y = self.conv1(y)
        x = self.conv2(x)
        return x+y

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

class V2V(nn.Module):

    def __init__(self,init_channels=16):
        super(V2V,self).__init__()

        self.conv1 = nn.Conv3d(1,init_channels,4,2,1)
        self.conv2 = nn.Conv3d(init_channels,2*init_channels,4,2,1)
        self.conv3 = nn.Conv3d(2*init_channels,4*init_channels,4,2,1)
        self.conv4 = nn.Conv3d(4*init_channels,8*init_channels,4,2,1)

        ### upsample
        self.deconv4 = nn.ConvTranspose3d(8*init_channels,4*init_channels,4,2,1)
        self.conv_u4 = nn.Conv3d(8*init_channels,4*init_channels,3,1,1)
        self.deconv3 = nn.ConvTranspose3d(4*init_channels,2*init_channels,4,2,1)
        self.conv_u3 = nn.Conv3d(4*init_channels,2*init_channels,3,1,1)
        self.deconv2 = nn.ConvTranspose3d(2*init_channels,init_channels,4,2,1)
        self.conv_u2 = nn.Conv3d(2*init_channels,init_channels,3,1,1)
        self.deconv1 = nn.ConvTranspose3d(init_channels,init_channels//2,4,2,1)
        self.conv_u1 = nn.Conv3d(init_channels//2,1,3,1,1)

        self.b3 = Block(inchannels=4*init_channels,outchannels=4*init_channels,dropout=False,kernel=3,bias=False,depth=2,mode='same',factor=2)
        self.b2 = Block(inchannels=2*init_channels,outchannels=2*init_channels,dropout=False,kernel=3,bias=False,depth=2,mode='same',factor=2)
        self.b1 = Block(inchannels=init_channels,outchannels=init_channels,dropout=False,kernel=3,bias=False,depth=2,mode='same',factor=2)

    def forward(self,x):
        x1 = F.relu(self.conv1(x))
        x2 = F.relu(self.conv2(x1))
        x3 = F.relu(self.conv3(x2))
        x4 = F.relu(self.conv4(x3))

        ## upsample

        u1 = F.relu(self.deconv4(x4))
        u1 = F.relu(self.conv_u4(torch.cat((self.b3(x3),u1),dim=1)))
        u2 = F.relu(self.deconv3(u1))
        u2 = F.relu(self.conv_u3(torch.cat((self.b2(x2),u2),dim=1)))
        u3 = F.relu(self.deconv2(u2))
        u3 = F.relu(self.conv_u2(torch.cat((self.b1(x1),u3),dim=1)))
        u4 = F.relu(self.deconv1(u3))
        out = self.conv_u1(u4)
        out = torch.tanh(out)
        return out

class Dis(nn.Module):
    def __init__(self):
        super(Dis,self).__init__()
        ### downsample
        self.conv1 = spectral_norm(nn.Conv3d(1,32,4,2,1),eps=1e-4)
        self.conv2 = spectral_norm(nn.Conv3d(32,64,4,2,1),eps=1e-4)
        self.conv3 = spectral_norm(nn.Conv3d(64,128,4,2,1),eps=1e-4)
        self.conv4 = spectral_norm(nn.Conv3d(128,1,4,2,1),eps=1e-4)
        self.ac = nn.LeakyReLU(0.2,inplace=True)

    def forward(self,x):
        x1 = self.ac(self.conv1(x))
        x2 = self.ac(self.conv2(x1))
        x3 = self.ac(self.conv3(x2))
        x4 = self.ac(self.conv4(x3))
        x5 = F.avg_pool3d(x4,x4.size()[2:])
        return [x1,x2,x3,x4],x5.view(-1)


import logging

from odoo import http
from odoo.http import request
from odoo.addons.restful.common import invalid_response, valid_response
from odoo.addons.restful.controllers.main import validate_token
from datetime import datetime
from ast import literal_eval
from odoo.exceptions import UserError
import json

logger = logging.getLogger(__name__)

class UomAPI(http.Controller):
    @validate_token
    @http.route("/odoo/uom", methods=["POST"], type="http",
                auth="none", csrf=False)
    def create_uom(self, **post):
        # get values from parameters
        # post = request.jsonrequest
        if not post.get('name'):
            return invalid_response({'message': "Compulsory field - Name not found as an identifier",
                                     'status': 401})

        # if not post.get('rounding'):
        #     return invalid_response({'message': "Compulsory field - Rounding not found as an identifier",
        #                              'status': 401})

        uom_vals = {
            'name': post.get('name', False),
            'category_id': 1,
            'uom_type': post.get('uom_type', False),
        }

        if post.get('active'):
            if post.get('active') == 'True':
                uom_vals.update({'active': True})
            if post.get('active') == 'False':
                uom_vals.update({'active': False})

        # if post.get('factor_inv'):
        #     uom_vals.update({'factor_inv': post.get('factor_inv')})
        # if post.get('rounding'):
        #     uom_vals.update({'rounding': post.get('rounding')})

        try:
            new_uom = request.env['uom.uom'].sudo().create(uom_vals)
        except Exception as exception:
            return invalid_response({'message': "Uom creation failed!",
                                     'details': str(exception),
                                     'status': 401})

        return valid_response({'message': "Uom Successfully Created",
                               'status': 200,
                               'odoo_partner': new_uom.name})

    @validate_token
    @http.route("/odoo/uom", methods=["PUT"], type="http",
                auth="none", csrf=False)
    def edit_uom(self, **post):
        Uom = request.env['uom.uom']
        existing_uom = Uom.search([('name', '=', post.get('name')), '|', ('active', '=', True), ('active', '=', False)])

        if not existing_uom:
            return invalid_response({
                'message': "Uom Record Not Found! Please check in Odoo System",
                'status': 401})

        uom_vals = {
            'name': post.get('name', False),
            'category_id': 1,
            'uom_type': post.get('uom_type', False),
            'rounding': post.get('rounding', False),
        }

        if post.get('active'):
            if post.get('active') == 'True':
                uom_vals.update({'active': True})
            if post.get('active') == 'False':
                uom_vals.update({'active': False})

        filtered_uom_vals = dict(filter(lambda elem: elem[1] is not False and elem[0] == 'active', uom_vals.items()))

        existing_uom.write(filtered_uom_vals)

        return valid_response({'message': "Uom Update Sucessfully",
                               'status': 200})


"""Fill excel file with cells missing in atoll."""

from openpyxl import Workbook

def fill_sheet(sheet, missed_cells):
    """
    Fill the excel sheet with missed cells.

    Args:
        sheet: openpyxl sheet object
        missed_cells: list
    """
    if not missed_cells:
        return
    columns = missed_cells[0]._fields

    row = 1
    for col in columns:
        sheet.cell(
            row=row,
            column=columns.index(col) + 1,
            value=col,
        )

    row = 2
    for missed_cell in missed_cells:
        for cell_val in missed_cell:
            sheet.cell(
                row=row,
                column=missed_cell.index(cell_val) + 1,
                value=cell_val,
            )
        row += 1

def fill_excel(selected_data, path):
    """
    Fill excel file with missed in atoll cells, each technology to separate sheet.

    Args:
        selected_data: dict
        path: string
    """
    work_book = Workbook()

    for tech, missed_cells in selected_data.items():
        work_sheet = work_book.create_sheet(tech)
        fill_sheet(work_sheet, missed_cells)

    del work_book['Sheet']
    work_book.save(path)