import numpy as np
import matplotlib.pyplot as plt
import seaborn as sns
import pandas as pd
import utils
import scipy as sp
from scipy import ndimage

def plot_stars(p,x,y,size='large',horizontalalignment='center',**kwargs):
    ''' Plots significance stars '''
    plt.text(x,y,stars(p),size=size,horizontalalignment=horizontalalignment,**kwargs)

def plot_linestar(p,x1,x2,y):
    hlines(y, x1, x2)
    plot_stars(0.5*(x1+x2),y+0.02,stars(p),size='large',horizontalalignment='center')

def _date_labels(dates):
    months = np.array([mdt.month for mdt in dates])
    months_idx = np.append([True] , months[:-1] != months[1:])
    strfs = np.array(['%d', '%b %d'])[months_idx.astype(int)]
    return [dt.strftime(strf) for dt, strf in zip(dates, strfs)]

def plot_filtered_performance_calendar(subj,df,num_days=7, **kwargs):
    '''
    plots a calendar view of the performance for a subject on the past num_days.
    '''
    plot_performance_calendar(subj, utils.filter_normal_trials(utils.filter_recent_days(df, num_days)), **kwargs)

def plot_performance_calendar(subj, data_to_analyze, disp_counts=False, vmins=(0, 0, 0), vmaxs=(None, 1, None)):
    '''
    plots a calendar view of performance for a subject.
    Plots all trials from data_to_analyze so make sure it is filtered.

    Parameters:
    -----------
    subj : str
        the subject
    data_to_analyze : pandas DataFrame
        filtered data to plot. Can be a slice, a copy is made anyways.
    disp_counts : boolean
        display values in grid, removes colorbars, default False
    vmins, vmaxs : iterable of floats, length 3, optional
        Values to anchor the colormaps. If None, they are inferred from the data.
    '''
    data_to_analyze = data_to_analyze.copy()
    data_to_analyze['date'] = data_to_analyze.index.date
    data_to_analyze['hour'] = data_to_analyze.index.hour

    blocked = data_to_analyze.groupby(['date', 'hour'])
    aggregated = pd.DataFrame(blocked.agg({'correct': lambda x: np.mean(x.astype(float)),
                                              'reward': lambda x: np.sum(x.astype(float)),
                                              'type_': lambda x: np.sum((x=='normal').astype(float))}).to_records())

    f, ax = plt.subplots(1,3,sharex=True,sharey=True,figsize=(16.0, 4.0))

    columns = ('type_', 'correct', 'reward')
    titles = (subj+': Trials per hour', 'Accuracy', 'Feeds')
    cmaps = [plt.get_cmap(cmap) for cmap in ('Oranges', 'RdYlBu', 'BuGn')]
    for cmap in cmaps:
        cmap.set_bad(color='Grey')

    pivoted = aggregated.pivot('hour', 'date')

    for i, (column, title, cmap, vmin, vmax) in enumerate(zip(columns, titles, cmaps, vmins, vmaxs)):
        g = sns.heatmap(pivoted[column], annot=disp_counts, ax=ax[i],
                        cmap=cmap, cbar=not disp_counts,
                        vmin=vmin, vmax=vmax)
        g.set_title(title)
    g.set_xticklabels(_date_labels(pivoted.keys().levels[1]));

def plot_filtered_accperstim(title,df,num_days=7, **kwargs):
    '''
    plots accuracy per stim for a subject on the past num_days.
    '''
    plot_accperstim(title, utils.filter_normal_trials(utils.filter_recent_days(df, num_days)), **kwargs)

def plot_accperstim(title, data_to_analyze, stim_ids='stimulus', stims_all=None, label_count_cutoff=50, extract_stim_names=True):
    '''
    percent correct broken out by stimulus and day.

    Parameters:
    -----------
    title : str
        the plot title
    data_to_analyze : pandas DataFrame
        filtered data to plot. Can be a slice, a copy is made anyways.
    stim_ids : str
        label of the column to group-by.
    stims_all : None or list-like
        order of stims. must match values in stim_ids
    label_count_cutoff : int
        max number of stimuli labels. If below this value will sort stim_ids by class.
    extract_stim_names : boolean
        whether to extract stimuli names from full stimuli paths. If true, ignores stim_ids.
    '''
    data_to_analyze = data_to_analyze.copy()
    if extract_stim_names:
        stim_ids = 'stim_name'
        utils.extract_filename(data_to_analyze, target=stim_ids)
    data_to_analyze['date'] = data_to_analyze.index.date

    blocked = data_to_analyze.groupby(['date', stim_ids])
    aggregated = pd.DataFrame(blocked.agg({'correct': lambda x: np.mean(x.astype(float))}).to_records())
    pivoted = aggregated.pivot(stim_ids, 'date', 'correct')
    if stims_all:
        yticklabels = stims_all
    elif len(pivoted)<label_count_cutoff:
        yticklabels = data_to_analyze.groupby(['class_', stim_ids]).index.unique().index.get_level_values(stim_ids).values
    else:
        yticklabels = int(len(pivoted)/label_count_cutoff)
    cmap = sns.diverging_palette(15, 250, as_cmap=True)
    cmap.set_bad(color = 'k', alpha = 0.5)
    plt.figure()
    g = sns.heatmap(pivoted, vmin=0, vmax=1, cmap=cmap,
                    xticklabels=_date_labels(pivoted.keys().values),
                    yticklabels=yticklabels)
    g.set_title(title)

def plot_daily_accuracy(subj, df, x_axis='trial_num', smoothing='gaussian', day_lim=0):
    '''
    plots the accuracy of the subject throughout the day.
    a preset for the more general plot_accuracy_bias

    Parameters:
    -----------
    subj : str
        the subject
    df : pandas DataFrame
        data frame of behavior data
    x_axis : str
        whether to plot 'time' or 'trial_num' along the x axis
    smoothing : str
        whether to smooth using 'exponential', 'rolling' average,
        'gaussian' filter'
    day_lim : None or non-negative int
        max number of days of trials to include. Zero means just today.
    '''
    plot_accuracy_bias(subj, df, x_axis=x_axis, smoothing=smoothing, trial_lim=None, day_lim=day_lim,
                        plt_correct_smoothed=True, plt_correct_shade=True, plt_correct_line=True,
                        plt_L_response_smoothed=False, plt_L_response_shade=False, plt_L_response_line=False,
                        plt_R_response_smoothed=False, plt_R_response_shade=False, plt_R_response_line=False,
                        plt_ci=False, block_size=100)

def plot_ci_accuracy(subj, df, x_axis='time', day_lim=7, trial_lim=None, bias=True):
    '''
    plots the accuracy (and bias) of the subject throughout the day.
    a preset for the more general plot_accuracy_bias

    Parameters:
    -----------
    subj : str
        the subject
    df : pandas DataFrame
        data frame of behavior data
    x_axis : str
        whether to plot 'time' or 'trial_num' along the x axis
    trial_lim : None or int
        max number of most recent trials to include
    day_lim : None or non-negative int
        max number of days of trials to include. Zero means just today.
    bias : boolean
        whether to plot the line for the left bias
    '''
    plot_accuracy_bias(subj, df, x_axis=x_axis, smoothing='rolling', trial_lim=None, day_lim=day_lim,
                        plt_correct_smoothed=True, plt_correct_shade=False, plt_correct_line=False,
                        plt_L_response_smoothed=bias, plt_L_response_shade=False, plt_L_response_line=False,
                        plt_R_response_smoothed=False, plt_R_response_shade=False, plt_R_response_line=False,
                        plt_ci=True, block_size=100)

def plot_accuracy_bias(subj, df, x_axis='time', smoothing='exponential', trial_lim=None, day_lim=7,
                        plt_correct_smoothed=True, plt_correct_shade=True, plt_correct_line=True,
                        plt_L_response_smoothed=False, plt_L_response_shade=False, plt_L_response_line=False,
                        plt_R_response_smoothed=False, plt_R_response_shade=False, plt_R_response_line=False,
                        plt_ci=False, block_size=100):
    '''
    plots the accuracy or bias of the subject.

    Parameters:
    -----------
    subj : str
        the subject
    df : pandas DataFrame
        data frame of behavior data
    x_axis : str
        whether to plot 'time' or 'trial_num' along the x axis
    smoothing : str
        whether to smooth using 'exponential', 'rolling' average,
        'gaussian' filter'
    trial_lim : None or int
        max number of most recent trials to include
    day_lim : None or non-negative int
        max number of days of trials to include. Zero means just today.
    plt_{correct, L_response, R_response}_smoothed : boolean
        whether to plot a smoothed line for the value
    plt_{correct, L_response, R_response}_shade : boolean
        whether to plot a red shaded region filling in the line of actual responses
    plt_{correct, L_response, R_response}_line : boolean
        whether to plot a red line of the actual responses
    '''
    fig = plt.figure(figsize=(16, 2))
    if trial_lim is not None:
        df = df[-trial_lim:]
    if day_lim is not None:
        df = utils.filter_recent_days(df, day_lim)
    df = utils.filter_normal_trials(df)
    if x_axis == 'time':
        x = df.index._mpl_repr()
        use_index=True
    elif x_axis == 'trial_num':
        x = np.arange(len(df))
        use_index=False
    else:
        raise Exception('invalid value for x_axis')

    datas = (df['correct'], df['response']=='L', df['response']=='R')
    plot_smoothed_mask = (plt_correct_smoothed, plt_L_response_smoothed, plt_R_response_smoothed)
    plot_shaded_mask = (plt_correct_shade, plt_L_response_shade, plt_R_response_shade)
    plot_line_mask = (plt_correct_line, plt_L_response_line, plt_R_response_line)

    for data, smoothed, shaded, line in zip(datas, plot_smoothed_mask, plot_shaded_mask, plot_line_mask):
        if shaded:
            plt.fill_between(x, .5, data.values.astype(bool), color = 'r', alpha = .25)
        if line:
            g = data.plot(color='r', marker='o', linewidth = .5, use_index=use_index)
        if smoothed:
            if smoothing == 'exponential':
                data.ewm(halflife=20).mean().plot(use_index=use_index)
            elif smoothing == 'gaussian':
                plt.plot(x, sp.ndimage.filters.gaussian_filter(data.values.astype('float32'), 3, order=0))
            elif smoothing == 'rolling':
                data.rolling(window=block_size, center=True).mean().plot(use_index=use_index)
            else:
                raise Exception('invalid value for smoothing')

    if plt_ci and smoothing == 'rolling':
        ci = utils.binomial_ci(0.5*block_size,block_size)
        plt.axhspan(ci[0],ci[1],color='grey',alpha=0.5)
    plt.axhline(y=.5, c='black', linestyle='dotted')
    plt.title('Today\'s Performance: '+subj)
    plt.xlabel(x_axis)

def plot_trial_feeds(behav_data, num_days=7):
    '''
    plots numer of trials and number of feeds for all birds across time

    Parameters:
    -----------
    behav_data : dict of pandas dataframes
        from loading.load_data_pandas
    num_days : non-negative int
        number of days to include data for
    '''
    colors = sns.hls_palette(len(behav_data))
    fig = plt.figure(figsize=(16.0, 4.0))
    ax1 = fig.gca()
    ax2 = ax1.twinx()

    for (subj, df), color in zip(behav_data.items(), colors):
        data_to_analyze = utils.filter_recent_days(df, num_days).copy()
        if not data_to_analyze.empty:
            data_to_analyze['date'] = data_to_analyze.index.date
            blocked = data_to_analyze.groupby('date')

            days = np.sort(blocked.groups.keys())
            trials_per_day = blocked['response'].count().values
            line = ax1.plot(days, trials_per_day, label=subj + ' trials per day', c=color)
            if len(days) == 1:
                plot(0, trials_per_day[-1], 'o', c=color, ax=ax1)

            aggregated = blocked.agg({'reward': lambda x: np.sum((x==True).astype(float))})
            aggregated['reward'].plot(ax=ax2, label=subj + ' feeds per day', ls='--', c=color)
            if len(days) == 1:
                ax2.plot(0, aggregated['reward'][0], 'o', c=color)

    plt.title('trials and feeds per day')
    for ax, label, loc in zip((ax1, ax2), ('trials per day', 'feeds per day'), ('upper left', 'upper right')):
        ax.set_ylabel(label)
        ax.set_ylim(bottom=0)
        ax.legend(loc=loc)
    ax1.set_xticklabels(_date_labels(days))


import numpy as np
from math import sqrt
import matplotlib.pyplot as plt
import warnings
from matplotlib import style
from collections import Counter
style.use('fivethirtyeight')

dataset ={'k':[[1,2],[2,3],[3,1]], 'r':[[6,5],[7,7],[8,6]]}

new_features = [5,5]

def k_nearst_neighbors(data, predict, k=3):
    if len(data)>=k:
        warnings.warn('k is set to a value than total voting groups!')

    distances = []
    for group in data:
        print(group)
        for features in data[group]:
            print(features)
            #euclidean_distance = sqrt( (features[0]-predict[0])**2 + (features[1]-predict[1])**2 )
            euclidean_distance = np.linalg.norm(np.array(features)-np.array(predict))
            distances.append([euclidean_distance, group])
    votes = [i[1] for i in sorted(distances) [:k]]
    print(Counter(votes).most_common(1))
    vote_result = Counter(votes).most_common(1)[0][0]

    return vote_result

result = k_nearst_neighbors(dataset, new_features, k=3)
print(result)


""" Compute mechancis for a given trial:
    Output = Total energy(t) = Kinetic energy(t) + potential energy(t)
    Total power(t) = upper body power(t) + lower body power(t)
    Friction(t)
    Aero drag(t)

    """
import sys

sys.path.insert(0, "srcPython")
import util
import mvn
from subject import Subject
import numpy as np
import matplotlib.pyplot as plt
import copy
from tqdm import tqdm
from matplotlib import use as plt_use
from pspline import PSpline
import scipy.interpolate as intrp
import quaternion as quat
from pose import Pose

plt_use("MacOSX")

def delta_x(com, slope, hand):
    dx = np.abs(np.cos(slope) * (com[0] - hand[0]) - np.sin(slope) * (com[1] - hand[1]))
    return dx

sub = Subject(6)
sub.load_trial("hard", "xsens")
frame = 29000

n = sub.mvnx.frame_count

p = sub.poses[29000]

x = []
y = []

for i in range(1, n):
    p0 = sub.gnss.pos[i - 1, :][0:2]
    p1 = sub.gnss.pos[i, :][0:2]
    x.append(np.linalg.norm(p1 - p0))
    y.append(sub.gnss.pos[i, 2])

x = np.array([0, *np.cumsum(x)])
y = np.array([sub.gnss.pos[0, 2], *y])
time = sub.gnss.time

nslope = np.zeros((n, 2))
nslope[:, 0] = intrp.CubicSpline(time, x).derivative(1)(time)
nslope[:, 1] = intrp.CubicSpline(time, y).derivative(1)(time)

for i in range(n):
    nslope[i, :] = nslope[i, :] / np.linalg.norm(nslope[i, :])

slope_angle = np.arctan2(np.diff(x), np.diff(y))

slope_angle = [0, *slope_angle]

ax = plt.subplot()
ax.plot(x, y)
ax2 = ax.twinx()
ax2.plot(x, dslope2[:, 1], color=util.CMAP(1))
# ax2.plot(x, slope_angle, color = util.CMAP(1))
plt.show()

x_com = np.zeros(np.shape(x))
y_com = np.zeros(np.shape(y))
for i in range(n):
    x_com[i] = x[i] + sub.poses[i].get_com()[0]
    y_com[i] = y[i] + sub.poses[i].get_com()[2]

ax = plt.subplot()
ax.plot(x, y)
ax.plot(x_com, y_com, color=util.CMAP(2))
ax2 = ax.twinx()
ax2.plot(x, slope_angle, color=util.CMAP(1))
plt.show()

# Compute hand position relative to contact
r_hand = np.zeros((n, 2))
l_hand = np.zeros((n, 2))
contact = np.zeros((n, 2))
for i in range(n):
    contact_raw = (
        np.array([sub.poses[i].points["RightToe"] + sub.poses[i].points["LeftToe"]]) / 2
    )
    contact_raw = np.array([contact_raw[0][0], contact_raw[0][2]])
    contact[i] = contact_raw
    com = [sub.poses[i].get_com()[0], sub.poses[i].get_com()[2]]
    r_hand_raw = [
        sub.poses[i].points["RightHand"][0],
        sub.poses[i].points["RightHand"][2],
    ]
    l_hand_raw = [
        sub.poses[i].points["LeftHand"][0],
        sub.poses[i].points["LeftHand"][2],
    ]
    r_hand[i] = r_hand_raw - contact[i]
    l_hand[i] = l_hand_raw - contact[i]

ax = plt.subplot()
ax.plot(time[0:20], l_hand[0:20, 0])
plt.show()

# Compute hand velocity
dl_hand = np.zeros((n, 2))
dl_hand[:, 0] = intrp.CubicSpline(time, l_hand[:, 0]).derivative(1)(time)
dl_hand[:, 1] = intrp.CubicSpline(time, l_hand[:, 1]).derivative(1)(time)

dr_hand = np.zeros((n, 2))
dr_hand[:, 0] = intrp.CubicSpline(time, r_hand[:, 0]).derivative(1)(time)
dr_hand[:, 1] = intrp.CubicSpline(time, r_hand[:, 1]).derivative(1)(time)

l_speed_thresh = np.zeros((n,))
r_speed_thresh = np.zeros((n,))

for i in range(n):

    if np.linalg.norm(dl_hand[i, :]) > 1:  # Filter to speed > 1m/s
        l_speed_thresh[i] = 1

    if np.linalg.norm(dr_hand[i, :]) > 1:
        r_speed_thresh[i] = 1

    dl_hand[i, :] = dl_hand[i, :] / np.linalg.norm(dl_hand[i, :])
    dr_hand[i, :] = dr_hand[i, :] / np.linalg.norm(dr_hand[i, :])

# Compute tip position
l_pole_tip = sub.pole_length * dl_hand + l_hand
r_pole_tip = sub.pole_length * dr_hand + r_hand

# Compute tip penetration
dx_l = np.zeros((n,))
dx_r = np.zeros((n,))
dx_l2 = np.zeros((n,))
dx_r2 = np.zeros((n,))

for i in range(n):
    if (np.arctan2(dl_hand[i, 0], dl_hand[i, 1]) < -np.pi / 2) & (
        np.arctan2(dl_hand[i, 0], dl_hand[i, 1]) > -np.pi
    ):
        dx_l[i] = np.linalg.norm(
            np.cross(l_pole_tip[i, :], dslope[i, :])
        ) / np.linalg.norm(dslope[i, :])
    if (np.arctan2(dr_hand[i, 0], dr_hand[i, 1]) < -np.pi / 2) & (
        np.arctan2(dr_hand[i, 0], dr_hand[i, 1]) > -np.pi
    ):
        dx_r[i] = np.linalg.norm(
            np.cross(r_pole_tip[i, :], dslope[i, :])
        ) / np.linalg.norm(dslope[i, :])

ax = plt.subplot()
ax.plot(time, dx_l)
ax.plot(time, dx_r)
plt.show()

# compute pole force
# Max pole force = 430 N Stoggl et al. 2016
MAX_POLE_FORCE = 450  # combined left/right
k_gc = MAX_POLE_FORCE / np.max(np.max([np.vstack((dx_l, dx_r))]))
Fp_l = np.zeros((n, 2))
Fp_r = np.zeros((n, 2))
for i in range(n):
    Fp_l[i, :] = (
        l_speed_thresh[i]
        * k_gc
        * dx_l[i]
        * -dl_hand[i, :]
        / np.linalg.norm(dl_hand[i, :])
    )
    Fp_r[i, :] = (
        r_speed_thresh[i]
        * k_gc
        * dx_r[i]
        * -dr_hand[i, :]
        / np.linalg.norm(dl_hand[i, :])
    )

ax = plt.subplot()
ax.plot(time, Fp_l[:, 0])
ax.plot(time, Fp_l[:, 1])
plt.show()

# Compute SKI FORCE
dt = 1 / sub.mvnx.frame_rate
# Compute ski position relative to com
r_ski = np.zeros((n, 2))
l_ski = np.zeros((n, 2))
com = np.zeros((n, 2))
for i in range(n):
    com[i, :] = [sub.poses[i].get_com()[0], sub.poses[i].get_com()[2]]
    r_ski_raw = [sub.poses[i].points["RightToe"][0], sub.poses[i].points["RightToe"][2]]
    l_ski_raw = [sub.poses[i].points["LeftToe"][0], sub.poses[i].points["LeftToe"][2]]
    r_ski[i, :] = r_ski_raw - com[i, :]
    l_ski[i, :] = l_ski_raw - com[i, :]

# compute ski velocity
# Compute hand velocity
dl_ski = np.zeros((n, 2))
dl_ski[:, 0] = intrp.CubicSpline(time, l_ski[:, 0]).derivative(1)(time)
dl_ski[:, 1] = intrp.CubicSpline(time, l_ski[:, 1]).derivative(1)(time)

dr_ski = np.zeros((n, 2))
dr_ski[:, 0] = intrp.CubicSpline(time, r_ski[:, 0]).derivative(1)(time)
dr_ski[:, 1] = intrp.CubicSpline(time, r_ski[:, 1]).derivative(1)(time)

ax = plt.subplot()
ax.plot(time, dl_ski[:, 0])
plt.show()

#  compute force
k_sc = (
    0.8 * sub.get_total_mass() * util.GRAVITY / np.max(np.vstack((dl_ski, dr_ski))) / 2
)
Fs_l = np.zeros((n, 2))
Fs_r = np.zeros((n, 2))
for i in range(n):
    if (dl_ski[i, 0] < 0) & (dl_ski[i, 1] < 0):
        Fs_l[i, :] = (
            k_sc
            * np.linalg.norm(dl_ski[i, :])
            * -dl_ski[i, :]
            / np.linalg.norm(dl_ski[i, :])
        )
    if (dr_ski[i, 0] < 0) & (dr_ski[i, 1] < 0):
        Fs_r[i, :] = (
            k_sc
            * np.linalg.norm(dr_ski[i, :])
            * -dr_ski[i, :]
            / np.linalg.norm(dr_ski[i, :])
        )

ax = plt.subplot()
ax.plot(time, Fs_l[:, 0])
ax.plot(time, Fs_l[:, 1])

plt.show()

# Compute Aero Drag
C_d = 0.67

# compute deriative of position
dx = np.zeros((n, 2))
dx[:, 0] = intrp.CubicSpline(time, x_com).derivative(1)(time)
dx[:, 1] = intrp.CubicSpline(time, y_com).derivative(1)(time)
# compute velocity
v = intrp.CubicSpline(time, x).derivative(1)(time)

# get area and drag force
frontal_area = np.zeros((n,))
F_aero = np.zeros((n, 2))
for i in range(n):
    frontal_area[i] = sub.poses[i].area
    F_aero[i, :] = 0.5 * sub.weather.density * C_d * v[i] ** 2 * frontal_area[i] - dx[
        i, :
    ] / np.linalg.norm(dx[i, :])

ax = plt.subplot()
ax.plot(time, F_aero[:, 0])
ax.plot(time, F_aero[:, 1])
ax2 = ax.twinx()
ax2.plot(time, frontal_area)

plt.show()

# sum Forces in X/y
slope_angle = np.pi / 2 - np.arctan2(nslope[:, 0], nslope[:, 1])

def rotMat(theta):
    return np.array([[np.cos(theta), -np.sin(theta)], [np.sin(theta), np.cos(theta)]])

# Project into slope coordinate system
SumF_partial = np.zeros((n, 2))
SumF_partial[:, 0] = Fp_l[:, 0] + Fp_r[:, 0] + Fs_l[:, 0] + Fs_r[:, 0] + F_aero[:, 0]
SumF_partial[:, 1] = (
    Fp_l[:, 1]
    + Fp_r[:, 1]
    + Fs_l[:, 1]
    + Fs_r[:, 1]
    + F_aero[:, 1]
    - sub.get_total_mass() * util.GRAVITY
)

SumF_partial_slope = np.zeros((n, 2))
for i in range(n):
    SumF_partial_slope[i, :] = rotMat(slope_angle[i]) @ SumF_partial[i, :]

# Compute friction
mu = 0.06

def compute_forces_with_friction(SumF_partial_slope, slope_angle, mu):
    SumF = np.zeros((n, 2))
    friction = mu * SumF_partial_slope[:, 1]  # compute friction
    SumF_partial_slope[:, 0] += friction  # add to sum in slope CS
    for i in range(n):  # reorient back to GCS
        SumF[i] = np.transpose(rotMat(slope_angle[i])) @ SumF_partial_slope[i, :]

    return SumF

SumF = compute_forces_with_friction(SumF_partial_slope, slope_angle, mu)

# Compute Work
Wt = np.zeros((n,))
Ws = np.zeros((n,))
Wp = np.zeros((n,))
xy = np.column_stack((x, y))

Fs = Fs_l + Fs_r
Fp = Fp_l + Fp_r
for i in range(1, n):
    Wt[i] = np.dot(SumF[i, :], dx[i, :] * dt)
    Ws[i] = np.dot(Fs[i, :], dx[i, :] * dt)
    Wp[i] = np.dot(Fp[i, :], dx[i, :] * dt)

Power = intrp.CubicSpline(time, np.exp(Wp)).derivative(1)(time)
Ps = intrp.CubicSpline(time, np.exp(Wp)).derivative(1)(time)
Pp = intrp.CubicSpline(time, np.exp(Ws)).derivative(1)(time)

Wp_smooth = intrp.splrep(time, Wp, s=1.6 * sub.mvnx.frame_count)
Ws_smooth = intrp.splrep(time, Ws, s=2.5 * sub.mvnx.frame_count)

fig, (ax, ax2) = plt.subplots(1, 2)
ax.plot(time, intrp.BSpline(*Wp_smooth)(time))
ax.plot(time, Wp, color=util.CMAP(0), alpha=0.1)
ax.set_xlabel("Time [s]")
ax.set_ylabel("Work [J]")
ax.set_ylim((-4, 20))
ax.set_title("Work done by upper body")

ax2.plot(time, intrp.BSpline(*Ws_smooth)(time))
ax2.plot(time, Ws, color=util.CMAP(0), alpha=0.1)
ax2.set_xlabel("Time [s]")
ax2.set_ylabel("Work [J]")
ax2.set_ylim((-3, 20))
ax2.set_title("Work done by lower body")
plt.show()

def get_potential_energy(sub, frame=-1):
    print("STATUS: Estimating Potential energy")

    h0 = sub.gnss.pos[:, 2]
    n = sub.mvnx.frame_count
    M = sub.get_total_mass()

    if frame == -1:
        # pelvis_height = np.asarray(sub.mvnx.get_segment_pos(mvn.SEGMENT_PELVIS))[
        #     :, 2
        # ]  # note x./y dimensions are both 0

        # Set minimum height to zero.
        h0 = h0 - np.min(h0)

        E_pot = np.zeros(n)
        com_lcs, _ = sub.get_segment_pos()
        for frame in range(n):
            E_pot[frame] += M * util.GRAVITY * (h0[frame] + com_lcs[frame, 2])
    else:
        # pelvis_height = np.asarray(sub.mvnx.get_segment_pos(mvn.SEGMENT_PELVIS, frame))[
        #     2
        # ]  # note x./y dimensions are both 0

        h0 = h0[frame] - h0[0]
        com_lcs, _ = sub.get_segment_pos(frame=frame)
        E_pot = M * util.GRAVITY * (h0 + com_lcs[2])

    return E_pot

def get_kinetic_energy(sub, frame=-1):
    print("STATUS: Estimating Kinetic energy")
    _, v0, _ = sub.kalman.predict(sub, 0)
    n = sub.mvnx.frame_count
    if frame == -1:
        E_kin_lin = np.zeros((n,))
        E_kin_rot = np.zeros((n,))
        E_kin = np.zeros((n,))
        for (i, seg) in enumerate(tqdm(sub.segment_mdl.keys())):
            print("STATUS: Processing segment: {}".format(seg))
            I = np.diag(sub.segment_mdl[seg].inertia)
            v_i = np.zeros((n, len(util.SEGMENT_TO_XSENS[seg]), 3))
            omega_i = np.zeros((n, len(util.SEGMENT_TO_XSENS[seg]), 3))
            for (j, xseg) in enumerate(util.SEGMENT_TO_XSENS[seg]):
                v_i[:, j, :], _ = sub.get_segment_vel(segment=xseg)
                omega_i[:, j, :] = sub.mvnx.get_segment_angular_vel(xseg)
            v_i = np.mean(v_i, axis=1)
            omega_i = np.mean(omega_i, axis=1)

            for frame in range(n):
                I_f = util.quat_to_rot_mat(sub.mvnx.get_segment_ori(0, frame)) @ I

                v = v0[frame, :] + v_i[frame, :]
                E_kin_lin[frame] += 0.5 * sub.segment_mdl[seg].mass * np.dot(v, v)
                E_kin_rot[frame] += (
                    0.5 * np.transpose(omega_i[frame, :]) @ I_f @ omega_i[frame, :]
                )
                E_kin[frame] = E_kin_lin[frame] + E_kin_rot[frame]

    else:
        # TODO FROM HERE FOR SINGLE FRAME
        for (i, seg) in enumerate(sub.segment_mdl.keys()):
            I = np.diag(sub.segment_mdl[seg].inertia)
            v_i = np.zeros((len(util.SEGMENT_TO_XSENS[seg]), 3))
            omega_i = np.zeros((len(util.SEGMENT_TO_XSENS[seg]), 3))
            for (j, xseg) in enumerate(util.SEGMENT_TO_XSENS[seg]):
                v_i[j, :], _ = sub.get_segment_vel(xseg, frame)
                omega_i[j, :] = sub.mvnx.get_segment_angular_vel(xseg, frame)
            v_i = np.mean(v_i, axis=0)
            omega_i = np.mean(omega_i, axis=0)

            v = v0[frame, :] + v_i
            E_kin_lin = 0.5 * sub.segment_mdl[seg].mass * np.dot(v, v)
            E_kin_rot = 0.5 * np.transpose(omega_i) @ I @ omega_i
        E_kin = E_kin_lin + E_kin_rot

    return E_kin, E_kin_lin, E_kin_rot


from turtle import color
from matplotlib import pyplot
companies=['hp','acer','lenovo','dell','apple']
itemsold=[122,54,88,121,158]
clrs=['red','green','blue','yellow','gray']

pyplot.bar(companies,itemsold,color=clrs)
pyplot.xlabel('laptop')
pyplot.ylabel('sales')
pyplot.title('laptop sales in 2022')
pyplot.show()


# config : utf-8

import os
import sys
import psutil
import shutil

print ('Hi, Jackson!')
name = input("What's your name?")
print ("Hi, ", name)

answer = ''
while answer != 'q':
    answer = input("Shal we? y/n/q")
    if answer == "y":
        print ("OK")
        print ("1 - вывести инфо о системе")
        print ("2 - список файлов текущей дирректории")
        print ("3 - список ID активных процессов")
        print ("4 - дублирование файлов текущей дирректории")
        print ("5 - удаление дубликатов файлов текущей дирректории")

        do = int(input("Что делаем?  "))

        if do == 1:
            print ("процессоров: ", psutil.cpu_count())
            print ("Платформа: ", sys.platform)
            print ("Пользователь: ", os.getlogin())
        elif do == 2:
            print ("Список файлов: ", os.listdir())
        elif do == 3:
            print ("Списк процессов (ID): ", psutil.pids())
        elif do == 4:
            print("Дублирование файлов указанной дирректории")
            file_list = os.listdir()
            i = 0
            while i < len(file_list):
                if os.path.isfile(file_list[i]):
                    newfile = file_list[i] + '.dupl'
                    shutil.copy(file_list[i], newfile)
                    i += 1
                else:
                    pass

        else:
            pass

    elif answer == "n":
        print ("Sad")
    else:
        print ("Pitty")


# QLable

import sys
from PyQt5.QtWidgets import QApplication, QWidget, QLabel
from PyQt5.QtGui import QPixmap

class Lable(QWidget):
    def __init__(self):
        super().__init__()
        self.initGUI()

    def initGUI(self):
        self.setGeometry(100,100,900,700)
        self.setWindowTitle('gui demo')

        self.lable1 = QLabel(self)
        self.lable1.setText('Python Class')
        self.lable1.move(390, 40)

        self.lable2 = QLabel(self)
        self.lable2.setToolTip('http://goo.gl/pB9kmb')
        self.lable2.setText("<a href='http://goo.gl/pB9kmb'> Surprise URL </a>")
        self.lable2.move(390,90)
        self.lable2.setOpenExternalLinks(True)

        self.lable3 = QLabel(self)
        self.lable3.move(80, 130)
        self.lable3.setPixmap(QPixmap('a.png'))

        self.show()

if __name__ == "__main__":
        app = QApplication(sys.argv)
        Lable = Lable()
        sys.exit(app.exec_())


# -*- coding: utf-8 -*-
#Import libraries

import numpy as np
import gc
from sklearn.linear_model import LogisticRegression
from scipy import linalg
import random

## MCMC sampler for the minimum information dependence model with canonical statistics h and canonical parameter theta

def min_info_mcmc(X,h,loop,theta,printop=False):

###############################################################################
  #INPUT
  ## X: initial sample list [[multivariate sample 1],[multivariate sample 2],...]
  ## h   : canonical statistics function (from X (d-dim list) to R^K K-dim array)
  ## loop: number of mcmc steps
  ## theta: canonical parameter (np.array)
  ## printop: print option (if True then print the acceptance rate every 1000 steps)

  #OUTPUT
  ## list of Markov chains (list of Xs)
  ## output[0]  yields the input
  ## output[-1] yields the final output
###############################################################################

  if len(X) ==0:
    print("NULL list")
  else:
    n = len(X)
    d = len(X[0])
    output_list = [X]
    acceptancenum = 0
    for Li in range(loop):
      i  = random.sample(range(d),1)[0]
      s,t = random.sample(range(n),2)[0:2]
      X_iswap_s = output_list[Li][s].copy()
      X_iswap_t = output_list[Li][t].copy()

      X_iswap_s[i] = output_list[Li][t][i]
      X_iswap_t[i] = output_list[Li][s][i]

      h_diff = h(output_list[Li][s])+h(output_list[Li][t])-h(X_iswap_s)-h(X_iswap_t)
      log_rho_tilde  = np.min([np.log(1),-theta.dot(h_diff)])
      u  = np.random.uniform(low=0,high=1,size=1)
      if np.log(u) < log_rho_tilde:
        X_new = output_list[Li].copy()
        X_new[s] = X_iswap_s
        X_new[t] = X_iswap_t
        output_list.append(X_new)
        del X_new

        acceptancenum = acceptancenum + 1
      else:
        output_list.append(output_list[Li])
      del X_iswap_s
      del X_iswap_t
      if (Li % 10000 == 0):
        gc.collect()
      if (Li % 1000 == 0) and (printop == True):
        print("Step/Total : "+str(Li)+"/"+str(loop)+" Acceptance rate : "+str(np.round(acceptancenum/(Li+1),2)))
    return output_list

## Besag pseudo-likelihood estimation

def min_info_Besag(X,h,max_iter,tol,sparseop=False,sparsepen=1.):

###############################################################################
  #INPUT
  ## X        : initial sample list [[multivariate sample 1],[multivariate sample 2],...]
  ## h        : canonical statistics (from X (d-dim list) to R^K)
  ## max_iter : number of iteration
  ## tol      : tolerance value for the optimizer
  ## sparseop : if True, add l1 penalty
  ## sparsepen: penalty strength valid only if sparseop is True.

  #OUTPUT
  ## estimate (K-dim array)
###############################################################################

  if len(X) ==0:
    print("NULL list")
  else:
    n = len(X)
    d = len(X[0])
    Us = []
    Ys = []
    for i in range(d):
          for t in range(n):
            for s in range(t):

              X_iswap_s = X[s][:]
              X_iswap_t = X[t][:]
              X_iswap_s[i] = X[t][i]
              X_iswap_t[i] = X[s][i]
              Us.append(h(X[s])+h(X[t])-h(X_iswap_s)-h(X_iswap_t))
              if (t==(n-1))&(s == (n-2)):
                Ys.append(0)
              else:
                Ys.append(1)
    if sparseop==False:
      model = LogisticRegression(solver='liblinear',random_state=0,C=1e10,fit_intercept=False,tol=tol,max_iter=max_iter).fit(np.array(Us), Ys)
    else:
      model = LogisticRegression(solver='saga',random_state=0,C=sparsepen,penalty="l1",fit_intercept=False,tol=tol,max_iter=max_iter).fit(np.array(Us), Ys)
    return model.coef_[0]

## Bootstrap for Besag pseudo-likelihood estimation

def min_info_Besag_bootstrap(X,h,tol,max_iter,B,sparseop=False,sparsepen=1.):

###############################################################################
  #INPUT
  ## X       : initial sample list [[multivariate sample 1],[multivariate sample 2],...]
  ## h       : canonical statistics (from X (d-dim list) to R^K)
  ## max_iter: size of iteration
  ## tol     : tolerance value for the optimizer
  ## B       : size of bootstrap samples
  ## sparseop : if True, add l1 penalty
  ## sparsepen: penalty strength valid only if sparseop is True.

  #OUTPUT
  ## bootstrap samples of estimates
  ## mean of bootstraped estimates
  ## covariance of bootstraped estimates
###############################################################################

  n = len(X)
  bootstrap_Besag=[]
  for b in range(B):
    boot_sample=[X[i] for i in random.choices(range(n),k=n)]
    bootstrap_Besag.append(min_info_Besag(X=boot_sample,h=h,tol=tol,max_iter=max_iter,sparseop=sparseop,sparsepen=sparsepen))
  boot_mean = sum(bootstrap_Besag)/B
  boot_cov_1   = sum([np.tensordot(bootstrap_Besag[l],bootstrap_Besag[l],axes=0) for l in range(B)])/B
  boot_cov_2   = np.tensordot(boot_mean,boot_mean,axes=0)
  boot_cov     = boot_cov_1-boot_cov_2
  return bootstrap_Besag, boot_mean, boot_cov

## Calculation of score vector & Hessian of Besag pseudo likelihood
## Calculation of asymptotic covariance of Besag pseudo likelihood estimates

def min_info_Besag_score(x1,x2,h,theta):
###############################################################################
  #INPUT
  ## x1      : multivariate sample
  ## x2      : multivariate sample
  ## h       : canonical statistics (from X (d-dim list) to R^K)
  ## theta   : dependence parameter

  #OUTPUT
  ## score of Pseudo likelihood

  d = len(x1)
  K = theta.shape[0]
  score = 0*h(x1)

  for i in range(d):
    x_iswap_1 = x1[:]
    x_iswap_2 = x2[:]
    x_iswap_1[i] = x2[i]
    x_iswap_2[i] = x1[i]

    ui = h(x1)+h(x2)-h(x_iswap_1)-h(x_iswap_2)
    score = score + (-1)*ui/(1+np.exp(theta.dot(ui)))

  return score

def min_info_Besag_Hessian(x1,x2,h,theta):
###############################################################################
  #INPUT
  ## x1      : multivariate sample
  ## x2      : multivariate sample
  ## h       : canonical statistics (from X (d-dim list) to R^K)
  ## theta   : dependence parameter

  #OUTPUT
  ## Hessian of Pseudo likelihood

  d = len(x1)
  K = theta.shape[0]
  H = np.zeros(K*K).reshape((K,K))

  for i in range(d):
    x_iswap_1 = x1[:]
    x_iswap_2 = x2[:]
    x_iswap_1[i] = x2[i]
    x_iswap_2[i] = x1[i]

    ui = h(x1)+h(x2)-h(x_iswap_1)-h(x_iswap_2)
    Mi = np.tensordot(ui,ui,axes=0)
    H = H + Mi/(1+np.exp(theta.dot(ui)))**2

  return H

def min_info_Besag_asymptoticCovariance(X,h,tol,max_iter):

###############################################################################
  #INPUT
  ## X       : initial sample list [[multivariate sample 1],[multivariate sample 2],...]
  ## h       : canonical statistics (from X (d-dim list) to R^K)
  ## max_iter: size of iteration
  ## tol     : tolerance value for the optimizer

  #OUTPUT
  ## Asymptotic Covariance of PLE
###############################################################################

  n = len(X)
  theta_PLE=min_info_Besag(X=X,h=h,tol=tol,max_iter=max_iter,sparseop=False)
  d = theta_PLE.shape[0]
  I = np.zeros(d*d).reshape((d,d))
  J = np.zeros(d*d).reshape((d,d))

  for s in range(n):
    conditional_score = np.zeros(d)
    for t in range(n):
      conditional_score = conditional_score + (1/n)* min_info_Besag_score(x1=X[s],x2=X[t],h=h,theta=theta_PLE)
      if (t<s):
        B=min_info_Besag_Hessian(x1=X[s],x2=X[t],h=h,theta=theta_PLE)
        J=J+B/(n*(n-1)/2)
    I = I + np.tensordot(conditional_score ,conditional_score ,axes=0) / n

  asymptoticCov = (linalg.inv(J) @ I @ linalg.inv(J)) * (4/n)

  return asymptoticCov

## conditional maximum likelihood estimation

def min_info_CLE(X,h,L,burnin,thin,max_L,max_iter,tol,detailop=False):

###############################################################################
  #INPUT
  ## X       : initial sample list [[multivariate sample 1],[multivariate sample 2],...]
  ## h       : canonical statistics (from X (d-dim list) to R^K array)
	## L       : MCMC iteration (length of chain)
	## burnin  : burnin of MCMC
	## thin    : thinning
  ## max_iter: number of iteration
  ## tol     : tolerance value for the optimizer
  ##detailop : if True, print (iteration,L,current estimate, current residual for optimization) at each step

	#OUTPUT
	## list of estimates (by iteration)
	## list of residuals for optimization (by iteration)
	## list of L (by iteration)
	## list of asymptotic covariances (by iteration)
###############################################################################

	if len(X) ==0:
		print("NULL list")
	else:
		n = len(X)
		d = len(X[0])
		init_theta = min_info_Besag(X=X,h=h,tol=10**(-2),max_iter=1000)
		init_res = 10**3
		Li         = 0
		theta_list = [init_theta]
		res_list = [init_res]
		L_list   = [L]
		AsymptoticCov_list = [0]
		current_theta = init_theta #array
		current_res = init_res #real number

		while ((current_res>tol) and (Li<max_iter) and (L<max_L)):
			Li = Li + 1
			current_theta = theta_list[Li-1]
			current_res = res_list[Li-1]
			current_X_MCMC= min_info_mcmc(X=X,h=h,loop=L,theta=current_theta,printop=False)[burnin:L:thin]
			total_MCMC_num=len(current_X_MCMC)
			current_hsum             = sum(list(map(h,X)))
			current_hsum_MCMCsamples = [sum(list(map(h, current_X_MCMC[l]))) for l in range(total_MCMC_num)]
			current_hsum_mean        = sum(current_hsum_MCMCsamples)/total_MCMC_num
			current_hsum_cov_1         = sum([np.tensordot(current_hsum_MCMCsamples[l],current_hsum_MCMCsamples[l],axes=0) for l in range(total_MCMC_num)])/total_MCMC_num
			current_hsum_cov_2         = np.tensordot(current_hsum_mean,current_hsum_mean,axes=0)
			current_hsum_cov           = current_hsum_cov_1-current_hsum_cov_2
			score = current_hsum-current_hsum_mean
			modified_score            = linalg.solve(current_hsum_cov, score)
			theta_list.append(current_theta+modified_score)
			res_list.append(max(abs(score)))
			L_list.append(L)
			AsymptoticCov_list.append( linalg.pinv(current_hsum_cov) )
			##for debug
			if (detailop==True):
				print(Li,L,theta_list[Li],res_list[Li])
			##adaptive scaling of L on the basis of the residual update
			if(current_res>1.1*res_list[Li]):
				L = int(np.floor(1.5*L))
			else:
				L = L
			##restart if estimates are very far from PLE
			if(max(abs(theta_list[Li]) / (1 + abs(theta_list[0]))) > 100):
				theta_list[Li] = theta_list[0]
				print("parameter reseted.")

		theta_list.pop(-1)
		res_list.pop(-1)
		AsymptoticCov_list.pop(-1)
	return theta_list,res_list,L_list,AsymptoticCov_list


# List of all the trackers offered by openCV
OPENCV_TRACKERS = [
    "csrt",
    "kcf",
    "mosse",
    "mil",
    "boosting",
    "tld",
    "medianflow",
]

class TrackerFactory:
    """
    Static factory class used to instantiate new Tracker objects
    """

    @staticmethod
    def create(tracker_type="kcf"):
        """
        Create new Tracker object of a specified type

        Args:
            tracker_type (str): Identifier for tracker type

        Returns:
            (Tracker):
                Returns the created Tracker object or None if unknown
                tracker_type supplied
        """
        if tracker_type in OPENCV_TRACKERS:
            from .trackers.TrackerOpenCV import TrackerOpenCV

            return TrackerOpenCV(tracker_name=tracker_type)
        elif tracker_type == "dlib":
            from .trackers.CorrelationTracker import CorrelationTracker

            return CorrelationTracker()
        else:
            print("Unknown tracker type:", tracker_type)
            return None


class EmptyValue:
    pass

class Tree:
    def __init__(self, root=EmptyValue):
        self.root = root
        self.subtrees = []

    def is_empty(self):
        return self.root is EmptyValue

#non-mutating

    def size(self):
        if self.is_empty():
            return 0
        else:
            size = 1
            for subtree in subtrees:
                size += subtree.size()
            return size

    def count_leaves(self):
        if self.is_empty():
            return 0
        elif self.subtrees == []:
            return 1
        else:
            count = 0
            for subtree in self.subtrees:
                count += subtree.count_leaves()
            return count

    def internal_nodes(self):
        if self.is_empty():
            return 0
        elif self.subtrees == []:
            return 0
        else:
            count = 1
            for subtree in self.subtrees:
                count += subtree.internal_nodes()
            return count

    def count_d(self,d):
        if self.is_empty():
            return 0
        elif d ==1:
            return 1
        else:
            count = 0
            for subtree in self.subtrees:
                count += subtree.count_d(d-1)
            return count

    def count_less(self, d):
        if self.is_empty():
            return 0
        elif d == 1:
            return 1
        else:
            count = 1
            for subtree in self.subtrees:
                count += subtree.count_less(d-1)
            return count

    def count_more(tree, d):
        if tree.is_empty():
            return 0
        else:
            if d == 1:
                count = 1
                for subtree in tree.subtrees:
                    count += subtree.count_more(1)
                return count
            else:
                count = 0
                for subtree in tree.subtrees:
                    count += subtree.count_more(d-1)
                return count

    def check_item(self, item):
        if self.is_empty():
            return 0
        else:
            if self.root == item:
                count = 1
                for subtree in self.subtrees:
                    count += subtree.check_item(item)
                return count
            else:
                count = 0
                for subtree in self.subtrees:
                    count += subtree.check_item(item)
                return count

    def sum(self):
        if self.is_empty():
            return 0
        else:
            sum = self.root
            for subtree in self.subtrees:
                sum += subtree.sum()
            return sum

    def repeat_helper(self,seen):
        if self.is_empty():
            return False
        elif self.root in seen:
            return True
        else:
            seen.append(self.root)
            for subtree in self.subtrees:
                if self.repeat_helper(seen):
                    return True
            return False

    def repeat(self):
        return self.repeat_helper([])

    #def count_repeated(self):

    def count_even(self):
        if self.is_empty():
            return 0

class LLNode(object):
    def __init__(self, value, next):
        self.value = value
        self.next = next

def last_node(start_node):
    new = LLNode()
    curr = start_node.value
    while not curr.next is None:
        new.value = curr
        curr = curr.next.value
    return curr


"""Draw the ellipsoid that contains 50% of a cloud of Points,
then check how many points are inside the surface"""
#
# NB: check out pcaEllipse() method for 2D problems
#
from vedo import *

settings.use_depth_peeling = True

pts = Points(np.random.randn(10000, 3)*[3,2,1] + [50,60,70])

elli = pca_ellipsoid(pts, pvalue=0.50)

elli.inside_points(pts, return_ids=True)

ids  = elli.inside_points(pts, return_ids=True)
pts.print()  # a new "IsInside" array now exists in pts
pin = pts.points()[ids]
print("inside  points #", len(pin))

# Create an inverted mask instead of calling insidePoints(invert=True)
mask = np.ones(pts.npoints, dtype=bool)
mask[ids] = False
pout = pts.points()[mask]
print("outside  points #", len(pout))

# Extra info can be retrieved with:
print("axis 1 size:", elli.va)
print("axis 2 size:", elli.vb)
print("axis 3 size:", elli.vc)
print("axis 1 direction:", elli.axis1)
print("axis 2 direction:", elli.axis2)
print("axis 3 direction:", elli.axis3)
print("asphericity:", elli.asphericity(), '+-', elli.asphericity_error())

a1 = Arrow(elli.center, elli.center + elli.axis1)
a2 = Arrow(elli.center, elli.center + elli.axis2)
a3 = Arrow(elli.center, elli.center + elli.axis3)

show(elli,
     a1, a2, a3,
     Points(pin).c("green4"),
     Points(pout).c("red5").alpha(0.2),
     __doc__,
     axes=1,
).close()


try:
    from .common.ElementView import *
    from .models.TextModels import *
except:
    from common.ElementView import *
    from models.TextModels import *

import string
import pygame
import sys
import re

class BaseTextView(ElementView):
    def __init__(self, model):
        ElementView.__init__(self, model)
        self._model.on('changed', self.on_change)

        self.dirty = True

    def on_change(self, even, **kwargs):
        self.make_dirty()   # change emits in this method
        self.dirty = True

    def init_surface(self):
        self._calculate_size()

        font = self._model.font
        text = self._model.text
        color = self._model.color

        scalar = pygame.transform.scale
        rot = pygame.transform.rotate

        self._surface = font.render(text, False, color)
        self._surface = scalar(self._surface, [int(x) for x in (self.width, self.height)])
        self._surface = rot(self._surface, self._rotation)

        self.dirty = False

    def on_render(self, event, **kwargs):
        if self.dirty:
            self.init_surface()

        ElementView.on_render(self, event, **kwargs)

    def _get_font_size(self):
        return self._model.size
    def _set_font_size(self, value):
        self._model.load_font(self._model.resource, value)
    fontsize = property(_get_font_size, _set_font_size)

    def _get_text(self):
        return self._model.text
    def _set_text(self, text):
        self._model.text = text
    text = property(_get_text, _set_text)

    def _get_color(self):
        return self._model.color
    def _set_color(self, value):
        self._model.set_color(value)
    color = property(_get_color, _set_color)

class TextView(BaseTextView):
    def __init__(self, model):
        BaseTextView.__init__(self, model)

    def render(self, surface):
        if self.text == '\n':
            return

        blitter = pygame.Surface.blit
        blitter(surface, self._surface, (self.x, self.y, self.width, self.height))

class ParagraphView(ElementView):
    def __init__(self, model, width=300):
        ElementView.__init__(self, model)

        self._model.on('changed', self.on_model_changed)

        self._offset_x = self._offset_y = 6

        self.last_text = None
        self.model_dirty = True

        self._width = width
        self.ignore_model_size = True

        self.ignore_in_phrases = []

    ignore = '~`!@#$%^&*()_+=-{[}]\|'";:/?.>,<"

    def init_words(self):
        if self._model.text == self.last_text:
            self.handle_resize()
            return

        self.clear_children()

        txt = re.sub('\n', ' \n ', self._model.text).split(' ')
        for word in txt:
            if word == '\n':
                view = TextView(TextModel(self._model.resource, '\n', self._model.size))
                self.add_child(view)
                continue
            elif len(word.strip()) == 0:
                continue

            clean_word = word.translate(string.maketrans('', ''), string.punctuation)
            if len(clean_word) == 0:
                continue

            # strip punctuation before the word
            for character in word:
                if character == clean_word[0]:
                    break
                elif character in ParagraphView.ignore:
                    view = TextView(TextModel(self._model.resource, character, self._model.size))
                    view.justify = 'left'
                    self.add_child(view)

            view = TextView(TextModel(self._model.resource, clean_word, self._model.size))
            self.add_child(view)

            # strip punctuation after word
            for character in word[::-1]:
                if character == clean_word[-1]:
                    break
                elif character in ParagraphView.ignore:
                    view = TextView(TextModel(self._model.resource, character, self._model.size))
                    view.justify = 'right'
                    self.add_child(view)

        self.handle_resize()
        self.last_text = self._model.text

    def handle_resize(self):
        max_height = 0
        x, y = self._offset_x * 2, self._offset_y

        newline = False
        for child in self.children:
            newline = False
            max_height = max(max_height, child.height)

            if child.text == '\n' or x + child.width > self._width - (self._offset_x * 2):
                x = self._offset_x * 2
                y += max(max_height, child.height)
                newline = True

            try:
                justify = child.justify
                if justify == 'left':
                    child.x = x + self._offset_x
                    child.y = y
                elif justify == 'right':
                    child.x = x - self._offset_x
                    child.y = y

                    if newline:
                        child.y -= max(max_height, child_height)
            except:
                child.x = x
                child.y = y

            if newline:
                max_height = 0

            if child.text != '\n':
                x += child.width + self._offset_x
            else:
                x + self._offset_x

        self._height = y + max_height + self._offset_y * 2
        self.emit('changed')

    def on_model_changed(self, event, **kwargs):
        self.model_dirty = True

    def _get_font_size(self):
        return self._model.size
    def _set_font_size(self, value):
        for child in self.children:
            child.fontsize = value
        self._model.load_font(self._model.resource, value)
    fontsize = property(_get_font_size, _set_font_size)

    def pre_render(self, surface):
        if self.model_dirty or self._size_dirty:
            self.init_words()
            self.model_dirty = False

    def views_for_word(self, word):
        return [child for child in self.children if child._model.text == word]

    def views_for_phrase(self, phrase):
        words = phrase.split()
        # TODO

    def _get_text(self):
        return self._model.text
    def _set_text(self, value):
        self._model.text = value
    text = property(_get_text, _set_text)


from rest_framework import permissions

from django.conf import settings
from django.contrib.auth import get_user_model

from .constants import DEFAULT_ROLE_RULE_DENIED_ACCESS_MESSAGE
from .helpers import is_user_permitted

class GroupPermission(permissions.BasePermission):
    """A Permission class, which checks the role authorization of a user."""

    message = 'Only this group is allowed'
    groups_required = None

    def has_permission(self, request, view):
        """Overriden method, which checks role authorization of the user.

        Args:
            request (Request): the current request object
            view (View): the current View object

        Returns:
            (bool): True if the user is granted access.
        """

        # allow all access if the user is a superuser
        is_permitted = False
        is_group_in_tree = False

        if request.user.is_superuser:
            return True

        # prepare the url name
        url_name = request.resolver_match.url_name

        # if the user is anonymous, try to fetch it from query parameters
        user_id = (request.GET.get('rbac_user')
                   if request.user.is_anonymous else None)
        if user_id:
            User = get_user_model()
            user = User.objects.get(id=user_id)
        else:
            user = request.user

        # for each group required, check if the current user is
        # senior / junior or equivalent to this required group within the
        # hierarchy
        for group_required in self.groups_required:
            # is_in_tree means that the user group / role is within the
            # required group / role tree (parent - child or equivalent)
            user_permitted, is_in_tree = is_user_permitted(
                user,
                group_required,
                url_name,
                request.method.lower()
            )
            is_permitted |= user_permitted
            is_group_in_tree |= is_in_tree

        if is_group_in_tree and not is_permitted:
            message = getattr(
                settings,
                'ROLE_RULE_DENIED_ACCESS_MESSAGE',
                DEFAULT_ROLE_RULE_DENIED_ACCESS_MESSAGE
            )
            self.message = message
        return is_permitted

# Mixins
class MultiplePermissionsMixin(object):
    """A mixin class which enables conditional permission checks."""

    def check_permissions(self, request):
        """Run has_permission for each permission class on the view."""
        exception_states = []
        permissions = self.get_permissions()

        all_groups = [group for permission in permissions
                      for group in permission.groups_required]

        for permission in permissions:
            if not permission.has_permission(request, self):
                permission_message_mappings = [
                    {
                        'role': role_name,
                        'message': permission.message
                    } for role_name in permission.groups_required
                ]
                exception_states.extend(permission_message_mappings)

        raise_permissions = len(exception_states) == len(all_groups)

        if raise_permissions:
            self.permission_denied(request, exception_states)


import pickle

import torch
import torch.nn as nn
import torchvision.transforms as T
import os

from PIL import Image

class Flatten(nn.Module):
    def forward(self, input):
        return input.view(input.size(0), -1)

class FruitClassifier(nn.Module):

    def __init__(self, classes):
        super(FruitClassifier, self).__init__()
        self.model = nn.Sequential(
            nn.Conv2d(3, 64, kernel_size=5, stride=1),
            nn.ReLU(),
            nn.MaxPool2d(2),
            nn.Conv2d(64, 64, kernel_size=7, stride=1),
            nn.ReLU(),
            nn.MaxPool2d(3),
            nn.Conv2d(64, 64, kernel_size=7),
            nn.ReLU(),
            nn.MaxPool2d(5),
            Flatten(),
            nn.Linear(64, 100),
            nn.ReLU(),
            nn.Linear(100, classes)
        )
        with open('id2class.pkl', 'rb') as fd:
            id2class = pickle.load(fd)
        self.id2class = id2class

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

    def load_weights(self, path):
        self.model.load_state_dict(torch.load(path))

    def predict(self, x):
        return self.id2class[self.model(x).max(1)[1].cpu().item()]

def load_image(filename, device='cpu'):
    transform = T.Compose([T.ToTensor(),
                           T.Normalize([0.5, 0.5, 0.5], [0.5, 0.5, 0.5])])
    img = Image.open(filename)
    img_t = transform(img)
    return img_t.unsqueeze(0).to(device)

def predictFolder(path):
    predictions = []
    clf = FruitClassifier(5)
    clf.load_weights('fruit_classifier.pth')
    for img_path in os.listdir(path):
        img = load_image(path+"/"+img_path)
        predictions.append(clf.predict(img))
    return predictions


import sqlite3
import numpy as np

'''Data Exercise 1, part  B- List Count of patients by gender'''
conn = None
cursor = None

try:
    conn = sqlite3.connect('openmrs.db')
    cursor = conn.cursor()
    cursor.execute('''
        SELECT gender, count(gender)
        FROM patient
        GROUP BY gender
    ''')
    data = (cursor.fetchall())

    for datum in data:
        gender = ''

        if datum[0].strip().lower() == 'm':
            gender = 'Male'
        elif datum[0].strip().lower() == 'f':
            gender = 'Female'
        else:
            gender = 'Unspecified'

        print(f'{gender}: {datum[1]}')

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


from math import pi
from random import uniform, randrange
randrange(0, 2)   # random integer (0 or 1)

def rect_circ(width, height):
    "Returns rectangle circumference."
    return 2 * (width + height)

def write_notification(rectangle_area):
    "Defines the size of your rectangle."

    print('Your new rectangle is:')
    if rectangle_area < area / 4:
        print('Tiny.')
    elif rectangle_area < area / 2:
        print('Very small.')
    elif rectangle_area < area:
        print('Smaller.')
    elif rectangle_area == area:
        print('Identical.')
    elif rectangle_area < 2 * area:
        print('Big.')
    else:
        print('Huge.')

def yes_or_no(random_num):
    "Schroedingers cat"
    while True:
        random_num = random_num
        if random_num == 1:
            return True
        else:
            return False

def ellipse_area(semi_major, semi_minor):
    "Calculates the area of the elipse fun(a,b)."
    return round(pi * semi_major * semi_minor, 4)

def cylinder_vol(semi_long, semi_short, height):
    "Calculates the volume of any cylinder"
    return round(ellipse_area(semi_major, semi_minor) * height, 4)

def get_input():
    while True:
        x = input('Choose any length in metres: ')
        try:
            return float(x)
        except ValueError:
            print('This is not a number! please, try again!')

x = get_input()
#  input as float in metres
#  variable = input('Choose any string: ') input as text
#  variable = int(input('Choose any number: ')) input as integer

while x <= 0:
    x = float(input('Choose any length in metres: '))
    if x == 0:
        print("""Zero!!! ...
...We can't make any calculation this time.""")
        print("Please, please try again :|.")
    else:
        print("""C'mon. The side length has to be positive,
otherwise the results make no sense.""")
        print("Please, make more effort :/.")

else:
    cf = 4*x
    area = x ** 2
    r = x / 2
    circ = 2 * pi * r
    circ_area = pi * r ** 2
    semi_major = r * uniform(0.001, 1.999)  # semi major axis
    a = 2 * semi_major
    semi_minor = r * uniform(0.001, 1.999)  # semi minor axis
    b = 2 * semi_minor
    height = x  # cylinder height
    rectangle_area = a * b
    rectangle_circumference = rect_circ(a, b)
    print("The circumference of the square with side",
          round(x, 2), "m is", round(cf, 2), "m.")
    print("The area of the same square with side", x, "is",
          round(area, 2), "m2.")
    print("The circumference of the circle within this square (radius: ",
          round(r, 2), "m) is", round(circ, 2), "m.")
    print("The area of the same circle with radius is",
          round(circ_area, 2), "m2.")
    print("\nRANDOM RECTANGLE:\nHeight: ", round(a, 2), "metres.\nWidth: ",
          round(b, 2), "metres.")
    print('The circumference of this rectangle is',
          round(rectangle_circumference, 2), 'metres.')
    print('It\'s area is', round(rectangle_area, 4), 'm2.')
    write_notification(rectangle_area)
    print('\nRANDOM ELLIPSE:\nArea of the ellipse within your new rectanle',
          ellipse_area(a / 2, b / 2), 'is m2')
    print('Volume of the cylinder with height', height, 'over ellipse is',
          cylinder_vol(a / 2, b / 2, x), 'is m3')
    print('Thank you for using the random geometric calculator.')

    print("""\nBONUS:\nThe Schrödinger's cat.\nOnce upon the time...
...there was an important quantum experiment.""")
    random_num = randrange(0, 2)
    if yes_or_no(random_num):
            print('\nDoc\'s cat made it "alive" this time.')
    else:
            print("""\nMeow...
Ups!!!
It looks like Doc's cat died before he could even start his experiment!!!""")


import random
import time
import webbrowser
import urllib

#Affichage
def  FT_Affichage_StandBY():
    print("Lance video")

def  FT_Affichage_Jeu():
    print("Lance Affichage de la salle de jeu")

def  FT_Affichage_Bonus():
    print("Lance affichage BONUS")

def  FT_Affichage_Tilt():
    print("Lance affichage Tilt")

#TOOL Rasberry
def  Ft_Fermeture_trappe():
    print("Fermeture Trappe")
def Ft_Ouverture_Trappe():
    print("Ouverture Trappe")

def FT_capteur_jetons():
    print("tu captes")

def FT_Distributeur_Points():
    print("Tiens bro un point")

def FT_Distributeur_Jetons(gain):
    tour=0
    while tour < gain:
        print("Glin")
        tour+=1

#TOOL

def Ft_Detection(capte_jetons):
    FT_capteur_jetons()
    capte_jetons=int(input("Insere un jetons\n"))
    capte_jetons=int(capte_jetons)
    return capte_jetons

def Ft_Sleep_Timer(timer):
    time.sleep(0.3)
    timer+=1
    if timer==6000:
        timer="sleep"
        print("Sleep too much and i Stand by ")
    return timer

def FT_Trappe(mode_jeu):

    if mode_jeu==1 or mode_jeu==4:
        Ft_Fermeture_trappe()
    if mode==2:
        Ft_Ouverture_Trappe()

def FT_Affichage(mode_jeu):

    if mode_jeu==1:
        print("Je suis jolie ! Viens jouer avec moi")
        FT_Affichage_StandBY()
    if mode_jeu==2:
        print("C'est bien joue ")
        FT_Affichage_Jeu()
    if mode_jeu==3:
        print("Je fais de toi un heureux gagnant")
        FT_Affichage_Bonus()
    if mode_jeu==4:
        print("T'es vraiment une pute!")
        FT_Affichage_Tilt()

def FT_Led_carousel(mode_jeu):

    if mode_jeu==1:
        print("Je suis jolie ! Viens jouer avec moi")
    if mode_jeu==2:
        print("C'est bien joue ")
    if mode_jeu==3:
        print("Je fais de toi un heureux gagnant")
    if mode==4:
        print("T'es vraiment une pute!")

def Ft_Son(mode_jeu):

    if mode_jeu==0:
        print("Bim bim ")
    if mode_jeu==3:
        print("Trin trin trin trin")
    if mode_jeu==4:
        print("ahahahahha Vous etes un connard!")

def FT_Tilt(mode_jeu):
    #Check tilt
    Tilt=0
    if Tilt==1:
        mode_jeu =4
    return mode_jeu

#Write txt > SQL
def Ft_New_Player(mode_player):
    prochaincode="0"
    with open ("Banque/nombre_joueur.txt","a")as nombre_joueur:
        nombre_joueur.write("")
    with open ("Banque/nombre_joueur.txt","r")as nombre_joueur:
        for i in nombre_joueur:
            mode_player=i.rstrip('\n')
            print("Vous etes le joueur {}".format(mode_player))
            mode_player=int(mode_player)
            prochaincode=mode_player+1
            prochaincode=str(prochaincode)
    with open ("Banque/nombre_joueur.txt","w")as nombre_joueur:
        nombre_joueur.write(prochaincode)
    return mode_player

def FT_Base_StandBy():
    print("Int game")
    with open ("Banque/nb_bonus1.txt","w")as nb_bonus1_txt:
        nb_bonus1_txt.write("0")

        with open ("Banque/nb_bonus2.txt","w")as nb_bonus2_txt:
            nb_bonus2_txt.write("0")

            with open ("Banque/nb_bonus3.txt","w")as nb_bonus3_txt:
                nb_bonus3_txt.write("0")
                with open ("Banque/nombre_joueur.txt","w")as nombre_joueur:
                    nombre_joueur.write("1")
                    with open ("Banque/active_bonus.txt","w")as active_bonus:
                        active_bonus.write("0")

def FT_Set_Niveau_Bonus(liste_niveau_jetons):
#Bonus 1 curseur
    with open ("Banque/nb_bonus1.txt","r")as nb_bonus1_txt:
        for i in nb_bonus1_txt:
            niveau_jetons1=i.rstrip('\n')
            niveau_jetons1=int(niveau_jetons1)
            niveau_jetons1=niveau_jetons1+1
            niveau_jetons1=str(niveau_jetons1)
    with open ("Banque/nb_bonus1.txt","w")as nb_bonus1_txt:
        nb_bonus1_txt.write(niveau_jetons1)
        niveau_jetons1=int(niveau_jetons1)
#Bonus 2 curseur
    with open ("Banque/nb_bonus2.txt","r")as nb_bonus2_txt:
        for i in nb_bonus2_txt:
            niveau_jetons2=i.rstrip('\n')
            niveau_jetons2=int(niveau_jetons2)
            niveau_jetons2=niveau_jetons2+1
            niveau_jetons2=str(niveau_jetons2)
    with open ("Banque/nb_bonus2.txt","w")as nb_bonus2_txt:
        nb_bonus2_txt.write(niveau_jetons2)
        niveau_jetons2=int(niveau_jetons2)
#Bonus 3 curseur
    with open ("Banque/nb_bonus3.txt","r")as nb_bonus3_txt:
        for i in nb_bonus3_txt:
            niveau_jetons3=i.rstrip('\n')
            niveau_jetons3=int(niveau_jetons3)
            niveau_jetons3=niveau_jetons3+1
            niveau_jetons3=str(niveau_jetons3)
    with open ("Banque/nb_bonus3.txt","w")as nb_bonus3_txt:
        nb_bonus3_txt.write(niveau_jetons3)
        niveau_jetons3=int(niveau_jetons3)
    liste_niveau_jetons.append(niveau_jetons1)
    liste_niveau_jetons.append(niveau_jetons2)
    liste_niveau_jetons.append(niveau_jetons3)
    return liste_niveau_jetons

def Ft_Active_Bonus(active_bonus):
    with open ("Banque/active_bonus.txt","w")as active_bonus_txt:
        active_bonus_txt.write("{}\n".format(active_bonus))

def Ft_Need_Jetons_Bonus(liste_jetons_bonus):
#Int game
    #Je veux connnaitre le nombre de jetons requis pour gagner chaque bonus
    #Ici le Bonus 1
    tour=0
    with open ("Banque/bonus_1.txt","r")as bonus_1_txt:
      for i in bonus_1_txt:
            if tour==0:
                jetons_bonus1=i.rstrip('\n')
                jetons_bonus1=int(jetons_bonus1)
            else:
                if "POINTS" in i:
                    jetons_bonus_gain1=1
                else:
                    jetons_bonus_gain1=i.rstrip('\n')
                    jetons_bonus_gain1=int(jetons_bonus_gain1)
            tour+=1
    tour=0
    #Ici le Bonus 2
    with open ("Banque/bonus_2.txt","r")as bonus_2_txt:
      for i in bonus_2_txt:
            if tour==0:
                jetons_bonus2=i.rstrip('\n')
                jetons_bonus2=int(jetons_bonus2)
            else:
                if "POINTS" in i:
                    jetons_bonus_gain2=1
                else:
                    jetons_bonus_gain2=i.rstrip('\n')
                    jetons_bonus_gain2=int(jetons_bonus_gain1)
            tour+=1
    tour=0
    #Ici le Bonus 3
    with open ("Banque/bonus_3.txt","r")as bonus_3_txt:
      for i in bonus_3_txt:
        if tour==0:
            jetons_bonus3=i.rstrip('\n')
            jetons_bonus3=int(jetons_bonus3)
        else:
            if "POINTS" in i:
                jetons_bonus_gain3=1
            else:
                jetons_bonus_gain3=i.rstrip('\n')
                jetons_bonus_gain3=int(jetons_bonus_gain1)
        tour+=1
    tour=0
    print(jetons_bonus1,jetons_bonus2,jetons_bonus3)
    liste_jetons_bonus.append(jetons_bonus1)
    liste_jetons_bonus.append(jetons_bonus2)
    liste_jetons_bonus.append(jetons_bonus3)
    liste_jetons_bonus.append(jetons_bonus_gain1)
    liste_jetons_bonus.append(jetons_bonus_gain2)
    liste_jetons_bonus.append(jetons_bonus_gain3)
    return liste_jetons_bonus

#Mode 3 Bonus

def FT_Bonus(mode_jeu,mode_player):
    print("Bonus")
    active_bonus=1
    print("\nBONUS\n")
    liste_jetons_bonus=[]
    with open ("Banque/active_bonus.txt","w")as active_bonus_txt:
        active_bonus_txt.write("{}\n".format(active_bonus))
        active_bonus=0
    liste_jetons_bonus=Ft_Need_Jetons_Bonus(liste_jetons_bonus)
    gain=liste_jetons_bonus[mode_jeu]
    if gain>1:
        print("Gagne {} Jetons".format(gain))
        FT_Distributeur_Jetons(gain)
    else:
        FT_Distributeur_Points()
        print("Gagne 1 points")
    active_bonus=0
    with open ("Banque/active_bonus.txt","w")as active_bonus_txt:
        active_bonus_txt.write("{}\n".format(active_bonus))

    mode_jeu=2
    return mode_jeu + mode_player

#Mode 2 Play
def FT_Play(mode_jeu,mode_player,timer):
    print("PLAY {}".format(mode_player))
    active_bonus=0
    capte_jetons=0
    liste_niveau_jetons=[]
    liste_jetons_bonus=[]
    capte_jetons=Ft_Detection(capte_jetons)
    if capte_jetons==1:
        #Relance timer =0
        timer=0
        #Recup les stats jetons_bonus !
        print("detecte niveau jetons")
        liste_jetons_bonus=Ft_Need_Jetons_Bonus(liste_jetons_bonus)
        print(liste_jetons_bonus)
        #Remet a niveau l'affichage bonus
        liste_niveau_jetons=FT_Set_Niveau_Bonus(liste_niveau_jetons)
        #Check si un bonus est accomplie
        with open ("Banque/active_bonus.txt","r")as active_bonus_txt:
            for i in active_bonus_txt:
                active_bonus=i.rstrip('\n')
                active_bonus=int(active_bonus)
        if liste_niveau_jetons[0] >= liste_jetons_bonus[0] and active_bonus==0:
            mode_jeu=3
        if liste_niveau_jetons[1] >= liste_jetons_bonus[1] and active_bonus==0:
            mode_jeu=4
        if liste_niveau_jetons[2] >= liste_jetons_bonus[2] and active_bonus==0:
            mode_jeu=5
        capte_jetons = 0
        active_bonus=0
    else:
        timer=Ft_Sleep_Timer(timer)
        if timer=="sleep":
            mode_jeu=1
    return mode_jeu + mode_player + timer

#Mode 1
def FT_StandBY(mode_jeu,mode_player):
    print("Stand BY")
    FT_Base_StandBy()
    capte_jetons=0
    capte_jetons = Ft_Detection(capte_jetons)
    mode_player=0
    if capte_jetons==1:
        #Lance un joueur( lance une boucle de partie)
        Ft_New_Player(mode_player)
        mode_jeu=2
        #Mode jeu
        print('New player !! ')
        print(mode_player)
    return mode_jeu + mode_player

#Moi je renvoie le mode de jeu, mode = 0  Stand fro play, mode = 1 Play ! , mode = 2 BONUS , mode = 3 Il TILT ce CLIENT
def FT_Tool(mode_jeu):
    #Sans moi le joueur ne gagnera jamais de jetons!
    FT_Trappe(mode_jeu)
    #C'est ici que QT Python affiche TV
    FT_Affichage(mode_jeu)
    #Je scintille
    FT_Led_carousel(mode_jeu)
    #J'ambiance
    Ft_Son(mode_jeu)
    #Je je maintiens l'ordre
    FT_Tilt(mode_jeu)
    return mode_jeu

#Je suis simplement l'instance de jeu
def FT_Start():
    mode_jeu=1
    mode_player=0
    power=1
    timer=0
    while power==1:
        print("Start")
        print(mode_jeu)
        #En realite je controle la machine je fais juste en fonction des modes!
        FT_Tool(mode_jeu)
        if mode_jeu==1:
            #Moi je ne sers a rien ! j'attend juste un joueur et je matte des videos
            mode_jeu=FT_StandBY(mode_jeu,mode_player)
        elif mode_jeu==2:
            #Je compte juste les jetons ! Et j'appuie sur le Bonus quand c'est le moment !
            mode_jeu=FT_Play(mode_jeu,mode_player,timer)
        else:
            #Tout le programme n'existe rien que pour moi! JE distribue la bonne valeur au bon client !
            mode_jeu=FT_Bonus(mode_jeu,mode_player)

#Dev part
def DEV_Bonus():
    programme=1
    while programme==1:
        print("\n\n---Sélection:\nMode=1: Bonus 1\nMode=2: Bonus 2\nMode=3: Bonus 3\nMode = 4 quitte ou double\nMode =5 quitte le programme")
        mode=int(input("Choisi ton mode"))
        if mode==1:
            choix=int(input("Jetons=1 ou points=2 ou les deux=3"))
            nb_jetons=int(input("Combien de jetons pour gagner bonus?"))
            with open ("Banque/bonus_1.txt","w")as bonus_1_txt:
                if choix==1:
                    nb_jetons_gain=int(input("Combien de jetons gagner avec bonus?"))
                    bonus_1_txt.write("{}\n{}\n".format(nb_jetons,nb_jetons_gain))
                elif choix==2:
                    bonus_1_txt.write("{}\nPOINTS\n".format(nb_jetons))
                else:
                    nb_jetons_gain=int(input("Combien de jetons gagner avec bonus?"))
                    bonus_1_txt.write("{}\nPOINTS\n{}\n".format(nb_jetons,nb_jetons_gain))
        if mode==2:
            choix=int(input("Jetons=1 ou points=2 ou les deux=3"))
            nb_jetons=int(input("Combien de jetons pour gagner bonus?"))
            with open ("Banque/bonus_2.txt","w")as bonus_2_txt:
                if choix==1:
                    nb_jetons_gain=int(input("Combien de jetons gagner avec bonus?"))
                    bonus_2_txt.write("{}\n{}\n".format(nb_jetons,nb_jetons_gain))
                elif choix==2:
                    bonus_2_txt.write("{}\nPOINTS\n".format(nb_jetons))
                else:
                    nb_jetons_gain=int(input("Combien de jetons gagner avec bonus?"))
                    bonus_2_txt.write("{}\nPOINTS\n{}\n".format(nb_jetons,nb_jetons_gain))
        if mode==3:
            choix=int(input("Jetons=1 ou points=2 ou les deux=3"))
            nb_jetons=int(input("Combien de jetons pour gagner bonus?"))
            with open ("Banque/bonus_3.txt","w")as bonus_3_txt:
                if choix==1:
                    nb_jetons_gain=int(input("Combien de jetons gagner avec bonus?"))
                    bonus_3_txt.write("{}\n{}\n".format(nb_jetons,nb_jetons_gain))
                elif choix==2:
                    bonus_3_txt.write("{}\nPOINTS\n".format(nb_jetons))
                else:
                    nb_jetons_gain=int(input("Combien de jetons gagner avec bonus?"))
                    bonus_3_txt.write("{}\nPOINTS\n{}\n".format(nb_jetons,nb_jetons_gain))
        if mode==4:
            choix=0
            with open ("Banque/quitte_ou_double.txt","w")as quitte_ou_double_txt:
                while choix<4:
                    choix=int(input("Numero du bonus\n qui possede le mode quitte ou double, 4= quitter"))
                    quitte_ou_double_txt.write("{}\n".format(choix))
        elif mode==5:
          print("Quitte le programme")
          programme=0

def ft_lancementdev():
    print("lance Dev")
    programme=1
    while programme==1:
        print("\n\n---Sélection:\nMode=1: Dev Bonus\nMode = 2 quitte le programme")
        mode=int(input("Choisi ton mode"))
        if mode==1:
            DEV_Bonus()
        elif mode==2:
          print("Quitte le programme")
          programme=0

#Main menu
programme=1
while programme==1:
    print("\n\n---Sélection:\nMode=1: jeu\n Mode=2: Dev\n Mode=3 quitte le programme")
    mode=int(input("Choisi ton mode"))
    if mode==1:
        FT_Start()#ici que l'on lance la machine, pour qu'elle traduise
    elif mode==2:
        ft_lancementdev()#ici Que l'on lancement le mode devellopment
    elif mode==3:
      print("Quitte le programme")
      programme=0

Machine a jeu 6 joueur/code_source/debug1.py


from urllib.error import HTTPError
import rich
import json
import requests
import sys, os
import time
from dotenv import load_dotenv
from rich.console import Console
from rich.traceback import install
from rich.markdown import Markdown
import lang_supported
import tts_voice  # file module

load_dotenv()  # loads API TOKEN
install()  # traceback for error prompts
console = Console()  # rich console for styling

# get the .env variables
API_TOKEN = os.getenv('API_TOKEN')

# api calling
def api_call(text_converting, to_language):
    url_detect = "https://google-translate78.p.rapidapi.com/language_detect"
    url_translate = "https://google-translate78.p.rapidapi.com/translate"

    payload_detect = {"text": text_converting}

    headers = {
        "content-type": "application/json",
        "X-RapidAPI-Key": API_TOKEN,
        "X-RapidAPI-Host": "google-translate78.p.rapidapi.com"
    }

    response_detect = requests.request(
        "POST", url_detect, json=payload_detect, headers=headers)
    source_language = response_detect.json()["language_detection"]["language"]

    payload_translate = {
        "text": text_converting,
        "source": source_language,
        "target": to_language
    }

    response_translate = requests.request(
        "POST", url_translate, json=payload_translate, headers=headers)
    return response_translate.json()["translations"]["translation"]

# count letters in a string to check if the language is valid
def count_letters(word):
    return len([x for x in word if x.isalpha()])

# ----------------------------- MARKDOWN -------------------------------- #

MARKDOWN = """
# Translator v1.0

This is a simple translator that uses the Google Translate API to translate text from one language to another.

## Usage
1. Enter the text you want to translate.
2. Enter the language you want to translate to.
3. The translated text will be displayed.
##
"""
md = Markdown(MARKDOWN)
console.print(md)

# ----------------------------- main ----------------------------- #

if __name__ == '__main__':

    choice = console.input(
        '[bold yellow]Would you like to see the languages?[/bold yellow] [bold purple](y/n)\n[/bold purple]')
    if choice == 'y' or choice == 'Y':
        lang_supported.langs()

    # variables input
    text_converting = console.input(
        "\n[bold yellow]Enter the text you want to convert: ")
    to_language = console.input(
        "\n[bold yellow]Enter the language you want to convert to: ")

    # check if the language is valid (language cannot have more than 2 chars)
    while ((count_letters(to_language) > 2) or (to_language.isnumeric())):
        console.print(
            "\n[red blink]Invalid language[/red blink], [cyan]use the format [purple]'en'[/purple] for English[/cyan]")
        to_language = console.input(
            "\n[bold yellow]Enter the language you want to convert to: ")

    # output
    try:
        translated_text = api_call(text_converting, to_language)
    except HTTPError as e:
        console.print(f'[red]The following error occured:[/red] [bold red]{e}')
    except Exception as e:
        console.print(f'[bold red]{e}')
    else:
        console.print(
            f'\n[green]The translated text is: [/green][purple]{translated_text}[/purple]')

    # Hear the translation
    hear_choice = console.input(
        "\n[bold yellow]Do you want to hear the translation?[/bold yellow] [purple](y/n)\n[/purple]")
    if hear_choice == 'y' or hear_choice == 'Y':
        try:
            tts_voice.speak(translated_text, to_language)
        except Exception as e:
            console.print(f'[bold red]{e}')
        else:
            sys.exit()
# ----------------------------------------------------------------- #


import time

import attr
from taretto.navigate import NavigateToAttribute
from taretto.navigate import NavigateToSibling
from wait_for import wait_for
from widgetastic.utils import ParametrizedLocator
from widgetastic.utils import WaitFillViewStrategy
from widgetastic.widget import ParametrizedView
from widgetastic.widget import Text
from widgetastic.widget import View
from widgetastic_patternfly4 import Button

from mta.base.application.implementations.web_ui import MTANavigateStep
from mta.base.application.implementations.web_ui import navigate_to
from mta.base.application.implementations.web_ui import ViaWebUI
from mta.base.modeling import BaseCollection
from mta.base.modeling import BaseEntity
from mta.entities import AllProjectView
from mta.entities.analysis_results import AnalysisResultsView
from mta.utils import conf
from mta.utils.ftp import FTPClientWrapper
from mta.utils.update import Updateable
from mta.widgetastic import HiddenFileInput
from mta.widgetastic import Input
from mta.widgetastic import MTASelect
from mta.widgetastic import TransformationPath

class AddProjectView(AllProjectView):
    fill_strategy = WaitFillViewStrategy("15s")
    title = Text(locator=".//h1[normalize-space(.)='Create project']")

    @property
    def is_displayed(self):
        return self.title.is_displayed and self.create_project.is_displayed

    @View.nested
    class create_project(View):  # noqa
        title = Text(locator=".//h5[normalize-space(.)='Project details']")
        name = Input(name="name")
        description = Input(locator='.//textarea[@name="description"]')
        next_button = Button("Next")
        cancel_button = Button("Cancel")
        yes_button = Button("Yes")
        no_button = Button("No")
        fill_strategy = WaitFillViewStrategy("30s")

        @property
        def is_displayed(self):
            return self.name.is_displayed and self.title.is_displayed

        def after_fill(self, was_change):
            self.next_button.click()

    @View.nested
    class add_applications(View):  # noqa
        title = Text(locator=".//h5[normalize-space(.)='Add applications']")
        delete_application = Text(locator=".//button[contains(@aria-label, 'delete-application')]")
        browse_button = Button("Browse")
        progress_bar = './/div[contains(@role, "progressbar")]'
        upload_file = HiddenFileInput(
            locator='.//input[@accept=".ear, .har, .jar, .rar, .sar, .war, .zip"]'
        )

        next_button = Button("Next")
        back_button = Button("Back")
        cancel_button = Button("Cancel")
        fill_strategy = WaitFillViewStrategy("20s")

        @property
        def is_displayed(self):
            return self.title.is_displayed and self.browse_button.is_displayed

        def in_progress(self):
            return self.browser.is_displayed(self.progress_bar)

        def fill(self, values):
            app_list = values.get("app_list")
            env = conf.get_config("env")
            fs = FTPClientWrapper(env.ftpserver.entities.mta)
            for app in app_list:
                # Download application file to analyze
                # This part has to be here as file is downloaded temporarily
                file_path = fs.download(app)
                self.upload_file.fill(file_path)
            wait_for(lambda: self.next_button.is_enabled, delay=0.2, timeout=60)
            was_change = True
            self.after_fill(was_change)
            return was_change

        def after_fill(self, was_change):
            self.next_button.click()

    class configure_analysis(View):  # noqa
        @View.nested
        class set_transformation_target(View):  # noqa
            title = Text(locator=".//h5[normalize-space(.)='Select transformation target']")
            transformation_path = TransformationPath()
            application_packages = Text(
                locator=".//wu-select-packages/h3[normalize-space(.)='Application packages']"
            )
            next_button = Button("Next")
            back_button = Button("Back")
            cancel_button = Button("Cancel")
            fill_strategy = WaitFillViewStrategy("15s")

            @property
            def is_displayed(self):
                return self.title.is_displayed and self.transformation_path.is_displayed

            def fill(self, values):
                """
                Args:
                    values: transformation path to be selected
                """
                if values.get("transformation_path"):
                    self.transformation_path.select_card(
                        card_name=values.get("transformation_path")
                    )
                was_change = True
                wait_for(lambda: self.next_button.is_enabled, delay=0.2, timeout=60)
                self.after_fill(was_change)
                return was_change

            def after_fill(self, was_change):
                self.next_button.click()

        @ParametrizedView.nested
        class select_packages(ParametrizedView):  # noqa
            title = Text(locator=".//h5[normalize-space(.)='Select packages']")
            PARAMETERS = ("pkg",)
            select_all_packages = Text(locator=".//input[@class='ant-checkbox-input']")

            packages = Text(
                ParametrizedLocator(
                    ".//div[contains(@class, 'ant-tree-treenode-switcher-close') "
                    "and not(contains(@class, 'ant-tree-treenode-disabled'))]"
                    "/span/span/span[normalize-space(.)={pkg|quote}]"
                )
            )
            included_packages = Text(
                ParametrizedLocator(
                    ".//li[@class='ant-transfer-list-content-item']"
                    "/span[normalize-space(.)={pkg|quote}]"
                )
            )
            move_into_button = Button(locator=".//span[contains(@class, 'anticon anticon-right')]")
            move_from_button = Button(locator=".//span[contains(@class, 'anticon anticon-left')]")

            next_button = Button("Next")
            back_button = Button("Back")
            cancel_button = Button("Cancel")
            fill_strategy = WaitFillViewStrategy("15s")

            @property
            def is_displayed(self):
                return self.title.is_displayed and self.select_all_packages.is_displayed

            def fill_pkg(self):
                """Add packages"""
                self.packages.click()
                self.move_into_button.click()
                was_change = True
                return was_change

            def remove(self):
                """Remove packages"""
                self.included_packages.click()
                self.move_from_button.click()
                was_change = True
                return was_change

            def fill(self, values):
                """
                Args:
                    values: application packages to be selected
                """
                if values.get("pkg"):
                    self.fill_pkg()
                was_change = True
                self.after_fill(was_change)
                return was_change

            def after_fill(self, was_change):
                self.next_button.click()

    class advanced(View):  # noqa
        @View.nested
        class custom_rules(View):  # noqa
            title = Text(locator=".//h5[normalize-space(.)='Custom rules']")
            add_rule_button = Button("Add rule")
            upload_rule = HiddenFileInput(locator='.//input[contains(@accept,".xml")]')
            close_button = Button("Close")
            enabled_button = Text(locator=".//label/span[contains(@class, 'pf-c-switch__toggle')]")
            next_button = Button("Next")
            back_button = Button("Back")
            cancel_button = Button("Cancel")
            fill_strategy = WaitFillViewStrategy("15s")

            @property
            def is_displayed(self):
                return self.title.is_displayed and self.add_rule_button.is_displayed

            def fill(self, values):
                """
                Args:
                    values: custom rule file to be uploaded
                """
                if values.get("file_rule"):
                    self.expand_custom_rules.click()
                was_change = True
                wait_for(lambda: self.next_button.is_enabled, delay=0.2, timeout=60)
                self.after_fill(was_change)
                return was_change

            def after_fill(self, was_change):
                self.next_button.click()

        @View.nested
        class custom_labels(View):  # noqa
            title = Text(locator=".//h5[normalize-space(.)='Custom labels']")
            add_label_button = Button("Add label")
            upload_label = HiddenFileInput(locator='.//input[contains(@accept,".xml")]')
            enabled_button = Text(locator=".//label/span[contains(@class, 'pf-c-switch__toggle')]")
            close_button = Button("Close")
            next_button = Button("Next")
            back_button = Button("Back")
            cancel_button = Button("Cancel")
            fill_strategy = WaitFillViewStrategy("15s")

            @property
            def is_displayed(self):
                return self.title.is_displayed and self.add_label_button.is_displayed

            def fill(self, values):
                """
                Args:
                    values: custom label file to be uploaded
                """
                if values.get("file_label"):
                    self.expand_custom_labels.click()
                wait_for(lambda: self.next_button.is_enabled, delay=0.2, timeout=60)
                was_change = True
                self.after_fill(was_change)
                return was_change

            def after_fill(self, was_change):
                self.next_button.click()

        @View.nested
        class options(View):  # noqa
            title = Text(locator=".//h5[normalize-space(.)='Advanced options']")
            app_name = Input(name="inputApplicationName")
            select_target = MTASelect(
                locator='.//div/input[contains(@placeholder, "Select targets")]'
                '/ancestor::div[contains(@class, "pf-c-select")]'
            )
            select_source = MTASelect(
                locator='.//div/input[contains(@placeholder, "Select sources")]'
                '/ancestor::div[contains(@class, "pf-c-select")]'
            )

            export_csv = Text(
                locator=".//span[./preceding-sibling::input[@aria-label='Export CSV']]"
            )
            disable_tattletale = Text(
                locator=".//span[./preceding-sibling::input[@aria-label='Disable Tattletale']]"
            )
            class_not_found_analysis = Text(
                locator=".//span[./preceding-sibling::input"
                "[@aria-label='Class Not Found analysis']]"
            )
            compatible_files_report = Text(
                locator=".//span[./preceding-sibling::input"
                "[@aria-label='Compatible Files report']]"
            )
            exploded_app = Text(
                locator=".//span[./preceding-sibling::input[@aria-label='Exploded app']]"
            )
            keep_work_dirs = Text(
                locator=".//span[./preceding-sibling::input[@aria-label='Keep work dirs']]"
            )
            skip_reports = Text(
                locator=".//span[./preceding-sibling::input[@aria-label='Skip reports']]"
            )
            allow_network_access = Text(
                locator=".//span[./preceding-sibling::input[@aria-label='Allow network access']]"
            )
            mavenize = Text(locator=".//span[./preceding-sibling::input[@aria-label='Mavenize']]")
            source_mode = Text(
                locator=".//span[./preceding-sibling::input[@aria-label='Source mode']]"
            )

            add_button = Button("Add")
            cancel_button = Button("Cancel")
            next_button = Button("Next")
            back_button = Button("Back")
            fill_strategy = WaitFillViewStrategy("25s")

            @property
            def is_displayed(self):
                return self.title.is_displayed and self.select_target.is_displayed

            def after_fill(self, was_change):
                wait_for(lambda: self.next_button.is_enabled, delay=5, timeout=350)
                self.next_button.click()

    @View.nested
    class review(View):  # noqa
        title = Text(locator=".//h5[normalize-space(.)='Review project details']")
        save = Button("Save")
        save_and_run = Button("Save and run")
        fill_strategy = WaitFillViewStrategy("15s")

        @property
        def is_displayed(self):
            return self.title.is_displayed and self.save_and_run.is_displayed

        def after_fill(self, was_change):
            wait_for(lambda: self.save_and_run.is_enabled, delay=5, timeout=150)
            self.save_and_run.click()

class DetailsProjectView(AllProjectView):
    run_analysis_button = Button("Run Analysis")
    title = Text(locator=".//div/h2[normalize-space(.)='Active Analysis']")

    @property
    def is_displayed(self):
        return self.run_analysis_button.is_displayed and self.title.is_displayed

class EditProjectView(AllProjectView):
    title = Text(locator=".//h1[normalize-space(.)='Project details']")
    name = Input(name="name")
    description = Input(name="description")
    save_button = Button("Save")
    cancel_button = Button("Cancel")
    fill_strategy = WaitFillViewStrategy("35s")

    @property
    def is_displayed(self):
        return self.save_button.is_displayed and self.title.is_displayed

class DeleteProjectView(AllProjectView):
    title = Text(locator=".//h1[normalize-space(.)='Project details']")
    delete_project_name = Input(id="matchText")
    fill_strategy = WaitFillViewStrategy("35s")

    delete_button = Button("Delete")
    cancel_button = Button("Cancel")

    @property
    def is_displayed(self):
        return self.delete_button.is_displayed and self.title.is_displayed

@attr.s
class Project(BaseEntity, Updateable):

    name = attr.ib()
    description = attr.ib(default=None)
    app_list = attr.ib(default=None)
    transformation_path = attr.ib(default=None)

    @property
    def exists(self):
        """Check project exist or not"""
        view = navigate_to(self.parent, "All")
        time.sleep(10)
        if view.table_loaded():
            for row in view.table:
                if row.name.text == self.name:
                    return True
        return False

    def update(self, updates):
        view = navigate_to(self, "Edit")
        view.wait_displayed("30s")
        changed = view.fill(updates)
        if changed:
            view.save_button.click()
        else:
            view.cancel_button.click()
        view = self.create_view(AllProjectView, override=updates)
        view.wait_displayed()
        assert view.is_displayed

    def delete(self, cancel=False, wait=False):
        """
        Args:
            cancel: cancel deletion
            wait: wait for delete
        """
        view = navigate_to(self, "Delete")
        view.wait_displayed("30s")
        view.fill({"delete_project_name": self.name})
        if cancel:
            view.cancel_button.click()
        else:
            wait_for(lambda: view.delete_button.is_enabled, delay=5, timeout=30)
            view.delete_button.click()
            if wait:
                wait_for(lambda: not self.exists, delay=5, timeout=30)

    def delete_if_exists(self):
        """Check project exist and delete"""
        if self.exists:
            self.delete()

@attr.s
class ProjectCollection(BaseCollection):

    ENTITY = Project

    def all(self):
        """Return all projects instance of Project class"""
        view = navigate_to(self, "All")
        if view.is_empty:
            return []
        else:
            return [
                self.instantiate(name=p.name.text, description=p.description.text)
                for p in view.all_projects
            ]

    def create(
        self,
        name,
        description=None,
        app_list=None,
        transformation_path=None,
        pkg=None,
        file_rule=None,
        file_label=None,
        options=None,
    ):
        """Create a new project.

        Args:
            name: The name of the project
            description: The description of the project
            app_list: Applications to be analyzed
            transformation_path: transformation_path
            pkg: package
            file_rule: Rules
            file_label: Label
            options: Options
        """
        view = navigate_to(self, "Add")
        view.create_project.fill({"name": name, "description": description})
        view.add_applications.wait_displayed()
        view.add_applications.fill({"app_list": app_list})
        view.configure_analysis.set_transformation_target.wait_displayed()
        view.configure_analysis.set_transformation_target.fill(
            {"transformation_path": transformation_path}
        )
        wait_for(
            lambda: view.configure_analysis.select_packages(pkg).is_displayed, delay=10, timeout=600
        )
        view.configure_analysis.select_packages(pkg).wait_displayed()
        view.configure_analysis.select_packages(pkg).fill({"pkg": pkg})
        view.advanced.custom_rules.wait_displayed()
        view.advanced.custom_rules.fill({"file_rule": file_rule})
        view.advanced.custom_labels.wait_displayed()
        view.advanced.custom_labels.fill({"file_label": file_label})
        view.advanced.options.wait_displayed("20s")
        view.advanced.options.fill({"options": options})
        view.review.wait_displayed("30s")
        view.review.after_fill(was_change=True)

        project = self.instantiate(
            name=name,
            description=description,
            app_list=app_list,
            transformation_path=transformation_path,
        )
        view = self.create_view(AnalysisResultsView)
        view.wait_displayed("60s")
        assert view.is_displayed
        wait_for(lambda: view.analysis_results.in_progress(), delay=0.2, timeout=450)
        wait_for(lambda: view.analysis_results.is_analysis_complete(), delay=0.2, timeout=450)
        assert view.analysis_results.is_analysis_complete()
        return project

    def sort_projects(self, criteria, order):
        view = navigate_to(self, "All")
        view.table.sort_by(criteria, order)

    def search_project(self, project):
        view = navigate_to(self, "All")
        view.search.fill(project)

    def get_project(self, name):
        view = navigate_to(self, "All")
        for row in view.table:
            if row.name.text == name:
                return row

@ViaWebUI.register_destination_for(ProjectCollection)
class All(MTANavigateStep):
    VIEW = AllProjectView
    prerequisite = NavigateToAttribute("application.collections.base", "LoggedIn")

    def step(self, *args, **kwargs):
        self.prerequisite_view.wait_displayed("20s")
        if not self.prerequisite_view.is_empty:
            self.prerequisite_view.navigation.select("Projects")

@ViaWebUI.register_destination_for(ProjectCollection)
class Add(MTANavigateStep):
    VIEW = AddProjectView
    prerequisite = NavigateToSibling("All")

    def step(self, *args, **kwargs):
        self.prerequisite_view.wait_displayed("20s")
        if self.prerequisite_view.is_empty:
            self.prerequisite_view.blank_state.create_project.click()
        else:
            self.prerequisite_view.create_project.click()

@ViaWebUI.register_destination_for(Project)
class Edit(MTANavigateStep):
    VIEW = EditProjectView
    prerequisite = NavigateToAttribute("parent", "All")

    def step(self, *args, **kwargs):
        for row in self.prerequisite_view.table:
            if row.name.text == self.obj.name:
                row[self.prerequisite_view.ACTIONS_INDEX].widget.item_select("Edit")

@ViaWebUI.register_destination_for(Project)
class Delete(MTANavigateStep):
    VIEW = DeleteProjectView
    prerequisite = NavigateToAttribute("parent", "All")

    def step(self, *args, **kwargs):
        for row in self.prerequisite_view.table:
            if row.name.text == self.obj.name:
                row[self.prerequisite_view.ACTIONS_INDEX].widget.item_select("Delete")