import numpy as np
import torchio as tio
from matplotlib import pyplot as plt
from torch.utils.data import DataLoader
import nibabel as nib
from torchvision import transforms
from data_utils import get_data_pathes

class RandomSliceVolume(object):
    """Slice a portion of fixed size from the volume
      return a slice of size "slice_size" in the -4 dimension of the sample.
    """
    def __init__(self, slice_size=48):
        self.slice_size = slice_size

    def __call__(self,  image):
        if image.shape[-1] > self.slice_size:
            start_slice = np.random.randint(0, image.shape[-1] - self.slice_size)
            end_slice = start_slice + self.slice_size - 1

            image = image[..., start_slice:end_slice + 1]

        return image

def tio_to_tensor(subject):
    return {'ct': subject.ct.tensor.permute(0, 3, 1, 2)[0],
            'gt': subject.gt.tensor.permute(0, 3, 1, 2)[0],
            'case_name': subject.case_name}

def get_transforms(slice_size, resize):
    train_transforms = [
        tio.CropOrPad(mask_name='gt'),
        tio.ToCanonical(),
        tio.RandomAnisotropy(p=0.25),                            # resample axial dimension (could be faster after crio)
        tio.Lambda(RandomSliceVolume(slice_size=slice_size)),
        tio.CropOrPad((resize, resize, slice_size)),
        tio.RescaleIntensity((-1, 1)),
        tio.RandomBlur(p=0.25),  # blur 25% of times
        tio.RandomNoise(p=0.25),  # Gaussian noise 25% of times
        # tio.OneOf({  # either
        #     tio.RandomAffine(): 0.7,  # random affine
        #     tio.RandomElasticDeformation(): 0.3,  # or random elastic deformation
        # }, p=0.8),  # applied to 80% of images
        tio_to_tensor
    ]

    val_transforms = [
        # augmentations.Resize(resize),
    ]
    return transforms.Compose(train_transforms), transforms.Compose(val_transforms)

def get_datasets(data_root, val_perc, slice_size, resize):
    data_paths = get_data_pathes(data_root)
    subjects = [
        tio.Subject(ct=tio.ScalarImage(ct_path),
                    gt=tio.LabelMap(gt_path),
                    case_name=os.path.splitext(os.path.basename(ct_path))[0])
        for (ct_path, gt_path) in data_paths
    ]

    train_transforms, val_transforms = get_transforms(slice_size, resize)
    n_val = int(len(data_paths) * val_perc)
    tarin_set = tio.SubjectsDataset(subjects[n_val:], transform=train_transforms)
    val_set = tio.SubjectsDataset(subjects[:n_val], transform=val_transforms)
    return tarin_set, val_set

def get_dataloaders(data_root, val_perc, params, slice_size=1, resize=256):
    """
    Get dataloaders for training and evaluation.
    train_by_volume: 3d/2d training returns full CT volumes (batch_size, slices, H, W) or (batch_size, H, W)
    """
    train_set, val_set = get_datasets(data_root, val_perc, slice_size, resize)

    train_loader = DataLoader(train_set, shuffle=True, **params)
    params['batch_size'] = 1
    val_loader = DataLoader(val_set, shuffle=True, **params)

    return train_loader, val_loader

# @title Visualization functions
def get_bounds(self):
    """Get image bounds in mm.

    Returns:
        np.ndarray: [description]
    """
    first_index = 3 * (-0.5,)
    last_index = np.array(self.spatial_shape) - 0.5
    first_point = nib.affines.apply_affine(self.affine, first_index)
    last_point = nib.affines.apply_affine(self.affine, last_index)
    array = np.array((first_point, last_point))
    bounds_x, bounds_y, bounds_z = array.T.tolist()
    return bounds_x, bounds_y, bounds_z

def to_pil(image):
    from PIL import Image
    from IPython.display import display
    data = image.numpy().squeeze().T
    data = data.astype(np.uint8)
    image = Image.fromarray(data)
    w, h = image.size
    display(image)
    print()  # in case multiple images are being displayed

def stretch(img):
    p1, p99 = np.percentile(img, (1, 99))
    from skimage import exposure
    img_rescale = exposure.rescale_intensity(img, in_range=(p1, p99))
    return img_rescale

def show_subject_slice(subject, stretch_slices=True, parcellation=True):
    print(subject.ct.data.shape)
    subject = tio.ToCanonical()(subject)

    def flip(x):
        return np.rot90(x)

    fig, axes = plt.subplots(2, 3, figsize=(12, 8))

    half_shape = torch.Tensor(subject.spatial_shape) // 2
    i, j, k = half_shape.long()
    # i -= 5  # use a better slice

    bounds_x, bounds_y, bounds_z = get_bounds(subject.ct)  ###

    orientation = ''.join(subject.ct.orientation)
    if orientation != 'RAS':
        import warnings
        warnings.warn(f'Image orientation should be RAS+, not {orientation}+')

    kwargs = dict(cmap='gray', interpolation='none')
    data = subject['ct'].data
    slices = data[0, i], data[0, :, j], data[0, ..., k]
    if stretch_slices:
        slices = [stretch(s.numpy()) for s in slices]
    sag, cor, axi = slices

    axes[0, 0].imshow(flip(sag), extent=bounds_y + bounds_z, **kwargs)
    axes[0, 1].imshow(flip(cor), extent=bounds_x + bounds_z, **kwargs)
    axes[0, 2].imshow(flip(axi), extent=bounds_x + bounds_y, **kwargs)

    kwargs = dict(interpolation='none')
    data = subject.gt.data
    slices = data[0, i], data[0, :, j], data[0, ..., k]
    if parcellation:
        sag, cor, axi = [colorize(s.long()) for s in slices]
    else:
        sag, cor, axi = slices
    axes[1, 0].imshow(flip(sag), extent=bounds_y + bounds_z, **kwargs)
    axes[1, 1].imshow(flip(cor), extent=bounds_x + bounds_z, **kwargs)
    axes[1, 2].imshow(flip(axi), extent=bounds_x + bounds_y, **kwargs)

    plt.tight_layout()
    plt.show()

def colorize(label_map):
    rgb = np.stack(3 * [label_map], axis=-1)
    rgb[label_map == 1] = (0, 0, 255)
    rgb[label_map == 2] = (255, 0, 0)
    return rgb

if __name__ == '__main__':
    from torchvision.utils import save_image
    import torch
    from datasets.visualize_data import overlay
    import os

    outputs_dir = "visualize_augmentations"
    os.makedirs(outputs_dir, exist_ok=True)
    # data_path = 'datasets/LiverData_(S-1_MS-(3, 30, 30)RL-True_CL-1_margins-(1, 1, 1)_OB-0.5_MD-7)'
    # data_path = r'/home/ariel/projects/MedicalImageSegmentation/CTSegmentation-Pytorch/datasets/LiverData_(S-1_MS-(3, 30, 30)_RL-True_CP-CL-1_margins-(1, 1, 1)_OB-0.5_MD-7)'
    data_path = '/home/ariel/projects/MedicalImageSegmentation/data/LiverTumorSegmentation/raw_data'
    params = dict(batch_size=1, num_workers=0)
    train_loader, _ = get_dataloaders(data_path, val_perc=0.1, params=params, slice_size=16, resize=400)

    for sample in train_loader:
        ct = sample['ct'][0]
        gt = sample['gt'][0]
        case_name = sample['case_name'][0]

        raw = overlay(ct, gt * 0)
        gt_vis = overlay(ct, gt)
        imgs = torch.cat([raw, gt_vis], dim=-1)
        for s in range(ct.shape[0]):
            save_path = os.path.join(outputs_dir, f"Case-{case_name}-slice-{s}_.png")
            save_image(imgs[s], save_path, normalize=True)


# Date: 2023-03-19
# Description: path planning algorithms and user interface
#-----------------------------------------------------------------------------

# Load external modules
import cv2 # OpenCV
import matplotlib # all of Matplotlib
from matplotlib import pyplot as plt # Matplotlib plotting functionality
matplotlib.rcParams['toolbar'] = 'toolmanager' # toolbar functionality
from matplotlib.backend_tools import ToolBase,ToolToggleBase # toolbar functionality
import numpy as np # Numpy toolbox
import pandas # data handling toolbox
import sys # access to Windows OS
import tkinter as tk # TkInter UI backbone

# Load remaining user modules
import GeneralSupportFunctions as gensup # general support functions

# Hardcoded directory paths
dirPvars = '../vars/' # persistent variables directory

# Load persistent variables
from Constants import(dispRes,
                      softwareName,
                      guiColor_black,
                      guiColor_offwhite,
                      guiColor_hotgreen,
                      guiColor_hotyellow,
                      guiFontSize_large,
                      guiFontType_normal)

#-----------------------------------------------------------------------------

def pathSolution(path):
    """
    Generates a smooth path based on a set of waypoints
    Args:
        path: robot path
    Returns:
        path: the updated robot path
    """

    # Characterize the turns
    ways_clock = [None]
    ways_gamma = [None]
    ways_dbt = [None]
    for i in range(1,path.numWayPoints()-1,1):

        # Get the coordinates of the relevant waypoints
        ax = path.ways_x[i-1]
        ay = path.ways_y[i-1]
        bx = path.ways_x[i]
        by = path.ways_y[i]
        cx = path.ways_x[i+1]
        cy = path.ways_y[i+1]

        # Calculate the angle between the segments
        dotproduct = (ax-bx)*(cx-bx)+(ay-by)*(cy-by)
        mag_ba = np.sqrt(((ax-bx)**2)+((ay-by)**2))
        mag_bc = np.sqrt(((cx-bx)**2)+((cy-by)**2))
        theta = np.arccos(dotproduct/(mag_ba*mag_bc))
        theta_half = theta/2

        # Calculate the angle from the x-axis to the line bisecting the segments
        alpha_bc = np.arctan2((cy-by),(cx-bx))
        crossproduct = (ax-bx)*(cy-by)-(ay-by)*(cx-bx)
        if(crossproduct<0):
            clock = 1
            gamma = alpha_bc+theta_half
        else:
            clock = -1
            gamma = alpha_bc-theta_half
        ways_gamma.append(gamma)
        ways_clock.append(clock)

        # Calculate transition distance along the linear segments
        dbt = path.ways_R[i]/np.tan(theta_half)
        ways_dbt.append(dbt)

    # The last waypoint never has any smoothing
    ways_clock.append(None)
    ways_gamma.append(None)
    ways_dbt.append(None)

    # Generate the dense position points
    idxs_smooth = [1] # the waypoint the smooth point is trying to reach
    ptxs_smooth = [path.ways_x[0]]
    ptys_smooth = [path.ways_y[0]]
    tchs_smooth = [0]
    section = 'middle'
    rx = None
    ry = None
    kappa = None
    for i in range(0,path.numWayPoints()-1,1):

        # Get the coordinates of the relevant waypoints
        ax = path.ways_x[i]
        ay = path.ways_y[i]
        bx = path.ways_x[i+1]
        by = path.ways_y[i+1]

        # Get the relevant turn information
        dat_beg = ways_dbt[i]
        clock_beg = ways_clock[i]
        R_beg = path.ways_R[i]
        delta_kappa_beg = path.step_size/R_beg
        dbt_end = ways_dbt[i+1]
        gamma_end = ways_gamma[i+1]
        clock_end = ways_clock[i+1]
        R_end = path.ways_R[i+1]
        delta_kappa_end = path.step_size/R_end

        # Reset the next segment flag
        flag_nxt = False

        # Check that the waypoints aren't closer than the step size
        dw = np.sqrt(((bx-ax)**2)+((by-ay)**2))
        if(dw>path.step_size):
            timeout = 0
            while(True):

                # Check and update the timeout counter
                if(timeout>10000): raise Exception('no solution')
                timeout += 1

                if(section=='begarc'):

                    # Find the arc center
                    # has not moved from previous arcend

                    # Determine the angle to start at
                    # pick up where you left off from previous arcend

                    # Calculate the transition point
                    alpha_ab = np.arctan2((by-ay),(bx-ax))
                    tx = ax+dat_beg*np.cos(alpha_ab)
                    ty = ay+dat_beg*np.sin(alpha_ab)

                    # Calculate the next point on the arc and increment
                    nx = rx+R_beg*np.cos(kappa)
                    ny = ry+R_beg*np.sin(kappa)
                    kappa += clock_beg*delta_kappa_beg

                    # Check for the transition of the arc
                    dotproduct = (nx-rx)*(tx-rx)+(ny-ry)*(ty-ry)
                    mag_rn = np.sqrt(((nx-rx)**2)+((ny-ry)**2))
                    mag_rt = np.sqrt(((tx-rx)**2)+((ty-ry)**2))
                    theta = np.arccos(dotproduct/(mag_rn*mag_rt))
                    if(theta<=delta_kappa_beg):
                        section = 'middle'

                if(section=='middle'):

                    # Calculate the next point
                    alpha_ab = np.arctan2((by-ay),(bx-ax))
                    dx = path.step_size*np.cos(alpha_ab)
                    dy = path.step_size*np.sin(alpha_ab)
                    nx = ptxs_smooth[-1]+dx
                    ny = ptys_smooth[-1]+dy

                    # Calculate remaining linear distance to the next way point
                    dab = np.sqrt(((bx-nx)**2)+((by-ny)**2))

                    # Check if we are at the end of this segment
                    if(dab<=path.step_size): flag_nxt = True

                    # Check if we should start arcing
                    if(not flag_nxt):
                        if(dbt_end is not None):
                            if(dab<=dbt_end):
                                kappa = None
                                section = 'endarc'

                if(section=='endarc'):

                    # Find the arc center
                    dbr = np.sqrt((dbt_end**2)+(R_end**2))
                    rx = bx+dbr*np.cos(gamma_end)
                    ry = by+dbr*np.sin(gamma_end)

                    # Determine the angle to start at
                    if(kappa is None):
                        kappa = np.arctan2((ny-ry),(nx-rx))

                    # Calculate the next point on the arc and increment
                    nx = rx+R_end*np.cos(kappa)
                    ny = ry+R_end*np.sin(kappa)
                    kappa += clock_end*delta_kappa_end

                    # Check for the end of the arc
                    dotproduct = (nx-rx)*(bx-rx)+(ny-ry)*(by-ry)
                    mag_rn = np.sqrt(((nx-rx)**2)+((ny-ry)**2))
                    mag_rb = np.sqrt(((bx-rx)**2)+((by-ry)**2))
                    theta = np.arccos(dotproduct/(mag_rn*mag_rb))
                    if(theta<=delta_kappa_end):
                        section = 'begarc'
                        flag_nxt = True

                # Insert the next point in the path
                idxs_smooth.append(i+1)
                ptxs_smooth.append(nx)
                ptys_smooth.append(ny)
                if(flag_nxt):
                    if(path.ways_T[i+1]>0.5): tchs_smooth.append(1)
                    else: tchs_smooth.append(0)
                else: tchs_smooth.append(0)

                # Check if this segment of the path is complete
                if(flag_nxt): break

        else: section = 'middle'

        # The next dense point is the next waypoint if there was no arc
        if(section=='middle'):
            idxs_smooth.append(min(i+2,path.numWayPoints()-1))
            ptxs_smooth.append(path.ways_x[i+1])
            ptys_smooth.append(path.ways_y[i+1])
            tchs_smooth.append(0)

    # Calculate the distances along the path and for each segment
    ds_seg = 0
    wayNum = 1
    dsts_segs = [0]
    dsts_smooth = [0]
    for i in range(1,len(ptxs_smooth),1):

        # Calculate the the change in distance along the path since the last smooth point
        ax = ptxs_smooth[i-1]
        ay = ptys_smooth[i-1]
        bx = ptxs_smooth[i]
        by = ptys_smooth[i]
        ds = np.sqrt(((bx-ax)**2)+((by-ay)**2))

        # Total distance along the path
        ds_total = dsts_smooth[-1] + ds
        dsts_smooth.append(ds_total)

        # Distance along the path in the current segment
        ds_seg += ds

        # Save the distances for each segment
        if(idxs_smooth[i]!=wayNum):
            dsts_segs.append(ds_seg)
            ds_seg = 0
            wayNum += 1

    # Store the distance for the final segment
    dsts_segs.append(ds_seg)

    # Calculate the smooth velocities
    wayNum = 0
    v_running = path.ways_v[0] # intialize to start velocity
    vels_smooth = [v_running]
    for i in range(1,len(ptxs_smooth),1):

        if(idxs_smooth[i]!=wayNum):

            # Determine the requested delta v
            wayNum += 1
            v_goal = path.ways_v[wayNum]
            delta_v_req = v_goal-v_running

            # Travel distance available in this segment
            delta_s_seg = dsts_segs[wayNum]

            # Handle acceleration limiting
            if(delta_v_req>0):

                # Calculate the maximum delta v permitted
                delta_v_max = -v_running+np.sqrt((v_running**2)+(2*path.a_max*delta_s_seg))

                # Accelerate as fast as possible if we missed the previous velocity waypoint
                if(v_running<path.ways_v[wayNum-1]):
                    delta_v_okay = delta_v_max
                else:
                    delta_v_okay = min(delta_v_req,delta_v_max)

            else:

                # No decceleration limit
                delta_v_okay = delta_v_req

            # Normalize the delta v per unit distance
            delta_v_per_s = delta_v_okay/delta_s_seg

        # Update the robot's current velocity
        delta_s = dsts_smooth[i]-dsts_smooth[i-1]
        v_running += delta_v_per_s*delta_s
        if(delta_v_req>0): v_running = min(v_running,v_goal)
        else: v_running = max(v_running,v_goal)
        vels_smooth.append(v_running)

    # Impliment instantaneous acceleration/decceleration below 12.0 in/s
    for i in range(1,len(ptxs_smooth)-1,1):
        if(idxs_smooth[i]==idxs_smooth[i+1]):
            vels_smooth[i] = max(12.0,vels_smooth[i])
    vels_smooth[0] = max(vels_smooth[0],12.0) # prevent a velocity lower than 12.0 in/s on the first point

    # Calculate the smooth times
    t_total = 0 # total time that the robot has been traveling
    tims_smooth = [t_total]
    for i in range(1,len(ptxs_smooth),1):

        # Calculate the time elapsed in the current step
        delta_s = dsts_smooth[i]-dsts_smooth[i-1]
        v_avg = 0.5*(vels_smooth[i]+vels_smooth[i-1])
        delta_t = delta_s/v_avg

        # Update the total time
        t_total += delta_t
        tims_smooth.append(t_total)

    # Calculate the smooth orientations
    wayNum = 0
    o_running = path.ways_o[0] # intialize to start orientation
    oris_smooth = []
    omgs_smooth = []
    for i in range(1,len(ptxs_smooth),1):

        if(idxs_smooth[i]!=wayNum):

            # Start of a new segement, fix any accumulated issues
            o_running = path.ways_o[wayNum]
            try: oris_smooth[-1] = path.ways_o[wayNum]
            except: pass # handle first point

            # Determine the requested delta o
            wayNum += 1
            o_goal = path.ways_o[wayNum]
            if(o_goal>o_running):
                delta_oseg1 = o_goal-o_running
                delta_oseg2 = 360 - delta_oseg1
                if(delta_oseg1<delta_oseg2): delta_o = delta_oseg1
                else: delta_o = -delta_oseg2
            else:
                delta_oseg1 = o_running-o_goal
                delta_oseg2 = 360 - delta_oseg1
                if(delta_oseg1<delta_oseg2): delta_o = -delta_oseg1
                else: delta_o = delta_oseg2

            # Travel time available in this segment
            t_seg_start = tims_smooth[i]
            for ii in range(i,len(ptxs_smooth),1):
                if(idxs_smooth[ii]!=wayNum): break
            t_seg_end = tims_smooth[ii]
            delta_t_seg = t_seg_end - t_seg_start
            delta_t_cruise = path.omega_fraction*delta_t_seg
            delta_t_linear = 0.5*(delta_t_seg - delta_t_cruise)
            t_seg_accel = t_seg_start + delta_t_linear
            t_seg_decel = t_seg_accel + delta_t_cruise

            # Calculate the cruising rotational velocity
            omega_cruise = 2*delta_o/((1+path.omega_fraction)*delta_t_seg)

        # Calculate the feed-forward rotational velocity
        t_i = tims_smooth[i]
        if(t_i<=t_seg_accel):
            omega_i = 0 + omega_cruise*(t_i-t_seg_start)/(t_seg_accel-t_seg_start) # acceleration phase
        elif((t_i>t_seg_accel)&(t_i<t_seg_decel)):
            omega_i = omega_cruise # cruise phase
        else:
            omega_i = omega_cruise - omega_cruise*(t_i-t_seg_decel)/(t_seg_end-t_seg_decel) # deceleration phase
        omgs_smooth.append(omega_i)

        # Update the robot's current orientation
        try: delta_o_i = omega_i*(tims_smooth[i+1]-tims_smooth[i])
        except: delta_o_i = 0
        o_running += delta_o_i
        oris_smooth.append(o_running%360)

    # Ensure that the final feed-forward velocity is zero
    omgs_smooth.append(0)
    oris_smooth.append(o_running%360)

    # Update the path
    path.updateSmoothPath(ptxs_smooth,ptys_smooth,vels_smooth,oris_smooth,dsts_smooth,tims_smooth,tchs_smooth,omgs_smooth)

    return path

#-----------------------------------------------------------------------------

def popupPtData(path,x_prior,y_prior,flag_newPt):
    """
    Creates a pop-up window that allows a user to create or edit a waypoint
    Args:
        path: robot path
        x_prior: (pixels) the x coordinate of the user's mouse click
        y_prior: (pixels) the y coordinate of the user's mouse click
        flag_newPt: True if this is a new point
    Returns:
        path: the updated robot path
    """

    # Configure waypoint selection
    [x_init,y_init,v_init,o_init,R_init,T_init,way_index] = path.configureWayPoint(x_prior,y_prior,flag_newPt)
    if(way_index!=-1): way_order = way_index
    else: way_order = path.numWayPoints()

    # Define button callbacks
    def actionClose(*args):

        # userEntry = entry0.get()
        popwindow.unbind('<Return>')
        popwindow.quit()
        popwindow.destroy()

    def actionSave(*args):

        # Check entries for errors
        flags = True
        [O_way,flags] = gensup.safeTextEntry(flags,textFields[0]['field'],'int',vmin=0,vmax=path.numWayPoints())
        [x_way,flags] = gensup.safeTextEntry(flags,textFields[1]['field'],'float',vmin=-path.field_x_real,vmax=path.field_x_real)
        [y_way,flags] = gensup.safeTextEntry(flags,textFields[2]['field'],'float',vmin=-path.field_y_real,vmax=path.field_y_real)
        [v_way,flags] = gensup.safeTextEntry(flags,textFields[3]['field'],'float',vmin=path.v_min/12.0,vmax=path.v_max/12.0)
        [o_way,flags] = gensup.safeTextEntry(flags,textFields[4]['field'],'float',vmin=0.0,vmax=360.0)
        [R_way,flags] = gensup.safeTextEntry(flags,textFields[5]['field'],'float',vmin=3*path.step_size)
        [T_way,flags] = gensup.safeTextEntry(flags,textFields[6]['field'],'bool')
        if(T_way): T_way = 1
        else: T_way = 0

        # Perform any requested waypoint flips ***
        if(x_way<0): x_way += path.field_x_real
        if(y_way<0): y_way += path.field_y_real

        # Save the error-free entries in the correct units
        if(flags):

            # Add way point
            path.addWayPoint(x_way,y_way,v_way*12,o_way,R_way,T_way,way_index,O_way)

            # Close the popup
            actionClose()

    def actionDelete(*args):

        # Remove a way point
        path.removeWayPoint(way_index)
        actionClose()

    # Define the popup window
    popwindow = tk.Toplevel()
    popwindow.title('Waypoint')
    windW = 300 # window width
    windH = 500 # window height
    popwindow.geometry(str(windW)+'x'+str(windH))
    popwindow.configure(background=guiColor_offwhite)
    popwindow.resizable(width=False, height=False)

    # Set the initial window location
    popwindow.geometry("+{}+{}".format(int(0.5*(popwindow.winfo_screenwidth()-windW)),int(0.5*(popwindow.winfo_screenheight()-windH))))

    # Configure to handle use of the Windows close button
    popwindow.protocol('WM_DELETE_WINDOW',actionClose)

    # Define the fields
    fieldNames = ['Order',
                  'X Position (in)',
                  'Y Position (in)',
                  'Velocity (ft/s)',
                  'Orientation (deg) [0-360]',
                  'Turn Radius (in)',
                  'Touch this Point']
    defaults = [way_order,
                x_init,
                y_init,
                v_init,
                o_init,
                R_init,
                T_init>0.5]

    # Set up the elements
    textFields = []
    for i in range(0,len(fieldNames),1):
        spacer = tk.Label(popwindow,text='',bg=guiColor_offwhite,font=(guiFontType_normal,2),anchor='w')
        [title,field] = gensup.easyTextField(popwindow,windW,fieldNames[i],str(defaults[i]))
        textFields.append({'title': title, 'field': field, 'spacer': spacer})
    if(way_index==-1): buttonName = 'Create'
    else: buttonName = 'Edit'
    if(way_index==-1): textFields[0]['field'].configure(state=tk.DISABLED)
    buttonSave = tk.Button(popwindow,text=buttonName,fg=guiColor_black,bg=guiColor_hotgreen,font=(guiFontType_normal,guiFontSize_large),height=1,width=int(0.04*windW),command=actionSave)
    popwindow.bind('<Return>',actionSave)
    buttonDelete = tk.Button(popwindow,text='Delete',fg=guiColor_black,bg=guiColor_hotyellow,font=(guiFontType_normal,guiFontSize_large),height=1,width=int(0.04*windW),command=actionDelete)

    # Place all elements
    for i in range(0,len(textFields),1):
        textFields[i]['title'].pack(fill='both')
        textFields[i]['field'].pack()
        textFields[i]['spacer'].pack()
    buttonSave.pack(pady=5,fill='x')
    buttonDelete.pack(pady=5,fill='x')

    # Run the GUI
    popwindow.mainloop()

    return path

#-----------------------------------------------------------------------------

def loadRobot(file_robot,scale_pi):
    """
    Loads the robot model
    Args:
        file_robot: file path to the robot model
        scale_pi: (pix/in) unit conversion factor for the field
    Returns:
        I_robot: image of the robot model
    """

    try:

        # Load the robot model
        I_robot = cv2.imread(file_robot,cv2.IMREAD_COLOR)
        I_robot = gensup.convertColorSpace(I_robot) # fix image coloring

        # Recover the robot dimensions
        filename = file_robot.split('/')[-1]
        filename = filename.split('.')[0]
        dimensions = filename.split('_')
        robot_x = float(dimensions[1].replace('-','.')) # (in) robot length
        robot_y = float(dimensions[2].replace('-','.')) # (in) robot width
        robot_x = int(np.round(robot_x*scale_pi,0)) # (pix)
        robot_y = int(np.round(robot_y*scale_pi,0)) # (pix)

        # Resize the robot model
        I_robot = cv2.resize(I_robot,(robot_x,robot_y)) # resize the image

        # Pad the robot model for later rotation
        pad_v = I_robot.shape[0]//2
        pad_h = I_robot.shape[1]//2
        I_robot = cv2.copyMakeBorder(I_robot,pad_v,pad_v,pad_h,pad_h,cv2.BORDER_CONSTANT,value=[255,255,255])

    except:

        # default robot model
        I_robot = 255*np.ones((10,10,3),np.uint8)

    return I_robot

#-----------------------------------------------------------------------------

def overlayRobot(I_in,I_robot_in,alliance,scale_pi,field_y_pixels,center_x,center_y,theta):
    """
    Overlays the robot model on top of the field image
    Args:
        I_in: image of the field map
        I_robot_in: image of the robot model
        alliance: ['red','blue'] specifies the alliance
        scale_pi: (pix/in) unit conversion factor for the field
        field_y_pixels: (pix) width of the field
        center_x: (in) x coordinate of the robot center
        center_y: (in) y coordinate of the robot center
        theta: (deg) rotation angle for the robot
    Returns:
        I: fused image of the field map and the robot model
    """

    # Handle OpenCV ghost assignments
    I = np.copy(I_in)
    I_robot = np.copy(I_robot_in)

    # Re-color the robot based on the current alliance
    locs_robot = ~((I_robot[:,:,0]>=225) & (I_robot[:,:,1]>=225) & (I_robot[:,:,2]>=225))
    if(alliance=='red'):
        I_robot[locs_robot,0] = 255
        I_robot[locs_robot,1] = 0
        I_robot[locs_robot,2] = 0
    else:
        I_robot[locs_robot,0] = 0
        I_robot[locs_robot,1] = 0
        I_robot[locs_robot,2] = 255

    # Convert the coordinates into pixels
    center_x = scale_pi*center_x
    center_y = field_y_pixels - scale_pi*center_y
    tx = center_x - 0.5*I_robot.shape[1] # shift for the center of the robot
    ty = center_y - 0.5*I_robot.shape[0] # shift for the center of the robot
    tx = int(np.round(tx,0))
    ty = int(np.round(ty,0))

    # Rotate the robot model about its center
    M_rot = cv2.getRotationMatrix2D((I_robot.shape[1]//2,I_robot.shape[0]//2),theta,1.0)
    I_robot = cv2.warpAffine(I_robot,M_rot,(I.shape[1],I.shape[0]))

    # Translate the robot model
    M_trans = np.float32([[1,0,tx],[0,1,ty]])
    I_robot = cv2.warpAffine(I_robot,M_trans,(I.shape[1],I.shape[0]))

    # Find the background pixel locations and make them transparent in the robot image
    locs_background = (I_robot[:,:,0]>=225) & (I_robot[:,:,1]>=225) & (I_robot[:,:,2]>=225)
    I_robot[locs_background,0] = 0
    I_robot[locs_background,1] = 0
    I_robot[locs_background,2] = 0

    # Find the foreground pixel locations and make them transparent in the field image
    locs_foreground = (I_robot[:,:,0]>=30) | (I_robot[:,:,1]>=30) | (I_robot[:,:,2]>=30)
    I[locs_foreground,0] = 0
    I[locs_foreground,1] = 0
    I[locs_foreground,2] = 0

    # Fuse the two images
    I = I + I_robot

    return I

#-----------------------------------------------------------------------------

def definePath(path_loaded,alliance,file_I,file_robot,buttonPlan,file_red,file_blue):
    """
    Allows the user to define an autonomous path
    Args:
        path_loaded: loaded robot path
        alliance: ['red','blue'] specifies the alliance
        file_I: file path to the field map image
        file_robot: file path to the robot model
        buttonPlan: handle for the path planning button
        file_red: path to the red-side calibration points
        file_blue: path to the blue-side calibration points
    Returns:
        None
    """

    # Initialize the path with the loaded path
    global path
    path = path_loaded

    # Load the field image
    I = cv2.imread(file_I,cv2.IMREAD_COLOR) # load the selected image
    I = cv2.resize(I,(int(dispRes*path.field_x_real),int(dispRes*path.field_y_real))) # resize the image
    I = gensup.convertColorSpace(I) # fix image coloring
    if(alliance=='blue'): I = cv2.rotate(I,cv2.ROTATE_180) # rotate the field image

    # Calculate the scaling
    path.fieldScale(I)

    # Load the robot model
    I_robot = loadRobot(file_robot,path.scale_pi)

    # Display the field image
    global h_im,h_fig
    [h_fig,h_im,ax,_] = gensup.smartRealImageDisplay(I,[path.field_x_real,path.field_y_real],path.loaded_filename,
                                                      flag_grid=True,
                                                      origin='bottomleft',x_real='X: Down Field',y_real='Y: Side Field',
                                                      units='in')

    try:

        # Load the field calibration points
        df_red = pandas.read_csv(file_red)
        points_x_red = np.array(list(df_red['X (in)'].values)).astype(float)
        points_y_red = np.array(list(df_red['Y (in)'].values)).astype(float)
        points_ref_x_red = np.array(list(df_red['Ref X (in)'].values)).astype(float)
        points_ref_y_red = np.array(list(df_red['Ref Y (in)'].values)).astype(float)

        # Convert the field calibration points
        points_x_red += points_ref_x_red
        points_y_red += points_ref_y_red
        points_x_red *= path.scale_pi
        points_y_red = path.field_y_pixels-points_y_red*path.scale_pi

        # Render the field calibration points
        ax.scatter(points_x_red,points_y_red,c='r',marker='+',s=400)

    except: pass

    try:

        # Load the field calibration points
        df_blue = pandas.read_csv(file_blue)
        points_x_blue = np.array(list(df_blue['X (in)'].values)).astype(float)
        points_y_blue = np.array(list(df_blue['Y (in)'].values)).astype(float)
        points_ref_x_blue = np.array(list(df_red['Ref X (in)'].values)).astype(float)
        points_ref_y_blue = np.array(list(df_red['Ref Y (in)'].values)).astype(float)

        # Convert the field calibration points
        points_x_blue += points_ref_x_blue
        points_y_blue += points_ref_y_blue
        points_x_blue *= path.scale_pi
        points_y_blue = path.field_y_pixels-points_y_blue*path.scale_pi

        # Render the field calibration points
        ax.scatter(points_x_blue,points_y_blue,c='b',marker='+',s=400)

    except: pass

    # Define global variables
    global flag_toolwaypoint
    flag_toolwaypoint = 1
    global flag_risingEdge
    flag_risingEdge = False
    global flag_adding
    flag_adding = False
    global h_ways
    h_ways = None
    global h_smooths
    h_smooths = None
    global hs_ori
    hs_ori = []
    global flag_newchanges
    flag_newchanges = False
    global firstclick
    firstclick = None

    # Watch for window close event
    def actionWindowClose(evt):
        global flag_newchanges

        # Save the path
        if(flag_newchanges): savePath()

        # Reset the GUI
        buttonPlan.configure(bg=guiColor_hotgreen,state=tk.NORMAL)

    # Set up mouse button click callbacks
    def mouseClick(event):
        global flag_risingEdge,flag_adding,h_fig,flag_newchanges,firstclick
        sys.stdout.flush()
        button = 'LEFT'
        if(flag_toolwaypoint!=0):
            if(str(event.button).find(button)!=-1):
                if(flag_risingEdge==False):
                    flag_risingEdge = True
                    if(flag_toolwaypoint!=4): firstclick = None # make sure to reset
                    if(not flag_adding):

                        # Block additional popups
                        flag_adding = True

                        # Retrieve information about the selected point
                        [x_prior,y_prior] = event.xdata, event.ydata

                        if((flag_toolwaypoint==1)|(flag_toolwaypoint==2)):

                            # Display popup window
                            try:
                                popupPtData(path,x_prior,y_prior,flag_toolwaypoint==1)
                                generatePath()
                                h_fig.canvas.set_window_title(path.loaded_filename+'*')
                                flag_newchanges = True
                                flag_adding = False
                            except: flag_adding = False # ignore

                        elif(flag_toolwaypoint==3):
                            fmt_str = path.probe(x_prior,y_prior)
                            tk.messagebox.showinfo(softwareName,fmt_str)
                            flag_adding = False

                        elif(flag_toolwaypoint==4):
                            if(firstclick is None):
                                firstclick = (x_prior,y_prior)
                            else:
                                path.move(firstclick[0],firstclick[1],x_prior,y_prior)
                                generatePath()
                                h_fig.canvas.set_window_title(path.loaded_filename+'*')
                                flag_newchanges = True
                                firstclick = None
                            flag_adding = False

    # Set up mouse button unclick callbacks
    def mouseUnClick(event):
        global flag_risingEdge
        sys.stdout.flush()
        button = 'LEFT'
        if(flag_toolwaypoint!=0):
            if(str(event.button).find(button)!=-1):
                if(flag_risingEdge==True):
                    flag_risingEdge = False

    def savePath():
        global path,flag_newchanges

        if(path.numWayPoints()>1):

            # Ask the user if they would like to save the path
            filename = gensup.popupTextEntry('save path as',path.loaded_filename)

            if(filename!=''):

                # If the name has changed, ask the user where they would like to save the file
                if((filename=='unamed 1')|(filename!=path.loaded_filename)):
                    path.folder_save = tk.filedialog.askdirectory(initialdir=path.folder_save,title = 'Choose a Location to Save the Path')
                    path.folder_save += '/'

                # Save the .csv file
                nComp = max(0,path.numSmoothPoints()-path.numWayPoints())
                df = pandas.DataFrame(data={"Distance (in)": path.smooths_d,
                                            "Time (s)": path.smooths_t,
                                            "X (in)": path.smooths_x,
                                            "Y (in)": path.smooths_y,
                                            "Velocity (in/s)": path.smooths_v,
                                            "Orientation (deg)": path.smooths_o,
                                            "Touch": path.smooths_T,
                                            "Rotational Velocity (deg/s)": path.smooths_w,
                                            "Way X (in)": path.ways_x + nComp*[''],
                                            "Way Y (in)": path.ways_y + nComp*[''],
                                            "Way Velocity (in/s)": path.ways_v + nComp*[''],
                                            "Way Orientation (deg)": path.ways_o + nComp*[''],
                                            "Way Turn Radius (in)": path.ways_R + nComp*[''],
                                            "Touch this Point": path.ways_T + nComp*['']})
                df.to_csv(path.folder_save+filename+'.csv', sep=',',index=False)

                # Save an image of the path planning figure
                h_fig.savefig(path.folder_save+filename+'.jpg')

                # Update the loaded path name
                path.loaded_filename = filename
                h_fig.canvas.set_window_title(path.loaded_filename)
                flag_newchanges = False

    def generatePath():
        global path,h_im,h_ways,h_smooths,hs_ori

        # Remove the previous plots
        try:

            h_ways.remove()
            h_smooths.remove()
            for h in hs_ori: h[0].remove()
            hs_ori = []
        except: pass

        if(path.numWayPoints()>0):

            # Add the robot model at the starting waypoint
            I_fused = overlayRobot(I,I_robot,alliance,path.scale_pi,path.field_y_pixels,path.ways_x[0],path.ways_y[0],path.ways_o[0])

        if(path.numWayPoints()>1):

            # Add the robot model at the ending waypoint
            I_fused = overlayRobot(I_fused,I_robot,alliance,path.scale_pi,path.field_y_pixels,path.ways_x[-1],path.ways_y[-1],path.ways_o[-1])

        if(path.numWayPoints()>0):

            # Display the robot at the starting and end points
            h_im.remove()
            h_im = ax.imshow(I_fused,vmin=0,vmax=255,interpolation='none',extent=[0,I.shape[1],I.shape[0],0])

        if(path.numWayPoints()>0):

            # Update the way point plots
            if(alliance=='red'): waycolor = 'r'
            else: waycolor = 'b'
            h_ways = ax.scatter(path.scale_pi*np.array(path.ways_x),(path.field_y_pixels)*np.ones((len(path.ways_y)),float) - path.scale_pi*np.array(path.ways_y),
                                facecolors='none',edgecolors=waycolor,marker='o',s=400)

        if(path.numWayPoints()>1):

            # Calculate the path
            try:
                path = pathSolution(path)
                flag_solution = True
            except:
                tk.messagebox.showerror('4265 Path Planner','No pathing solution found, please modify the waypoints')
                flag_solution = False

            if(flag_solution):

                # Display the path metrics
                details_start = 'start at (%0.2f in, %0.2f in, %0.0f°)' %(path.smooths_x[0],path.smooths_y[0],path.smooths_o[0])
                details_end = 'end at (%0.2f in, %0.2f in, %0.0f°) predicted travel time: %0.2f s' %(path.smooths_x[-1],path.smooths_y[-1],path.smooths_o[-1],path.total_t)
                plt.xlabel('X: Down Field (in) \n%s\n%s' %(details_start,details_end))

                # Display the smooth path
                ptColors = []
                for i in range(0,path.numSmoothPoints(),1):
                    if(path.smooths_T[i]>0.5):
                        ptColor = [1,0,0] # color "must touch points red"
                    else: ptColor = plt.cm.jet(path.smooths_v[i]/path.v_max)
                    ptColors.append(np.array([ptColor[0],ptColor[1],ptColor[2]]))
                h_smooths = ax.scatter(path.scale_pi*np.array(path.smooths_x),
                                       (path.field_y_pixels)*np.ones((len(path.smooths_y)),float) - path.scale_pi*np.array(path.smooths_y),
                                       color=np.array(ptColors),marker='.',s=50)

                # Display the orientation overlays
                for i in range(0,path.numSmoothPoints(),1):
                    xa = path.smooths_x[i]*path.scale_pi
                    ya = path.field_y_pixels-(path.smooths_y[i]*path.scale_pi)
                    oa = np.pi*path.smooths_o[i]/180.0
                    xb = xa + (path.step_size*path.scale_pi)*np.cos(oa)
                    yb = ya - (path.step_size*path.scale_pi)*np.sin(oa)
                    hs_ori.append(plt.plot(np.array([xa,xb]),np.array([ya,yb]),color=np.array(ptColors[i])))

    class ToolSavePath(ToolBase):
        description = 'Saves the path'
        default_toggled = False
        image = gensup.absolutePath(dirPvars+'savepath.png')
        def trigger(self,*args):
            savePath()

    class ToolAddWaypoint(ToolToggleBase):
        description = 'Adds a waypoint'
        radio_group = 'default'
        default_toggled = True
        image = gensup.absolutePath(dirPvars+'addwaypoint.png')
        def enable(self,*args):
            global flag_toolwaypoint
            flag_toolwaypoint = 1 # add waypoint tool is selected
        def disable(self,*args):
            global flag_toolwaypoint
            flag_toolwaypoint = 0 # add waypoint tool is deselected

    class ToolEditWaypoint(ToolToggleBase):
        description = 'Edits a waypoint'
        radio_group = 'default'
        default_toggled = False
        image = gensup.absolutePath(dirPvars+'editwaypoint.png')
        def enable(self,*args):
            global flag_toolwaypoint
            flag_toolwaypoint = 2 # edit waypoint tool is selected
        def disable(self,*args):
            global flag_toolwaypoint
            flag_toolwaypoint = 0 # edit waypoint tool is deselected

    class ToolMoveWaypoint(ToolToggleBase):
        description = 'Moves a waypoint'
        radio_group = 'default'
        default_toggled = False
        image = gensup.absolutePath(dirPvars+'movewaypoint.png')
        def enable(self,*args):
            global flag_toolwaypoint
            flag_toolwaypoint = 4 # move waypoint tool is selected
        def disable(self,*args):
            global flag_toolwaypoint
            flag_toolwaypoint = 0 # move waypoint tool is deselected

    class ToolProbePath(ToolToggleBase):
        description = 'Probe the path'
        radio_group = 'default'
        default_toggled = False
        image = gensup.absolutePath(dirPvars+'probe.png')
        def enable(self,*args):
            global flag_toolwaypoint
            flag_toolwaypoint = 3 # probe path tool is selected
        def disable(self,*args):
            global flag_toolwaypoint
            flag_toolwaypoint = 0 # edit waypoint tool is deselected

    # Configure the tool manager
    tm = h_fig.canvas.manager.toolmanager
    h_fig.canvas.manager.toolmanager.remove_tool('help')
    h_fig.canvas.manager.toolmanager.remove_tool('subplots')
    h_fig.canvas.manager.toolmanager.remove_tool('save')

    # Add the new tools to the toolbar
    tm.add_tool('Save Path',ToolSavePath)
    h_fig.canvas.manager.toolbar.add_tool(tm.get_tool('Save Path'),'custom')
    tm.add_tool('Add Waypoint',ToolAddWaypoint)
    h_fig.canvas.manager.toolbar.add_tool(tm.get_tool('Add Waypoint'),'custom')
    tm.add_tool('Edit Waypoint',ToolEditWaypoint)
    h_fig.canvas.manager.toolbar.add_tool(tm.get_tool('Edit Waypoint'),'custom')
    tm.add_tool('Move Waypoint',ToolMoveWaypoint)
    h_fig.canvas.manager.toolbar.add_tool(tm.get_tool('Move Waypoint'),'custom')
    tm.add_tool('Probe Path',ToolProbePath)
    h_fig.canvas.manager.toolbar.add_tool(tm.get_tool('Probe Path'),'custom')

    # Connect the mouse button callbacks
    plt.connect('button_press_event',mouseClick)
    plt.connect('button_release_event',mouseUnClick)
    h_fig.canvas.mpl_connect('close_event', actionWindowClose)

    # First call of the pathing and rendering algorithm
    generatePath()


from __future__ import division
from pocketsphinx.pocketsphinx import *
from os import environ, path, listdir
import sys
import time
import wave
from analyze_text import *

__author__ = 'Emily Ahn and Elizabeth Hau'

''' ******************** speech_to_text.py ************************
    This file takes in an audio file (or multiple files) and uses
    the automatic speech recognition (ASR) system CMUPocketSphinx
    to generate a transcription for the files, writes each of the
    results to a hypothesis file and reports the frequencies of the
    use of filler words ("um" and "uhh" for now) compared to the
    gold standard.
    ***************************************************************
'''
# directory paths
MODELDIR = "/Users/joshuaji/Documents/code/projects/um_detector_api/elizabethhau_emilyahn-finalproject/pocketsphinx-python/pocketsphinx/model"
GOLD_DATADIR = "/home/sravana/data/cslu_fae_corpus/cs349"  # gold standard wav files
DATADIR = "data"  # wav files
HYPDIR = "data/hyp_test"  # stores test hypotheses

# paths to dictionaries
hmmd = '/home/sravana/applications/pocketsphinx-python/pocketsphinx/model/en-us/en-us'
lmd = '/home/sravana/applications/pocketsphinx-python/pocketsphinx/model/en-us/en-us.lm.bin'
dictd = '/home/sravana/applications/pocketsphinx-python/pocketsphinx/model/en-us/cmudict-en-us.dict'

# create a decoder
config = Decoder.default_config()
config.set_string('-hmm', path.join(MODELDIR, 'en-us/'))
config.set_string('-lm', path.join(MODELDIR, 'en-us.lm.bin'))
config.set_string('-dict', path.join(MODELDIR, 'cmudict-en-us.dict'))

def write_hypothesis(outfile, segments):
    ''' Writes the hypothesis file'''
    with open(path.join(HYPDIR, outfile), 'w') as o:
        for word in segments:
            o.write(word+' ')
    o.close()

def decode(datadir, filename):
    ''' Decode streaming data.'''
    decoder = Decoder(config)
    decoder.start_utt()

    stream = open(path.join(datadir, filename), 'rb')

    while True:
        buf = stream.read(1024)
        if buf:
            decoder.process_raw(buf, False, False)
        else:
            break
    decoder.end_utt()
    segments = [seg.word for seg in decoder.seg()]
    f = 'hypothesis-'+filename.split('.')[0]+'.txt'
    print('Best hypothesis segments: ', [seg.word for seg in decoder.seg()])
    write_hypothesis(f, segments)
    return segments

def file_in_correct_format(filename):
    ''' Checks if the provided file is in the correct format
        (i.e. mono channel with a sampling rate of 16000).
        returns True if it is in the correct format and False
        if it isn't. Also prints out an error message if the
        file is not in the correct format
    '''
    wf = wave.open(filename, 'rb')
    # get information about the audio file provided
    channels = wf.getnchannels()
    rate = wf.getframerate()

    # print error message if the format of provided file is incorrect
    if not channels == 1 or not rate == 16000:
        print('ERROR: file provided is not in the correct format. Please provide a mono channel file with a sampling rate of 16000')
        return False
    return True

if __name__ == '__main__':
    global filename
    start = time.time()

    if len(sys.argv) == 2:
        # if one argument provided, it's a filename
        # and assume the data directory is the default data directory
        filename = sys.argv[1]
        if file_in_correct_format(path.join(DATADIR, filename)):
            segments = decode(DATADIR, filename)
            new_list = preprocess_segments(segments)
            ('\n************* RESULTS ****************')
            filler_words(new_list)

    elif len(sys.argv) == 3:
        # if two arguments provided, the first argument will be the data directory and the second the filename
        datadir = sys.argv[1]
        filename = sys.argv[2]

        if file_in_correct_format(path.join(datadir, filename)):
            segments = decode(datadir, filename)
            new_list = preprocess_segments(segments)
            print('\n************* RESULTS ****************')
            filler_words(new_list)
    else:
        # if no args provided, run the decoder on all files in the default DATADIR
        # this assumes there are only .wav files in the directory (not including
        # other directories. throws an error if
        for f in listdir(DATADIR):
            if not f.startswith('.') and path.isfile(path.join(DATADIR, f)):
                if file_in_correct_format(path.join(DATADIR, f)):
                    decode(DATADIR, f)
    end = time.time()
    print('time elapsed:', (end - start))


import random

from pyglet.shapes import Batch
from cv2 import Mat
import pyglet

from Ball import Ball
from Detection import Detection
from AppState import AppState
import Config as C

class Game:
  def __init__(self, width: int, height: int) -> None:
    self.width = width
    self.height = height
    self.batch = Batch()
    self.detection = Detection()
    self.color_list = C.Color.LIST

  def _create_ball(self, *_) -> None:
    colour = random.choice(self.color_list)
    y = random.randint(C.Ball.RADIUS_MAX * 2, self.height - C.Ball.RADIUS_MAX * 2)
    velocity = random.randint(C.Ball.VELOCITY_MIN, C.Ball.VELOCITY_MAX)

    ball = Ball(width=self.width, x=C.Ball.START_X, y=y, velocity=velocity, colour=colour, batch=self.batch)

    self.balls.append(ball)

  def _end_game(self, *_) -> None:
    self.state = AppState.END

  def init(self) -> None:
    self.balls = []
    self.score = 0
    self.state = AppState.START

    pyglet.clock.unschedule(self._create_ball)
    pyglet.clock.schedule_interval(self._create_ball, 1) #create a randomly assigned ball every 1 second
    pyglet.clock.schedule_once(self._end_game, C.Game.GAME_OVER_TIME) #automatically end the game after x seconds

  def run(self, thresh: Mat) -> None:
    for ball in self.balls:
      #code reference: https://github.com/ITT23/assignment-04-markers-and-computer-vision-tina-e/blob/master/ar_game/Ball.py
      hit = thresh[int(self.height - ball.y)][int(ball.x)]

      if hit:
        self.score += 1
        ball.delete()
        self.balls.remove(ball)

      else:
        ball.move()

    self.batch.draw()


#Lab7
# Encode string with ROT13

import string

phrase = list(input("Enter a string: "))

abc = list(string.ascii_lowercase)
print (abc)

new_word = ''

for letter in phrase:
    letter_index = abc.index(letter)
    new_index = letter_index + 13
    #print (new_index)
    if new_index > 25:
        new_index -=  26
        print (new_index)
    cipher = abc[new_index]
    new_word += cipher

    print (cipher)
print(new_word)


import requests
import time
from bs4 import BeautifulSoup
from selenium import webdriver

#Headless 하는 법
options = webdriver.ChromeOptions()
options.headless = True
options.add_argument("window-size=1920x1080")

url = "https://play.google.com/store/movies/top"

browser = webdriver.Chrome(r"C:\Users\CKIRUser\AppData\Roaming\Microsoft\Windows\Start Menu\Programs\Python 3.7\jin\chromedriver.exe", options=options) #options는 여기 붙여주면 됨.

browser.get(url)

interval = 2

prev_height = browser.execute_script("return document.body.scrollHeight")

while True:
    #아래로 스크롤 내리
    browser.execute_script("window.scrollTo(0,document.body.scrollHeight)")
    time.sleep(interval)
    curr_height = browser.execute_script("return document.body.scrollHeight")
    if prev_height == curr_height:
        break
    prev_height = curr_height
print("scroll complete")

soup = BeautifulSoup(browser.page_source,"lxml")

movies = soup.find_all("div", attrs={"class":"Vpfmgd"})

# print(len(movies)) #10개 나옴 -> 태그가 다름

for movie in movies:

    #할인 전 가격
    original_price = movie.find("span", attrs={"class":"SUZt4c djCuy"})
    if original_price:
        original_price = original_price.get_text()
        title = movie.find("div",attrs={"class":"WsMG1c nnK0zc"}).get_text()
    else:
        #print(title,"할인되지 않은 영화 제외")
        continue

    #할인 된 가격
    sale_price = movie.find("span", attrs={"class":"VfPpfd ZdBevf i5DZme"}).get_text()

    #링크
    link = movie.find("a", attrs={"class":"JC71ub"})["href"]
    # 올바른 링크 = url + link

    print("제목 : {}".format(title))
    print("할인 전 금액 : {}".format(original_price))
    print("할인 후 금액 : {}".format(sale_price))
    print("링크 : {}".format(url+link))
    print("-"*10)

browser.quit()


import numpy as np
import matplotlib.pyplot as plt
from sklearn.linear_model import RANSACRegressor

from function_tools import root_mean_square as rms

# 绘制结果
def basic_visualize(x, y, x_n, y_m):
    plt.scatter(x_n, y_m, color='b', label='Points with Noise')
    plt.plot(x, y, 'r', label='Original Line')
    plt.xlabel('x')
    plt.ylabel('y')

def func_visualize(x, k, b, string):
    plt.plot(x, k * x + b, color='darkorange', label= string + ' Fitted line')
    plt.legend()
    plt.title(string + ' Line Fitting')
    plt.show()

    print("k_fit =", k)
    print("b_fit =", b)

# 最小二乘拟合
def least_sqaure(x, y):
    A = np.vstack([x, np.ones(num_points)]).T
    k_fit, b_fit = np.linalg.lstsq(A, y, rcond=None)[0]

    print("最小二乘拟合直线的参数:")
    func_visualize(x, k_fit, b_fit, 'Least Squares')

    return k_fit * x + b_fit

# RANSAC拟合
def ransac(x,y):
    X = x.reshape(-1, 1)
    ransac = RANSACRegressor()
    ransac.fit(X, y)

    k_fit, b_fit = ransac.estimator_.coef_[0], ransac.estimator_.intercept_

    print("ransac拟合直线的参数:")
    func_visualize(x, k_fit, b_fit, 'RANSAC')
    return k_fit * x + b_fit

# 随机抽样数据
def generate_data(a, b, c, num_points, noise):
    x_oringal = np.linspace(-10, 10, num_points)
    y_oringal = -(a * x_oringal + c) / b
    # 添加噪声
    noise_n = np.random.normal(0, noise, num_points)
    noise_m = np.random.normal(0, noise, num_points)
    x_n = x_oringal + noise_n
    y_m = y_oringal + noise_m

    return x_oringal,y_oringal,x_n,y_m

num_points = 100

def main():
    a_given, b_given, c_given, noise = 2.0, -1.0, -6.0, 1
    x, y, x_n, y_m = generate_data(a_given, b_given, c_given, num_points, noise)
    y_right = a_given * x_n + c_given

    basic_visualize(x, y, x_n, y_m)
    y_predict = least_sqaure(x_n, y_m)
    print(f"RMS误差评价为：{rms(y_right, y_predict)}")
    print("")
    basic_visualize(x, y, x_n, y_m)
    y_predict = ransac(x_n, y_m)
    print(f"RMS误差评价为：{rms(y_right, y_predict)}")

if __name__ == "__main__":
    main()

Essential math for AI/2021112845-张智雄-实验一/linear.py


import numpy as np
import cv2
import matplotlib.pyplot as plt
import matplotlib.image as mpimg
from params import *  # Left, Right

#image = cv2.imread('test_images/warp_img_with_lines.jpg')  #straight_lines1  test5
test_image = cv2.imread('test_images/test5.jpg') #straight_lines1  test5

# Convert to RGB
test_image = cv2.cvtColor(test_image, cv2.COLOR_BGR2RGB)

def colour_extraction(image, r_thresh =  ([220, 255]), s_thresh = ([120, 255])):
    hls = cv2.cvtColor(image, cv2.COLOR_BGR2HLS)

    H = hls[:,:,0]
    L = hls[:,:,1]  # For shadows
    S = hls[:,:,2]  # general good detection

    R = image[:,:,0]
    G = image[:,:,1]  # For shadows
    B = image[:,:,2]

    #plt.imshow(G)
    #plt.show()

    #---------------------------- R-CHANNEL-FILTER -----------------------------
    retval, r_binary = cv2.threshold(R.astype('uint8'), r_thresh[0], r_thresh[1], cv2.THRESH_BINARY)
    #r_binary = np.zeros_like(R)
    #r_binary[(R >= thresh[0]) & (R <= thresh[1])] = 1
    #---------------------------- S-CHANNEL-FILTER -----------------------------

    retval, s_binary = cv2.threshold(S.astype('uint8'), s_thresh[0], s_thresh[1], cv2.THRESH_BINARY)
    #s_binary = np.zeros_like(R)
    #s_binary[(S >= thresh[0]) & (S <= thresh[1])] = 1

    #---------------------------- COMBINING CHANNELS ---------------------------

    # Combine the two images to a binary thresholds
    combined_binaries_255 = cv2.bitwise_or(r_binary, s_binary)
    combined_binaries = np.zeros_like(combined_binaries_255)
    combined_binaries[(combined_binaries_255 > 0)] = 1

    if show == True:
        # Plot results line extraction
        f, (ax1, ax2, ax3) = plt.subplots(1, 3, figsize=(20, 8))
        f.tight_layout()
        ax1.imshow(s_binary,  cmap='gray')
        ax1.set_title('R-Binary', fontsize=20)
        ax2.imshow(r_binary, cmap='gray')
        ax2.set_title('S-Binary', fontsize=20)
        ax3.imshow(combined_binaries, cmap='gray')
        ax3.set_title('Combined', fontsize=20)
        plt.subplots_adjust(left=0., right=1, top=0.9, bottom=0.)
        plt.show()

    return combined_binaries

#--------------------------- GRADIENT -----------------------------------------
def gradient_extraction(img, gauss_kernel = 15, sobel_kernel=3, orient = 'both', thresh=(20, 255)):
    # Apply the following steps to img
    #  Convert to grayscale
    gray = cv2.cvtColor(img, cv2.COLOR_RGB2GRAY)
    # Take the gradient in x, y direction separately, or in both directions. Transform the result to an absolute value
    cv2.GaussianBlur(gray, (gauss_kernel, gauss_kernel), 0)

    if orient == 'x':
        sob = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
    elif orient == 'y':
        sob = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
    else:
        sob = cv2.Sobel(gray, cv2.CV_64F, 1, 0, ksize=sobel_kernel)
        sob_y = cv2.Sobel(gray, cv2.CV_64F, 0, 1, ksize=sobel_kernel)
        # calculate the direction of the gradient
    abs_sob = np.abs(sob)
    #abs_sob_y = np.abs(sob_y)
    #gradient_direction = np.arctan2(sob_abs_y, sob_abs_x)
    scaled_sob= np.uint8(255*abs_sob/np.max(abs_sob))
    #scaled_sob = cv2.convertScaleAbs(sob, alpha=1, beta=0)

    # Create a binary mask
    binary = np.zeros_like(scaled_sob)
    binary[(scaled_sob >= thresh[0]) & (scaled_sob <= thresh[1])] = 1
    return binary

"""

#plt.figure(figsize=(30, 8))
plt.subplots(2, 4, figsize = (20, 7))
for i in range(1,9):
    thresh = ([30, 255])
    thresh[0] = 5 + 2 * i
    binary = gradient_extraction(test_image, sobel_kernel=3, orient='x', thresh=thresh)
    plt.subplot(2, 4, i)
    if i == 1:
        plt.imshow(test_image)
    else:
        plt.imshow(binary, cmap='gray')
    plt.title('Sobel, Lower Thresh = {}'.format(thresh[0]))
    plt.axis('off')
    plt.tight_layout(pad=0.4, w_pad=0.5, h_pad=1.0)
plt.show()

"""


import numpy as np
import matplotlib.pyplot as plt
from utils import plot2Dclusters

from kmeans import KMeans

# If you want, you could write this function to compute pairwise L1 distances
def l1_distances(X1, X2):
    ## Got some help from https://sparrow.dev/pairwise-distance-in-numpy/
    ## With X1 dimensions of m x n, and X2 dimensions of p x n,
    ## returns dist matrix with dimension n x p, where dist[i, j] = l1-distance between X1[i:] (row i) with X2[j:] (row j)
    return np.sum(np.abs(X1[:, None, :] - X2[None, :, :]), axis = -1)

class KMedians(KMeans):
    # We can reuse most of the code structure from KMeans, rather than copy-pasting,
    # by just overriding these few methods. Object-orientation!

    def get_assignments(self, X):
        D1 = l1_distances(X, self.w)
        return np.argmin(D1, axis=1)

    def update_means(self, X, y):
        for k_i in range(self.k):
            same_k = y == k_i
            self.w[k_i] = np.median(X[same_k], axis = 0)

    def loss(self, X, y=None):
        w = self.w
        if y is None:
            y = self.get_assignments(X)

        n, self.d = X.shape
        k, d = w.shape

        sum_of_l1_distances = 0

        for cluster in range(k):
            cluster_median = w[cluster,]

            for example in range(n):
                if y[example] == cluster:
                    sum_of_l1_distances += np.linalg.norm(X[example,] - cluster_median, 1)

        return sum_of_l1_distances


import pandas as pd

connect_interneurons=True
upload_cortical_syn_locs = True

recording_dt = 0.1

connect_PV_to_Pyr  = True
connect_SOM_to_Pyr = True
connect_SOM_to_PV  = True

record_thalamic_syns = False  # Thalamic source (presynaptic)

record_PV_syns 		 = True # PV source (presynaptic)
record_SOM_syns 	 = True # SOM source (presynaptic)

record_Pyr_syns 	 = False # Pyr source (presynaptic)
record_channel 		 = False

SOM_from = 'post'

thalamic_params = {'ITI': 120, 'IPI': 2000, 'type': 'single', 'freq': 'BroadBand'}

Pyr_input_params 	= {'Dep': 671, 'Fac': 5, 'Use': 0.86}# {'Dep': 0, 'Fac': 0, 'Use': 1}
PV_input_params 	= {'Dep': 671, 'Fac': 5, 'Use': 0.86}
SOM_input_params 	= {'Dep': 671, 'Fac': 5, 'Use': 0.86}
Pyr_IClamp_amp 		= 0.1

Pyr_input_weight = 1
PV_input_weight  = 0.6
SOM_input_weight = 0.6

PV_to_Pyr_weight = 0.5
SOM_to_Pyr_weight = 0.3

# SOM => Pyr
n_SOMs_to_Pyr     = 11 # From BB connectivity data, based on cell types below
n_syns_SOM_to_Pyr = 11 * n_SOMs_to_Pyr # From BB connectivity data, based on cell types below

# SOM => PV
# n_SOMs_to_PV 	 = 5 # From BB connectivity data, based on cell types below
n_syns_SOM_to_PV = 200 # 11 * n_SOMs_to_PV # From BB connectivity data, based on cell types below
SOM_to_PV_weight = SOM_to_Pyr_weight # CHECK THIS

pyr_template_path 	= 'EPFL_models/L4_PC_cADpyr230_1'
pyr_template_name 	= 'cADpyr230_L4_PC_f15e35e578'
pyr_morph_path 		= '{}/morphology'.format(pyr_template_path)

PV_template_path 	= 'EPFL_models/L4_LBC_cNAC187_1'
PV_template_name 	= 'cNAC187_L4_LBC_990b7ac7df'
PV_morph_path 		= '{}/morphology/'.format(PV_template_path)

SOM_template_path = 'EPFL_models/L4_MC_cACint209_1'
SOM_template_name = 'cACint209_L4_MC_ba3c5063e4'
SOM_morph_path 	  = '{}/morphology/'.format(SOM_template_path)

pyr_type = 'L4_PC'
not_PVs = ['PC', 'SP', 'SS', 'MC', 'BTC', 'L1', 'BP', 'BPC']
SOM_types = ['MC', 'BPC', 'BP']

PV_input_delay 	= 0 # TEMPORARY: CHANGE THIS
Pyr_input_delay = PV_input_delay + 4 # taken from Tohar paper (Fig 4- Supp. 2a)
SOM_input_delay = PV_input_delay + 3 # taken from Tohar paper (Fig 4- Supp. 2a)

PV_output_delay = Pyr_input_delay + 5 # TEMPORARY: CHECK THIS
SOM_output_delay = PV_output_delay# + something??

# PV_output_params = {'Dep': 706, 'Fac': 21, 'Use': 0.25}
# SOM_output_params = {'Dep': 706, 'Fac': 21, 'Use': 0.25}

freq1 = 6666
freq2 = 9600
simulation_time = 154*1000 # in ms
spike_threshold = 0

filenames = {'cell_details': 'thalamocortical_Oren/thalamic_data/cells_details.pkl',
		 'thalamic_locs': 'thalamocortical_Oren/thalamic_data/thalamic_axons_location_by_gid.pkl',
		 'thalamic_connections': 'thalamocortical_Oren/thalamic_data/thalamo_cortical_connectivity.pkl',

		 # 'thalamic_activations_6666': 'thalamocortical_Oren/CreateThalamicInputs/test_times/input6666_106746_pairs_ITI_120_IPI_2000.p',
		 # 'thalamic_activations_9600': 'thalamocortical_Oren/CreateThalamicInputs/test_times/input9600_109680_pairs_ITI_120_IPI_2000.p',

		 'stim_times': 'thalamocortical_Oren/SSA_spike_times/stim_times.p',

		 'PV_spike_times': 'thalamocortical_Oren/SSA_spike_times/PV_spike_times/PV_spike_times_tstop_10000_input6666_by_gid.p',
		 'pyr_connectivity': 'thalamocortical_Oren/pyramidal_connectivity_num_connections.p',
		 'cortex_connectivity': 'thalamocortical_Oren/cortex_connectivity_num_connections.p',
		 'cell_type_gids': 'thalamocortical_Oren/thalamic_data/cell_type_gids.pkl',
		 'thalamic_activations': {6666: 'thalamocortical_Oren/SSA_spike_times/input6666_106746.dat', 9600: 'thalamocortical_Oren/SSA_spike_times/input9600_109680.dat'}}

PV_to_Pyr_source = 'voltage'
assert PV_to_Pyr_source in ['spike_times', 'voltage'], 'Invalid PV output type (choose spike_times or voltage)'
assert PV_to_Pyr_source != 'spike_times', 'Still under construction!'

thal_connections   = pd.read_pickle(filenames['thalamic_connections'])
thalamic_locations = pd.read_pickle(filenames['thalamic_locs'])

recorded_segment = []

activated_frequency = thalamic_params['freq']
stand_freq = freq1*(str(freq1) == activated_frequency) + freq2*(str(freq2) == activated_frequency)
dev_freq = freq1*(str(freq1) != activated_frequency) + freq2*(str(freq2) != activated_frequency)


import threading, base64, json, jwt
import streamlit as st
from PIL import Image

def check_token_access(menuid):

    sighKey = "insert_sign_key_here"

    current_url = st.experimental_get_query_params()
    token = current_url.get("token", None)

    claims = None  # claims 변수를 미리 초기화
    try:
        claims = jwt.decode(token[0], base64.b64decode(sighKey), algorithms=['HS256'])
        if "menuList" not in claims:
            raise Exception("menu 정보가 없는 토큰입니다.")
    except jwt.ExpiredSignatureError:
        print("토큰이 만료되었습니다.")
    except jwt.InvalidTokenError:
        print("유효하지 않은 토큰입니다.")
    except Exception as e:
        print(str(e))

    if claims is not None:
        Subject = claims["sub"]

        menu_list_json = json.loads(claims['menuList'])

        menu_ids = [item['menuId'] for item in menu_list_json]
        #st.experimental_set_query_params(urlEncodedToken="")
        if menuid in menu_ids:
            #st.experimental_set_query_params(urlEncodedToken="")
            return True
        else:
            image = Image.open('./../../accessdenied403.png')
            st.image(image, width=70)
            st.title("403 Forbidden")
            st.markdown("# Permission Denied \n You do not have permission to access on this page.")
            st.markdown("Please go back to the portal below:")
            link = 'https://icebergdev.gscaltex.com/login'
            st.markdown(link, unsafe_allow_html=True)
            #st.experimental_set_query_params(urlEncodedToken="")
            exit()

    else:
        image = Image.open('./../../accessdenied403.png')
        st.image(image, width=70)
        st.title("403 Forbidden")
        st.write("Permission Denied \n You do not have permission to access on this page.")
        st.markdown("Please go back to the portal below:")
        link = 'https://icebergdev.gscaltex.com/'
        st.markdown(link, unsafe_allow_html=True)
        #st.experimental_set_query_params(urlEncodedToken="")
        exit()


from typing import Iterable, List, Optional, Set, Tuple, Union

DeltaPosition = Optional[int]
NumericDeltaPosition = Union[int, float]  # float is added here to support math.inf
DeltaRange = Tuple[DeltaPosition, DeltaPosition]

def merge_intervals(intervals: Set[DeltaRange]) -> Set[DeltaRange]:
    """Merges a set of N input intervals into a minimal number of output intervals.

    All input intervals will be merged into a minimal number of output intervals in O(N log N) time.

    Example:
        >>> merge_intervals((3, 9), (8, 12), (15, 19))
        ((3, 12), (15, 19))

    Example:
        >>> merge_intervals((3, 9), (None, 15), (13, 30))
        ((None, 30))

    Args:
        intervals: A list of intervals with an int type representing finite, closed bounded values and
            a None type representing infinity.

    Returns:
        A minimal number of output intervals
    """
    merged: Set[DeltaRange] = set()
    intervals_list: List[DeltaRange] = list(intervals)

    if len(intervals_list) == 0:
        return merged

    _to_numeric_values(intervals_list)
    intervals_list.sort()  # sort by starting range numbers

    merge_start, merge_end = None, None
    for interval in intervals_list:
        start, end = interval
        if start > end:
            raise ValueError(
                f"Invalid stream position range interval: ({start}, {end})"
            )

        if merge_start is None and merge_end is None:
            merge_start, merge_end = start, end
            continue

        if merge_end < start:
            # add current merge interval if no overlap, begin new interval
            _add_merged_interval(merged, merge_start, merge_end)
            merge_start, merge_end = start, end
        elif merge_end < end:
            merge_end = end  # expand current merge interval if there is an overlap

    # add final merge interval
    _add_merged_interval(merged, merge_start, merge_end)

    return merged

def _add_merged_interval(
    result_set: set, start: NumericDeltaPosition, end: NumericDeltaPosition
):
    start_pos: DeltaPosition = start if isinstance(start, int) else None
    end_pos: DeltaPosition = end if isinstance(end, int) else None
    result_set.add((start_pos, end_pos))

def _to_numeric_values(intervals_list: List[DeltaRange]):
    for i, interval in enumerate(intervals_list):
        start, end = _get_validated_interval(interval)
        if start is None:
            start = float("-inf")
        if end is None:
            end = float("inf")

        intervals_list[i] = (start, end)

def _get_validated_interval(interval: DeltaRange) -> DeltaRange:
    if not isinstance(interval, Iterable) or len(interval) != 2:
        raise ValueError(f"Interval {interval} must be a tuple of size 2")

    start, end = interval
    if not (isinstance(start, int) or start is None) or not (
        isinstance(end, int) or end is None
    ):
        raise ValueError(
            f"Invalid stream position value types: "
            f"({start}, {end}) - ({type(start), type(end)})"
        )

    return start, end


#!/usr/bin/python3
"""
Contains Base class
"""
import json

class Base:
    """Base class"""
    __nb_objects = 0

    def __init__(self, id=None):
        """Constructor"""
        if id is not None:
            self.id = id
        else:
            Base.__nb_objects += 1
            self.id = Base.__nb_objects

    @staticmethod
    def to_json_string(list_dictionaries):
        """returns the json string representation
        of its argument"""
        if list_dictionaries is None:
            return "[]"
        else:
            return json.dumps(list_dictionaries)

    @classmethod
    def save_to_file(cls, list_objs):
        """saves list_objs to json file"""
        obj = []
        filename = cls.__name__ + ".json"

        if list_objs is not None:
            for instance in list_objs:
                obj.append(instance.to_dictionary())

        with open(filename, mode='w') as json_file:
            json_file.write(cls.to_json_string(obj))

    @staticmethod
    def from_json_string(json_string):
        """return the list of the JSON string representation"""
        if json_string == "" or json_string is None:
            return []
        else:
            return json.loads(json_string)

    @classmethod
    def create(cls, **dictionary):
        """returns an instance with attributes set
        using **dictionary"""
        if cls.__name__ == "Rectangle":
            dummy = cls(dictionary["width"], dictionary["height"])
        else:
            dummy = cls(dictionary["size"])

        dummy.update(**dictionary)
        return dummy

    @classmethod
    def load_from_file(cls):
        """loads JSON file and returns a list of instances"""
        filename = cls.__name__ + ".json"

        try:
            with open(filename, mode='r', encoding="UTF-8") as name:
                # convert list in filename and save to obj_dict
                obj_dict = cls.from_json_string(name.read())

            instances = []
            # create instances from obj_dict dictionaries
            for instance in obj_dict:
                instances.append(cls.create(**instance))
            return instances
        except FileNotFoundError:
            return []


# -*- coding: utf-8 -*-
import sys
import codecs
from telethon import TelegramClient, sync
import re

# These example values won't work. You must get your own api_id, phone_number and
# api_hash from https://my.telegram.org, under API Development.
api_id = 111111
api_hash = 'eXXXXXXXXXXXXXXXXXXXXXXXXXXXXXXX'
phone_number = '+YYXXXXXXXXX'

# Start the telegram client
client = TelegramClient('session_id', api_id, api_hash)

# Check if it is already authorized
client.connect()
if not client.is_user_authorized():
    client.send_code_request(phone_number)
    me = client.sign_in(phone_number, input('Enter code: '))

# Get the chat_ids for the channels to do the search
hackplayers_id = client.get_entity('hackplayers').id
fwhibbit_id = client.get_entity('Fwhibbit').id
chat_ids = [hackplayers_id, fwhibbit_id]

# Define the search terms
search_terms = ['#ROJIRRINS', '#AZULONES', '#DULCINES', '#LECTURASENELROCA', '#ATMOSFERAPWN']

for search in search_terms:
    f= open(search.replace('#', '') + ".txt","w+")

    for chat in chat_ids:
        all_messages = client.get_messages(chat, None, search=search)
        for message in all_messages:
            f.write(str(message.message.replace('\n', ' ').encode('utf-8')))
            f.write('\n')

    f.close()


#!/usr/bin/env python3

"""
DAG Factory methods to create an EMR Cluster, run steps and terminate cluster
Developer: Gokturk (GT) Yurtyapan
e-mail: gt.yurtyapan@starz.com
Date: 2019-04-09
"""

from datetime import datetime, timedelta
import airflow
import json
from airflow import DAG
from airflow.contrib.operators.emr_create_job_flow_operator \
    import EmrCreateJobFlowOperator
from airflow.contrib.operators.emr_add_steps_operator \
    import EmrAddStepsOperator
from airflow.contrib.sensors.emr_step_sensor import EmrStepSensor
from airflow.contrib.operators.emr_terminate_job_flow_operator \
    import EmrTerminateJobFlowOperator

def run_emr_job(current_dag, cluster_name, task_gen_name, aws_connection, emr_connection,
                script_location, library_location, region='us-east-1'):
    """
    Creates the EMR cluster, runs the step and terminates the cluster when it is completed
    current_dag: DAG that is created by the user
    cluster_name: Name given to cluster by the user
    task_gen_name: A general name for the task being done. This is used to name different tasks
    aws_connection: Connection to AWS for account credentials
    emr_connection: Name of Airflow connection storing EMR configuration details
    script_location: S3 location of the xcript to be run
    library_location: S3 location of the library being used to run spark-submit
    region: AWS region where the cluster is being created
    """

    # Name of the new cluster being created
    job_flow_overrides = {
        'Name': cluster_name
    }

    # name of task creating the cluster
    create_cluster_task_name = task_gen_name + "_create_cluster"

    # Task that creates the cluster
    cluster_creator = EmrCreateJobFlowOperator(
        task_id= create_cluster_task_name,
        job_flow_overrides=job_flow_overrides,
        aws_conn_id=aws_connection,
        emr_conn_id=emr_connection,
        dag=current_dag
    )

    # script-runner.jar file location is region specific
    script_runner_jar = 's3://' + region + '.elasticmapreduce/libs/script-runner/script-runner.jar'

    # Step description
    step_definition = [
        {
            'Name': task_gen_name,
            'ActionOnFailure': 'CONTINUE',
            'HadoopJarStep': {
                'Jar': script_runner_jar,
                'Args': [script_location, library_location, '']
            }
        }
    ]

    # Task that terminates the cluster
    cluster_remover = EmrTerminateJobFlowOperator(
        task_id=task_gen_name + "_remove_cluster",
        job_flow_id="{{ task_instance.xcom_pull('" + create_cluster_task_name + "', key='return_value') }}",
        aws_conn_id=aws_connection,
        dag=current_dag
    )

    # Add the step and step checker tasks
    add_step_to_emr(cluster_creator, task_gen_name, step_definition, cluster_remover,
                    create_cluster_task_name, aws_connection, current_dag)

def add_step_to_emr(cluster_create_task, task_identifier, step_params, cluster_remover, task_create_cluster,
                    aws_connection, dag):
    """
    In case we need to add multiple steps to the cluster
    cluster_create_task: ID of task that creates a cluster
    task_identifier: ID of step
    step_params: parameters to pass to the step
    cluster_remover: task that terminates the cluster
    task_create_cluster: task that creates the cluster
    aws_connection: Connection to AWS for account credentials
    dag: DAG that is created by the user
    """
    step_adder = EmrAddStepsOperator(
        task_id=task_identifier,
        job_flow_id="{{ task_instance.xcom_pull('" + task_create_cluster + "', key='return_value') }}",
        aws_conn_id=aws_connection,
        steps=step_params,
        dag=dag
    )

    step_checker = EmrStepSensor(
        task_id=task_identifier + '_watch_step',
        job_flow_id="{{ task_instance.xcom_pull('" + task_create_cluster + "', key='return_value') }}",
        step_id="{{ task_instance.xcom_pull('" + task_identifier + "', key='return_value')[0] }}",
        aws_conn_id=aws_connection,
        dag=dag
    )

    cluster_create_task.set_downstream(step_adder)
    step_adder.set_downstream(step_checker)
    step_checker.set_downstream(cluster_remover)


# -*-coding: utf-8 -*-
''' Test suit for maridian.py

@version: 0.0.1
@author: sheng
@contact: sinotradition@gmail.com
@copyright: License according to the project lincese.
'''
import unittest
import meridian

class TestMeridianFunctions(unittest.TestCase):

    def setUp(self):
        self.ap = meridian.acupoint('name','type','channel')
        self.ac = meridian.acuchannel('name',('ap1','ap2'))
    def test_acupoint(self):
        self.assertEqual(self.ap.name, 'name', 'msg ap name')
        self.assertEqual(self.ap.type, 'type', 'msg ap type')
        self.assertEqual(self.ap.channel, 'channel', 'msg ap channel')
    def test_acuchannel(self):
        self.assertEqual(self.ac.name, 'name', 'msg ac name')
        self.assertEqual(self.ac.member, ('ap1','ap2'), 'msg ac member')

if __name__ == "__main__":
    unittest.main()


course='python for everybody'
#using whitespace for spacing the words after string concatenation
a="python"
b=" for"
c=" everybody"
print(a+b+c)
#testing built-in string functions
print(course)
q=course.title()
w=course.upper()
e=course.lower()
#taking user input
a=input("enter the word to be replaced\n")
b=input("enter the replacement\n")
r=course.replace(str(a),str(b))
c=input("enter the word to be found\n")
t=course.find(str(c))
print("\n",q,"\n",w,"\n",e,"\n",str(r).title(),"\n",t)

#formatting strings using % operator and format specifiers
brand = "HP OMEN CORE i7 12th GEN"
exchangeRate = 1.24
price=1299
message0 = "The price of this %s laptop is %d USD and the exchange rate is %4.2f USD to 1 EUR" %(brand,price,exchangeRate)
print (message0)

#formatting strings using format() function/operator
user_name="Danush"
user_height=1.82
user_weight=73
country="India"
wins=11
losses=0
script="Ladies and Gentlemen it's time for the main event of the evening,for the undisputed UFC welterweight championship of the World, fighting out of red corner, we have, the reigning, the defending undisputed Ufc welterweight champion {0:s}, with a professional record of {1:d} wins and {2:d} losses, fighting out of {3:s}, weighing in at {4:d} kilos and {5:4.2f} meters tall".format(user_name,wins,losses,country,user_weight,user_height)
print("\n\n",script)


# Definition for singly-linked list.
# class ListNode:
#     def __init__(self, val=0, next=None):
#         self.val = val
#         self.next = next
class Solution:
    def rotateRight(self, head: Optional[ListNode], k: int) -> Optional[ListNode]:
        stack=[]
        dummy=head
        while dummy:
            stack.append(dummy)
            dummy=dummy.next
        n=len(stack)
        if n<2:
            return head
        k=- k%n
        stack[-1].next=stack[0]
        stack[k-1].next=None
        return stack[k]


import pandas as pd
import sys
import os
sys.path.append(os.path.join(os.getcwd().split('xtraderbacktest')[0],'xtraderbacktest') )
import modules.other.sys_conf_loader as sys_conf_loader

import json
from itertools import product

def __read_opt_rng(opt_rng_json_dict):
    """ Transfer dict read from json to a dict of opt inputs.
    Args:
    opt_rng_json_dict: dict object read from json file.

    Returns:
    A dict of opt inputs.
    """
    opt_rng = {}
    for k, v in opt_rng_json_dict["opt_ranges"].items():
        opt_rng[k] = []
        if v["type"] == "range":
            steps = v["values"][1]
            end = v["values"][2]
            start =  v["values"][0]
            temp = start
            while(temp<=end):
                opt_rng[k].append(temp)
                temp = temp + steps
        elif v["type"] == "list":
            opt_rng[k] = v["values"]
    return opt_rng

def _generate_opt_input_all(opt_json_dict=None):
    """ Generate every combination of inputs.

    Args:
        opt_range: A dict of list of all want-to-try value for the inputs mean to optimize.

    Returns:
        A list of dict which can be feed in trading function directly.
    """
    opt_range = __read_opt_rng(opt_json_dict)
    fix_input = opt_json_dict["fix_input"]
    opt_rules = opt_json_dict["opt_rules"]
    strategy_file = opt_json_dict["strategy_file"]
    symbols = opt_json_dict["symbols"]

    ex_comb_lst = [dict(zip(opt_range, v)) for v in product(*opt_range.values())]
    for rule in opt_rules:
        if rule[1] == "<":
            ex_comb_lst = [opt_input for opt_input in ex_comb_lst
                            if opt_input[rule[0]] < opt_input[rule[2]]]
        elif rule[1] == ">":
            ex_comb_lst = [opt_input for opt_input in ex_comb_lst
                            if opt_input[rule[0]] > opt_input[rule[2]]]
        elif rule[1] == ">=":
            ex_comb_lst = [opt_input for opt_input in ex_comb_lst
                            if opt_input[rule[0]] >= opt_input[rule[2]]]
        elif rule[1] == "<=":
            ex_comb_lst = [opt_input for opt_input in ex_comb_lst
                            if opt_input[rule[0]] <= opt_input[rule[2]]]
        elif rule[1] == "==":
            ex_comb_lst = [opt_input for opt_input in ex_comb_lst
                            if opt_input[rule[0]] == opt_input[rule[2]]]
        elif rule[1] == "!=":
            ex_comb_lst = [opt_input for opt_input in ex_comb_lst
                            if opt_input[rule[0]] != opt_input[rule[2]]]

    results = []
    for symbol in symbols:
        for item in ex_comb_lst:
            t = item.copy()
            result = {
                "strategy_file":strategy_file,
                "custom":t
            }
            result.update({"symbols":symbol})
            result.update(fix_input)
            results.append(result)
    return results

def generate(path,file_name,saved_confs = True):
    abs_path = sys_conf_loader.get_sys_path() + path
    if sys.platform.startswith('linux') == False:
        abs_path = abs_path.replace('/','\\')
    opt_json = sys_conf_loader.read_configs_json(file_name,path)
    confs = _generate_opt_input_all(opt_json)
    if saved_confs is False:
        return confs
    folder_name = file_name.split(".json")[0]
    file_path_dir = abs_path + folder_name + "/"
    if sys.platform.startswith('linux') == False:
        file_path_dir = file_path_dir.replace('/','\\')
    if os.path.isdir(file_path_dir) is False:
        os.mkdir(file_path_dir)
    else:
        # Clear
        for f in os.listdir(file_path_dir):
            os.remove(file_path_dir + f)

    i = 0
    for conf in confs:
        # Save to file
        file_name_temp = folder_name + '_' +str(i) + ".json"
        with open(file_path_dir + file_name_temp,"w") as f:
            json.dump(conf,f,indent=4)
            #pass
        f.close()
        i = i + 1
    return confs

if __name__ == "__main__":
    #generate("/configurations/strategy/optmize/demo_strategy/","AAPL_opt.json")
    generate("/configurations/strategy/optmize/bbs_scalper/","AUDNZD_opt.json")


#!/bin/python
result = []
for x in range(1,10):
    if x % 2 == 0:
        print (  "is even")
    elif x % 2 == 1:
        print ( " is odd")

    else:
        break
    result.append(x)
print(result)


import platform
import os
import shutil
import re

print('OS:', platform.system())
Dir = os.path.dirname(os.path.abspath(__file__))
Flag = True
lines = []
newDir = ''

def init():
    command = input(">")
    if command == "init":
        if os.path.exists("my_git"):
            pass
        else:
            os.mkdir("my_git")
        ignore = open('my_git/ignore.txt', 'w')
        ignore.write('.git\n.vs\n.idea\nignore.txt\ninit.txt\n*.cmd\nmy_git\nCommites\nbin\n')
        ignore.close()
        with open('my_git/init.txt', 'w') as f1:
            dir_all(Dir, f1)
    elif command == "exit":
        global Flag
        Flag = False
    elif command == "commit":
        temp = open('my_git/temp.txt', 'w')
        dir_all(Dir, temp)
        temp.close()
        file1 = open('my_git/init.txt', 'r')
        f2 = open('my_git/temp.txt', 'r')
        f3 = open('my_git/ignore.txt', 'w')
        f3.write('.git\n.vs\n.idea\nignore.txt\ninit.txt\n*.cmd\nmy_git\nCommites\nbin\n')
        for i in file1:
            x = f2.readline()
            #print('i=' + i)
            #print('X=' + x + '-----')
            if x == i:
                line2 = x.split(';')
                f3.write(line2[0] + '\n')
        file1.close()
        f2.close()
        f3.close()
        ignore = open('my_git/ignore.txt', 'r')
        global lines
        while True:
            s = ignore.readline()
            line1 = re.sub('\n', '', s)
            if not line1:
                break
            #print(line1)
            lines.append(line1)

        ignore.close()
        with open('my_git/init.txt', 'w') as f1:
            dir_all(Dir, f1)
        name_commit = input("Введите название коммита:")
        com_dir = os.path.join(Dir, 'Commites', name_commit)
        if not os.path.exists(com_dir):
            os.mkdir(com_dir)
            commit_tree(Dir, com_dir)
            init()
        else:
            print('Commit exists!')

    else:
        print(f"{command} не является командой или оператором")
        init()

def ignore(f):
    global lines
    for item in lines:
        if f == item:
            return True

    return False

def dir_all(Dir, f1):
    dirfiles = os.listdir(Dir)
    for item in dirfiles:
        path = os.path.join(Dir, item)
        if os.path.isfile(path):
            f1.write(os.path.basename(path) + ';' + str(os.path.getmtime(path)))
            f1.write("\n")
        elif os.path.isdir(path):
            dir_all(path, f1)

def fill_dirs(Dir, line):
    dirfiles = os.listdir(Dir)
    for item in dirfiles:
        if ignore(item):
            continue

        path = os.path.join(Dir, item)
        if os.path.isfile(path):
            shutil.copy(path, line)
        elif os.path.isdir(path):
            print('Directory:', item)
            newDir = os.path.join(line, item)
            os.mkdir(newDir)
            commit_tree(path, line)

def commit_tree(Dir, line):
    global newDir
    dirfiles = os.listdir(Dir)
    for item in dirfiles:
        #print(item)
        if ignore(item):
            continue

        path = os.path.join(Dir, item)
        if os.path.isfile(path):
            shutil.copy(path, line)
        elif os.path.isdir(path):
            continue

    for item in dirfiles:
        if ignore(item):
            continue

        path = os.path.join(Dir, item)
        if os.path.isfile(path):
            continue
        elif os.path.isdir(path):
            print('Directory:', item)
            newDir = os.path.join(line, item)
            os.mkdir(newDir)
            fill_dirs(path, newDir)

while Flag:
    init()


# 2022 (c) Petr Kracik
# Apache 2 License

import json
from fio import FioBankAPI
from creditas import BankaCreditasAPI

def main():
    config = json.load(open("config.json"))

    creditas_accounts = []
    fio_accounts = []

    for a in config['creditas']:
        creditas_accounts.append(BankaCreditasAPI(a['account_type'], a['account_id'], a['token']))

    for a in creditas_accounts:
        print(a)

    for f in config['fio']:
        fio_accounts.append(FioBankAPI(f['token'], f['name'] if 'name' in f else None))

    for f in fio_accounts:
        print(f)

    total_balance = 0
    for balance in creditas_accounts+fio_accounts:
        total_balance += balance.balance

    print("Total balance: {}".format(total_balance))

if __name__ == "__main__":
    main()


import Tkinter as tk
#from tk import *
from PIL import Image, ImageTk
from Play import *
import os, sys

def Show(f, f1, old_label_image, root):
    image1 = Image.open(f)
    image1.resize((image1.size[0] / 2, image1.size[1] / 2), Image.ANTIALIAS)
    image2 = Image.open(f1)
    image2.resize((image2.size[0] / 2, image2.size[1] / 2), Image.ANTIALIAS)
    root.geometry('%dx%d' % (2 * image1.size[0], image1.size[1] + 80))
    tkpi = ImageTk.PhotoImage(image1)
    label_image = tk.Label(root, image=tkpi)
    label_image.place(x=0, y=0, width=image1.size[0], height=image1.size[1])
    tkpi2 = ImageTk.PhotoImage(image2)
    label_image2 = tk.Label(root, image=tkpi2)
    label_image2.place(x=image1.size[0], y=0, width=image1.size[0], height=image1.size[1])
    root.title(f)
    if old_label_image is not None:
        old_label_image.destroy()
    old_label_image = label_image
    root.mainloop()
    print("AfterMainloop")
    return  old_label_image

class ShowImages(tk.Frame):

    def __init__(self, parent):
        tk.Frame.__init__(self, parent)
        self.items_names = GetItemsNames("../dataset/ml-1m/movies_mine.dat")
        self.items_test = np.genfromtxt("data0/test_items.txt")
        #self.my_questions = np.genfromtxt("data/quest_item_random")#"data/questions_items")
        self.my_questions = np.genfromtxt("data0/questions_items")
        self.step = 0
        self.item_vecs, self.item_bias, user_vecs, user_bias, global_bias, user_vecs_train, user_bias_train = GetData("data0")
        self.inverse_matrix = np.linalg.inv(np.eye(self.item_vecs.shape[1]) * 0.001)
        self.answers = []
        self.used_items = []
        self.questions = []
        self.user_estim = np.mean(user_vecs_train, axis=0)

            # create a prompt, an input box, an output label,
            # and a button to do the computation
        self.old_label = None
        self.Last_answer = None
        #self.prompt = tk.Label(self, text="Enter a number:", anchor="w")
        self.show_images()
        self.submit1 = tk.Button(self, text="Img1", command=lambda:self.calculate(1))
        self.submit2 = tk.Button(self, text="Img2", command=lambda:self.calculate(-1))
        self.submit3 = tk.Button(self, text="Do not know", command=lambda:self.calculate(0))
        self.entry = tk.Entry(self)
        self.output = tk.Label(self, text="")

        # lay the widgets out on the screen.
        #self.prompt.pack(side="top", fill="x")
        #self.entry.pack(side="bottom", fill="x", padx=20)
        self.output.pack(side="top", fill="x", expand=True)
        self.submit1.pack(side="left")
        self.submit2.pack(side="right")
        self.submit3.pack()

    def get_posters(self, item, comparative_item):
        item_name = self.items_names[self.items_test[item] + 1][0]
        item_name = item_name.split('?')[-1].split('(')[0]
        comparative_item_name = self.items_names[self.items_test[comparative_item] + 1][0]
        comparative_item_name = comparative_item_name.split('?')[-1].split('(')[0]
        return "images/" + item_name + ".jpg", "images/" + comparative_item_name + ".jpg"

    def show_images(self):
        win = False
        while (not win):
            try:
                if (len(self.answers) > -1):
                    self.item, self.comparative_item, self.used_items = \
                    OneIteration(self.item_vecs, self.item_bias, self.user_estim,
                         self.used_items, self.questions, self.answers, True)
                    print(self.item, win)
                else:
                    self.item = int(self.my_questions[self.step][0])
                    self.comparative_item = int(self.my_questions[self.step][1])
                    self.used_items.append(self.item)
                    self.used_items.append(self.comparative_item)
                    self.step += 1
                    print (self.step, self.comparative_item, self.item)
                print(self.items_names)
                print(self.items_names[self.items_test[self.item] + 1][0],
                      self.items_names[self.items_test[self.item] + 1][-1],
                      self.items_names[self.items_test[self.comparative_item] + 1][0],
                      self.items_names[self.items_test[self.comparative_item] + 1][-1])
                self.img1, self.img2 = self.get_posters(self.item, self.comparative_item)
                #self.img1, self.img2 = Get_posters(self.items_test, self.items_names,
                #                                   self.item, self.comparative_item)
                #self.old_label = Show(self.img1, self.img2, self.old_label, root)

                #show pictures
                print(self.img1, self.img2)
                image1 = Image.open(self.img1)
                image2 = Image.open(self.img2)
                win = True
                print(win)
                #self.image1 = tk.PhotoImage(self.img1)
                #self.image2 = tk.PhotoImage(self.img2)

            except:
                win = False
        image1.resize((image1.size[0] / 2, image1.size[1] / 2), Image.ANTIALIAS)
        image2.resize((image2.size[0] / 2, image2.size[1] / 2), Image.ANTIALIAS)
        root.geometry('%dx%d' % (2 * image1.size[0], image1.size[1] + 80))
        self.tkpi = ImageTk.PhotoImage(image1)
        label_image = tk.Label(root, image=self.tkpi)
        label_image.place(x=0, y=0, width=image1.size[0], height=image1.size[1])
        self.tkpi2 = ImageTk.PhotoImage(image2)
        label_image2 = tk.Label(root, image=self.tkpi2)
        label_image2.place(x=image1.size[0], y=0, width=image1.size[0], height=image1.size[1])
        root.title(self.img1)
        if self.old_label is not None:
            self.old_label.destroy()
        self.ld_label_image = label_image
        if (len(self.answers) > 20):
            for i in range(10):
                recom_item = BestItem(self.item_vecs, self.user_estim, self.used_items, self.item_bias, 0.2)
                self.used_items.append(recom_item)
                print(self.items_names[self.items_test[recom_item] + 1][0].split('?')[-1].split('('))
        movie_title = self.items_names[self.items_test[self.item] + 1][0].split('?')[-1].split('(')[0]
        movie_title1 = self.items_names[self.items_test[self.comparative_item] + 1][0].split('?')[-1].split('(')[0]

        #os.remove(self.img1)
        #os.remove(self.img2)
        #os.move(self.img1, "images/" + movie_title + ".jpg")
        #os.move(self.img2, "images/" + movie_title + ".jpg")

    def calculate(self, answer):

        self.user_answer = float(answer)#float(self.entry.get())
        print(self.user_answer)
        if (answer != -10):
            self.answers, self.inverse_matrix, self.questions = \
            Update(self.answers, self.user_answer,
               self.item_vecs, self.item_bias, self.item, self.comparative_item,
               self.questions)
            self.user_estim = np.dot(self.inverse_matrix,
                            np.dot(np.array(self.answers),
                                   np.array(self.questions)))
        self.show_images()

        #user_estim, answers, inverse_matrix, used_items, questions = \
        #OneIteration(item_vecs, item_bias, user_estim, used_items, questions, answers, items_names, items_test)

        #print(self.user_estim)
        #root.mainloop()

class Example(tk.Frame):
    def __init__(self, parent):
        tk.Frame.__init__(self, parent)

        # create a prompt, an input box, an output label,
        # and a button to do the computation
        self.prompt = tk.Label(self, text="Enter a number:", anchor="w")
        self.entry = tk.Entry(self)
        self.submit = tk.Button(self, text="Submit", command = self.calculate)
        self.output = tk.Label(self, text="")

        # lay the widgets out on the screen.
        self.prompt.pack(side="top", fill="x")
        self.entry.pack(side="top", fill="x", padx=20)
        self.output.pack(side="top", fill="x", expand=True)
        self.submit.pack(side="right")

    def calculate(self):
        # get the value from the input widget, convert
        # it to an int, and do a calculation
        try:
            i = int(self.entry.get())
            result = "%s*2=%s" % (i, i*2)
        except ValueError:
            result = "Please enter digits only"

        # set the output widget to have our result
        self.output.configure(text=result)

# if this is run as a program (versus being imported),
# create a root window and an instance of our example,
# then start the event loop

if __name__ == "__main__":
    root = tk.Tk()
    root.geometry('+%d+%d' % (100, 100))
    ShowImages(root).pack(fill="both", expand=True)
    root.mainloop()

"""
import os, sys
import Tkinter

def button_click_exit_mainloop (event):
    event.widget.quit() # this will cause mainloop to unblock.

root = Tkinter.Tk()
root.bind("<Button>", button_click_exit_mainloop)
root.geometry('+%d+%d' % (100,100))
dirlist = os.listdir('.')
old_label_image = None
for f in dirlist:
    try:
        image1 = Image.open("1.jpg")
        root.geometry('%dx%d' % (image1.size[0],image1.size[1]))
        tkpi = ImageTk.PhotoImage(image1)
        label_image = Tkinter.Label(root, image=tkpi)
        label_image.place(x=0,y=0,width=image1.size[0],height=image1.size[1])
        root.title(f)
        if old_label_image is not None:
            old_label_image.destroy()
        old_label_image = label_image
        root.mainloop() # wait until user clicks the window
    except Exception, e:
        # This is used to skip anything not an image.
        # Image.open will generate an exception if it cannot open a file.
        # Warning, this will hide other errors as well.
        pass
        """
"""def button_click_exit_mainloop (event):
    event.widget.quit() # this will cause mainloop to unblock.

if __name__ == "__main__":
    old_label_image = None
    root = tk.Tk()
    #root.bind("<Button>", button_click_exit_mainloop)
    #root.geometry('+%d+%d' % (100, 100))
    #old_label_image = Show("1.jpg","1.jpg", old_label_image, root)
    Example(root).pack(fill="both", expand=True)"""


# 2090. K Radius Subarray Averages

class Solution:
    def getAverages(self, nums: List[int], k: int) -> List[int]:

        if k==0:
            return nums

        ans = []

        ans = [-1]*len(nums)

        if 2*k+1 > len(nums):
            return ans

        sum_ = sum(nums[:k+k+1])
        ans[k] = sum_//(2*k+1)

        for i in range(k+1, len(nums)-k):
            sum_ = sum_- nums[i-k-1] + nums[i+k]

            ans[i] = sum_//(2*k+1)

        return ans