# coding: utf-8

# In[132]:

### changes NOT only appended, within previous work as well ###

# # Thyroid dataset

# Disclaimer: some decisions in this notebook were made just to enhance data handling and may be not optimal, considering both time complexity and memory requirements

# In[133]:

import pandas as pd
import numpy as np
from sklearn.linear_model import LinearRegression
from sklearn.preprocessing import Imputer, LabelEncoder
from sklearn.neighbors import NearestNeighbors
from sklearn.tree import DecisionTreeClassifier
from sklearn.model_selection import cross_val_score
import sklearn.metrics as metrics
import scipy.stats as stats
import matplotlib.pyplot as plt
import seaborn as sns

# In[134]:

import sys
from IPython.display import display
import itertools

# Prepare script execution for test set

# In[135]:

file_name_base = 'train' # default
MODE_SCRIPT = len(sys.argv) == 3 and sys.argv[1]=='-script'

if MODE_SCRIPT:
    # script execution
    # usage:
    # -script <file_name_base>
    file_name_base = sys.argv[2]
else:
    # run in jupyter notebook
    get_ipython().run_line_magic('matplotlib', 'inline')

# ### Utilities

# In[136]:

def percent(number, prec=2):
    return '{} %'.format(round(number*100, prec))

# In[137]:

# filter rows with all unknown columns
def all_nan_cols(data_frame):
    return data_frame[data_frame.isnull().all(axis=1)]

# filter rows with at least 1 unknown column
def any_nan_cols(data_frame):
    return data_frame[data_frame.isnull().any(axis=1)]

# filter rows with no unknown columns
def no_nan_cols(data_frame):
    return data_frame[data_frame.notnull().all(axis=1)]

# In[138]:

# list column names of specific type from dataframe
def getcols(data_frame, compare_type):
    return [col for col in data_frame if data_frame[col].dtype==compare_type]

# string columns
def scols(data_frame):
    return getcols(data_frame, compare_type=object)

# boolean columns
def bcols(data_frame):
    return getcols(data_frame, compare_type=bool)

# integer columns
def icols(data_frame):
    return getcols(data_frame, compare_type=np.int64)

# decimal columns
def fcols(data_frame):
    return getcols(data_frame, compare_type=np.float64)

# categorical columns
def catcols(data_frame):
    return scols(data_frame) + bcols(data_frame)

# numeric columns
def numcols(data_frame):
    return icols(data_frame) + fcols(data_frame)

# In[139]:

# Modified imputer allows substitution with mode, which can be used for categorical variables
# https://stackoverflow.com/a/45228286/5148218
class CatImputer(Imputer):
    def __init__(self, **kwargs):
        Imputer.__init__(self, **kwargs)

    def fit(self, X, y=None):
        # modify most_frequent strategy to be able to process categorical
        if self.strategy == 'most_frequent':
            self.fills = pd.DataFrame(X).mode(axis=0).squeeze()
            self.statistics_ = self.fills.values
            return self
        else:
            return Imputer.fit(self, X, y=y)

    def transform(self, X):
        if hasattr(self, 'fills'):
            return pd.DataFrame(X).fillna(self.fills).values.astype(str)
        else:
            return Imputer.transform(self, X)

# ### Plotting toolbox

# In[140]:

# bar chart
def bar(series, title=None):
    plt.figure()
    ax = series.value_counts().plot(kind='bar', title=title)
    # https://stackoverflow.com/questions/25447700/annotate-bars-with-values-on-pandas-bar-plots
    for p in ax.patches:
        ax.annotate(str(p.get_height()), (p.get_x() * 1.005, p.get_height() * 1.005))
    plt.show()
    plt.close()

# histogram
def hist(series, title=None, bins=20):
    plt.figure()
    series.plot(kind='hist', bins=bins, title=title)
    plt.show()
    plt.close()

# box plot
def box(series, title=None):
    plt.figure()
    series.plot(kind='box', title=title)
    plt.show()
    plt.close()

# violin plot
def violin(series):
    plt.figure()
    sns.violinplot(series)
    plt.show()
    plt.close()

# series of plots for continuous variables
def contplot(series, bins=20):
    hist(series, title=series.name, bins=bins)
    box(series)
    violin(series)

# scatter plot
def scatter(series_x, series_y, color_series=None):
    plt.figure(figsize=[8,8])
    plt.scatter(series_x, series_y, s=7, alpha=.5, label=None, c=color_series)
    plt.xlabel(series_x.name)
    plt.ylabel(series_y.name)
    plt.show()
    plt.close()

# q-q plot
def qqplot(series, title=None):
    plt.figure(figsize=[5,5])
    stats.probplot(series, plot=plt); # default is normal distribution
    plt.title(title)
    plt.show()
    plt.close()

# ### IO CSV

# In[141]:

def load_csv(path):
    print('Load data from {}'.format(path))
    return pd.read_csv(path, index_col=0)

def save_csv(frame, path):
    print('Save data to {}'.format(path))
    frame.to_csv(path)

# ### Paths

# In[142]:

FILE_PATH = './{}.csv'
FILE_PATH_POLISHED = './{}_polished.csv'
FILE_PATH_GLOBAL = './{}_global.csv'
FILE_PATH_GLOBAL_REMOVAL = './{}_global_removal.csv'
FILE_PATH_GLOBAL_PERCENTILE = './{}_global_percentile.csv'
FILE_PATH_KNN = './{}_knn.csv'
FILE_PATH_KNN_REMOVAL = './{}_knn_removal.csv'
FILE_PATH_KNN_PERCENTILE = './{}_knn_percentile.csv'

# ## Polish

# First look at data

# In[143]:

df = load_csv(FILE_PATH.format(file_name_base))
pd.set_option('display.max_columns', 500) # ensure display all columns
pd.set_option('display.max_colwidth', -1) # ensure display full values
display(df.head(3))

# Some columns can be divided into more

# In[144]:

df = pd.concat([df.drop(['medical_info'], axis=1), df['medical_info'].apply(eval).apply(pd.Series)], axis=1)

# In[145]:

display(df[df['class'].apply(lambda x: len(x.split('.')) != 2)])

# Every element cointains dot, so that we can split on it

# In[146]:

df[['class_sick','class_num']] = pd.DataFrame(df['class'].apply(lambda x: x.split('.')).values.tolist(), index=df.index)
df.drop(['class'], axis=1, inplace=True)
[print(col, df[col].unique()) for col in ['class_sick','class_num']];

# We do not need separator now, let's just see now how to format prediction later

# In[147]:

display(df['class_num'].apply(lambda x: x[0]).value_counts())

# In[148]:

df['class_num'] = df['class_num'].apply(lambda x: x.replace('|','').replace('_',''))
display(df.head())

# ### Nonsense detection

# Now, for the first and the last time, we browse data manually

# In[149]:

for col in df:
    print(col)
    print(df[col].dtype)
    print(df[col].unique())
    print()

# TBG contains no information

# In[150]:

df.drop(['TBG measured','TBG'], axis=1, inplace=True)

# ### Date formatting

# We need all strings for string methods

# In[151]:

print(df['date_of_birth'].apply(type).unique())

# In[152]:

display(df[df['date_of_birth'].apply(lambda x: isinstance(x,float))]['date_of_birth'])

# Replace by string temporarily

# In[153]:

df['date_of_birth'].replace(to_replace=np.nan, value=(10*'?'), inplace=True)

# See length anomalies...

# In[154]:

print(df['date_of_birth'].apply(len).unique())

# ... and non-dash separators...

# In[155]:

display(df[df['date_of_birth'].apply(lambda x: ('-' in x))]['date_of_birth'].head())
display(df[df['date_of_birth'].apply(lambda x: (not '-' in x))]['date_of_birth'].head())

# ... and their combinations

# In[156]:

display(df[df['date_of_birth'].apply(lambda x: ('-' in x) and len(x)!=10)]['date_of_birth'].head())
display(df[df['date_of_birth'].apply(lambda x: (not '-' in x) and len(x)!=10)]['date_of_birth'].head())

# For longer format, make sure time is always at the end

# In[157]:

display(df[df['date_of_birth'].apply(lambda x: len(x)==19 and x[-2:]!='00')]['date_of_birth'])

# It is, so we can convert datetime to date

# In[158]:

df['date_of_birth'] = df['date_of_birth'].apply(lambda x: x[:10])

# For shorter format, make sure year is never at the end

# In[159]:

display(df[df['date_of_birth'].apply(lambda x: len(x)==8 and int(x[-2:])>31)]['date_of_birth'])

# Is is not, so we can add missing century

# In[160]:

df['date_of_birth'] = df['date_of_birth'].apply(lambda x: '19{}'.format(x) if len(x)==8 else x)

# Now we should have a single length

# In[161]:

display(df['date_of_birth'].apply(len).unique())

# We want dash as separator

# In[162]:

df['date_of_birth'] = df['date_of_birth'].apply(lambda x: x.replace('/','-'))

# In[163]:

display(df[df['date_of_birth'].apply(lambda x: (not '-' in x))]['date_of_birth'].head())

# Make sure date components are all separated by dash into day, month, year, respectively

# In[164]:

df['date_of_birth'] = df['date_of_birth'].apply(lambda x: x.split('-'))
display(df[df['date_of_birth'].apply(lambda x: len(x)!=3)]['date_of_birth'].head())

# In[165]:

display(df[df['date_of_birth'].apply(lambda x: len(x[0])!=4)]['date_of_birth'].head())

# Always 3 components but some of them reversed

# In[166]:

df['date_of_birth'] = df['date_of_birth'].apply(lambda x: x[::-1] if len(x[0])!=4 else x)
display(df[df['date_of_birth'].apply(lambda x: len(x[0])!=4)]['date_of_birth'].head())

# Make sure month in the middle

# In[167]:

display(df[df['date_of_birth'].apply(lambda x: len(x)!=1 and int(x[1])>12)]['date_of_birth'])

# Now correct missing date

# In[168]:

df['date_of_birth'] = df['date_of_birth'].apply(lambda x: [np.nan,np.nan,np.nan] if len(x)==1 else x)

# Divide date into separate columns

# In[169]:

df[['year','month','day']] = pd.DataFrame(df['date_of_birth'].values.tolist(), index=df.index, dtype=np.float64)
df.drop(['date_of_birth'], axis=1, inplace=True)

# ### Bool columns

# In[170]:

df['sex'].replace(to_replace='F', value='female', inplace=True) # prevent changing sex's F afterwards
df['sex'].replace(to_replace='M', value='male', inplace=True)
df.replace(to_replace=['f','F','FALSE','negative'], value=False, inplace=True)
df.replace(to_replace=['t','T','TRUE','sick'], value=True, inplace=True)

# ### ... measured columns

# Although the information whether measured or not can be obtained from numeric columns, we keep corresponding bool ones, because the fact that patient needed to have it measured can imply disease. Note here that a situation may occur when we know a substance has been measured but its value is unknown or vice versa

# In[171]:

print(df[df['FTI measured']=='??']['FTI'].unique())
print(df[pd.isnull(df['FTI measured'])]['FTI'].unique())

# Unknown boolean means measured for FTI

# In[172]:

df['FTI measured'].replace(to_replace=['??',np.nan], value=True, inplace=True)
df['FTI'].replace(to_replace='?', value=np.nan, inplace=True)

# Make sure no other anomalies

# In[173]:

for col_measured in df.filter(regex='.measured'):
    col = col_measured.split()[0]
    display(df[df[col].apply(lambda x: type(x)==np.float64)])

# ### Data types

# Goal is to have types:
# - object for string
# - boolean (sometimes 3rd option is necessary for unknown, thn we handle like previous)
# - numPy's float64 for all numbers (to take advantage of NaN)

# In[174]:

df.info()

# Convert integers to float

# In[175]:

[print(v) for v in df['class_num'] if type(v)!=str];

# In[176]:

for col in ['FTI','class_num']+icols(df):
    df[col] = df[col].astype(np.float64)

# From this point, every integer in the frame is also represented by float, so that unknown value can be NaN

# ### Strings

# Remove spaces

# In[177]:

for col in scols(df):
    print(col)
    df[col] = df[col].apply(lambda x: x.replace(' ',''))

# For workclass column we have observed inconsistency

# In[178]:

print(df['workclass'].unique())

# In[179]:

df['workclass'] = df['workclass'].apply(lambda x: x.lower())
print(df['workclass'].unique())

# All unknown strings are going to be represented temporarily by question mark

# In[180]:

df[scols(df)] = df[scols(df)].applymap(lambda x: '?' if pd.isnull(x) else str(x))
for col in scols(df):
    print(col)
    print(df[col].unique())

# Control check on types

# In[181]:

df.info()

# ## Explore

# ### Categorical

# In[182]:

[bar(df[col], title=col) for col in catcols(df)];

# Some columns can be generalized

# In[183]:

df['workclass_basic'] = df['workclass'].apply(pd.Series)
df['workclass_basic'].replace(regex='.*gov', value='gov', inplace=True)
df['workclass_basic'].replace(regex='self-emp.*', value='self-emp', inplace=True)
for col in ['workclass','workclass_basic']:
    bar(df[col], title='workclass: {} distinct'.format(df[col].nunique()))

# The problem is that in this case similar values do not necessarily imply the same disease risk, or even worse there are not enough value counts to find it out

# In[184]:

for v in df['workclass'].unique():
    temp = df[df['workclass']==v]
    bar(temp['class_sick'], title='{} {}'.format(v, percent(len(temp[temp['class_sick']==True]) / len(temp))))

# In[185]:

df['university'] = df['education'].apply(lambda x: x.lower()).apply(pd.Series)

df['university'].replace(to_replace='preschool', value='Before age', inplace=True)
df['university'].replace(regex='.*th', value='Before age', inplace=True)

df['university'].replace(to_replace='hs-grad', value='No', inplace=True)

df['university'].replace(to_replace=['some-college','bachelors'], value='Yes', inplace=True)
df['university'].replace(regex='assoc.*', value='Yes', inplace=True)

df['university'].replace(to_replace=['masters','doctorate'], value='Yes, advanced', inplace=True)
df['university'].replace(regex='prof.*', value='Yes, advanced', inplace=True)

for col in ['education','university']:
    bar(df[col], title='{}: {} distinct'.format(col, df[col].nunique()))

# In[186]:

df['native-country'].replace(to_replace='South', value='?', inplace=True)
df['native-country'].replace(to_replace='Hong', value='Hong-Kong', inplace=True)

df['continent'] = df['native-country'].apply(pd.Series)

continents = {}
continents.update(dict.fromkeys(['United-States','Canada','Outlying-US(Guam-USVI-etc)'],                                'North America'))
continents.update(dict.fromkeys(['Mexico','Puerto-Rico','Guatemala','Columbia','Jamaica','El-Salvador',                                 'Nicaragua','Cuba','Dominican-Republic','Haiti','Ecuador','Peru','Honduras'],                                'Latin America'))
continents.update(dict.fromkeys(['Germany','Poland','Italy','France','England','Greece','Yugoslavia','Portugal'],                                'Europe'))
continents.update(dict.fromkeys(['Trinadad&Tobago','Cambodia'],                                'Africa'))
continents.update(dict.fromkeys(['Philippines','Taiwan','China','Hong-Kong','Japan','India','Vietnam','Laos'],                                'Asia'))
##########
continents.update(dict.fromkeys(['Scotland','Ireland'],'Europe'))
continents.update(dict.fromkeys(['Iran'],'Asia'))
##########

df['continent'] = df['continent'].apply(lambda x: continents[x] if x in continents.keys() and x!='?' else x)

df['USA'] = df['native-country']=='United-States'

for col in ['native-country','continent','USA']:
    bar(df[col], title='{}: {} distinct'.format(col, df[col].nunique()))

# In[187]:

display(df[catcols(df)].describe())

# ### Numeric

# In[188]:

display(df[numcols(df)].describe(percentiles=[.001,.005,.01,.05,0.1,.25,.5,.75,.9,.95,.99,.995,.999]))

# In[189]:

[contplot(df[col], bins=50) for col in numcols(df)];

# ### Outliers

# We saw different types of outliers, that is why we choose different strategies:
# - *values against common sense:* such values can be labelled as unknown without information loss
# - *marginal values:* significantly different but despite possibly real, non-standard individuals, on those outlier substitution techniques can be applied

# In[190]:

ACCEPTED_AGE_CEIL = 120
df['age'] = df['age'].apply(lambda x: np.nan if x>ACCEPTED_AGE_CEIL or pd.isnull(x) else x)
display(df[pd.isnull(df['age'])])
contplot(df['age'])

# Before removal of (seemingly) measurement instrument's mistake, it is still good to make sure it does not represent an extremely sick patient

# In[191]:

# https://www.healthline.com/health/tsh
ACCEPTED_TSH_CEIL = 300
display(df[df['TSH']>ACCEPTED_TSH_CEIL][['TSH','class_sick']])
df['TSH'] = df['TSH'].apply(lambda x: np.nan if x>ACCEPTED_TSH_CEIL else x)
contplot(df['TSH'])

# Transform exponentially decreasing *TSH* by logarithm

# In[192]:

df['TSH_log'] = df['TSH'].apply(lambda x: x if pd.isnull(x) else np.log10(x))
contplot(df['TSH_log'])

# In[193]:

# https://www.healthline.com/health/t3
ACCEPTED_T3_CEIL = 8
display(df[df['T3']>ACCEPTED_T3_CEIL][['T3','class_sick']])
df['T3'] = df['T3'].apply(lambda x: np.nan if x>ACCEPTED_T3_CEIL else x)
contplot(df['T3'])

# In[194]:

# https://www.healthline.com/health/t4
# TT4 = total T4
# T4U = ???
ACCEPTED_TT4_CEIL = 350
display(df[df['TT4']>ACCEPTED_TT4_CEIL][['TT4','class_sick']])
df['TT4'] = df['TT4'].apply(lambda x: np.nan if x>ACCEPTED_TT4_CEIL else x)
contplot(df['TT4'])

# For some numeric columns (... measured in particular), a new boolean column could be generated based on increased/decreased value detected in individual's body (ideally with treshold estimated by a specialist). However, in this case few similar conclusion have already been made, see hyper- and hypothyroid etc.

# *fnlwgt*, i.e. sample weight tells what proportion of population the sampled individual represents

# In[195]:

df.rename(columns={'fnlwgt': 'sample-weight'}, copy=False, inplace=True)

# In[196]:

display(df[df['capital-gain']>30000][['capital-gain','class_sick']])
df['capital-gain'] = df['capital-gain'].apply(lambda x: np.nan if x==99999.0 else x)
contplot(df['capital-gain'])

# In[197]:

df['capital-loss_iszero'] = df['capital-loss'].apply(lambda x: '?' if pd.isnull(x) else x==0.0).apply(pd.Series)
bar(df['capital-loss_iszero'], title='capital-loss == 0.0')
df['capital-loss_nonzero'] = df['capital-loss'].apply(lambda x: np.nan if pd.isnull(x) or x==0.0 else x).apply(pd.Series)
contplot(df['capital-loss_nonzero'])

# In[198]:

ACCEPTED_YEAR_FLOOR = 1880
df['year'] = df['year'].apply(lambda x: np.nan if x<ACCEPTED_YEAR_FLOOR or pd.isnull(x) else x)
display(df[pd.isnull(df['year'])])
contplot(df['year'])
display(df[pd.isnull(df['age'])])

# ### Missing values

# In[199]:

[bar(df[col].apply(lambda x: 'NaN' if pd.isnull(x) else 'value'), title=col) for col in numcols(df)];

# Creating new column has been unfortunately a fail, due to too little known values

# In[200]:

df.drop(['capital-loss_nonzero'], axis=1, inplace=True)

# In[201]:

bar(df.applymap(lambda x: np.nan if type(x)==str and x=='?' else x).isnull().sum(axis=1), title='missing values count per row (i.e. per patient)')

# ### Bivariate analysis

# Scatter all pairs of variables, differentiate between sick and negative patients.
#
# Some variables (with exponential-like distribution in particular) can be beter explored after logarithmic-like transformation applied

# In[202]:

bool_color = df['class_sick'].apply(lambda x: 'red' if x else 'blue')
[scatter(df[colx], df[coly], color_series=bool_color) for colx,coly in itertools.combinations(numcols(df), r=2)];

# Correct observed *age*-*year* nonsense

# In[203]:

print((df['year'] + df['age']).unique())

# In[204]:

nonsense_age = df[(df['year'] + df['age']).apply(lambda x: x not in [2017,2018])][['age','year']]
display(nonsense_age)

# In[205]:

df.loc[nonsense_age.index,'year'] = np.nan
scatter(df['age'], df['year'], color_series=bool_color)

# We can see *age* & *year* represent the same information.
# Also, day & month seem improbable to be disease decoupled (in case we observed sick patients associated with a specific day or month on scatter plot we would consider to keep them)

# In[206]:

df.drop(['day','month','year'], axis=1, inplace=True)

# Confirm correlation *FTI*-*TT4* by all relevant coefficients

# In[207]:

for method in ['pearson','kendall','spearman']:
    print('{} correlation coefficient'.format(method))
    display(df[numcols(df)].corr(method)[df[numcols(df)].corr(method).applymap(lambda x: np.absolute(x) > .3)])

# We did not observe any apparent correlation apart from mentioned one

# We have noticed that *education-num* depends directly on *education* (it is discrete not continuous), some malformed occurences exist though

# In[208]:

display(df[['education','education-num']].drop_duplicates())

# Indentify concrete 1:1 relationship between education columns

# In[209]:

for edu_cat in df['education'].unique():
    print(edu_cat)
    print(df[df['education']==edu_cat]['education-num'].unique())

# In[210]:

def education_to_num(edu_cat):
    return {
        'Preschool': 1.,
        '1st-4th': 2.,
        '5th-6th': 3.,
        '7th-8th': 4.,
        '9th': 5.,
        '10th': 6.,
        '11th': 7.,
        '12th': 8.,
        'HS-grad': 9.,
        'Some-college': 10.,
        'Assoc-voc': 11.,
        'Assoc-acdm': 12.,
        'Bachelors': 13.,
        'Masters': 14.,
        'Prof-school': 15.,
        'Doctorate': 16.
    }.get(edu_cat, np.nan) # unexpected to reach default

# The advantage of numeric over categoric form is that it defines range, hence we do not proceed with column dropping, but changing (correcting) numeric series based on categoric. Great is that *education* contains no unknown (NaN) values

# In[211]:

df['education-num'] = df['education'].apply(lambda x: education_to_num(x))
display(df[['education','education-num']].drop_duplicates())
df.drop(['education'], axis=1, inplace=True)

# Outcomes (from scatter) with focus on predicted variable:
# - low *T3* levels definitely belong to disease endangered group
# - low *T4U* levels probably belong to disease endangered group
# - disease risk grows with *age*
# - *FTI* correlates with *TT4*. Interesting observation here is that sick patients have ratio FTI/TT4 > approx. 1
# - *class_num* is uniformly distributed, probably an index

# ### Distribution

# Compare quantiles with normal distribution

# In[212]:

[qqplot(df[col], title=col) for col in numcols(df)];

# Hereby we have confirmed visually correctness of logarithm-like transformation on *TSH*

# In[213]:

df.drop(['TSH'], axis=1, inplace=True)
# keep log transformed only

# ### Relationship to predicted variable

# In[214]:

# for each attribute
for col in catcols(df):
    print(col)
    # for each unique value
    for v in df[col].unique():
        # suppose this value (and NO another value) predicts True for sick patient), evaluate
        print('\t', v, len(df[df[col] == v]))
#         tp = len(df[(df[col] == v) & (df['class_sick'] == True)])
#         fp = len(df[(df[col] == v) & (df['class_sick'] != True)])
#         fn = len(df[(df[col] != v) & (df['class_sick'] == True)])
        y_col = df[col].apply(lambda x: x==v)
        # accuracy = (tp + tn) / total
        print(2*'\t', 'accuracy ', percent(metrics.accuracy_score(y_true=df['class_sick'], y_pred=y_col)))
        print(2*'\t', ' weighted', percent(metrics.accuracy_score(y_true=df['class_sick'], y_pred=y_col, sample_weight=df['sample-weight'])))
        # precision = tp / (tp + fp)
        print(2*'\t', 'precision', percent(metrics.precision_score(y_true=df['class_sick'], y_pred=y_col)))
        print(2*'\t', ' weighted', percent(metrics.precision_score(y_true=df['class_sick'], y_pred=y_col, sample_weight=df['sample-weight'])))
        # recall = tp / (tp + fn)
        print(2*'\t', 'recall   ', percent(metrics.recall_score(y_true=df['class_sick'], y_pred=y_col)))
        print(2*'\t', ' weighted', percent(metrics.recall_score(y_true=df['class_sick'], y_pred=y_col, sample_weight=df['sample-weight'])))
        # f1score = 2 / (1/precision + 1/recall)
        print(2*'\t', 'F1 score ', percent(metrics.f1_score(y_true=df['class_sick'], y_pred=y_col)))
        print(2*'\t', ' weighted', percent(metrics.f1_score(y_true=df['class_sick'], y_pred=y_col, sample_weight=df['sample-weight'])))

# *native-country* contains too little sample per most of countries. Besides, possible occurence of a new country is gonna be a problem for transformers

# In[215]:

df.drop(['native-country'], axis=1, inplace=True)

# Outcomes with focus on predicted variable:
# -

# ### Inconsistency

# Inconsistencies that have occured with test set:
# - column *native-country* contains other countries which makes newly created *continent* useless since we have defined key-value dictionary manually

# We fixed it by adding additional countries to train better model, even though it may decrease its robustness

# In[216]:

##########
# continents.update(dict.fromkeys(['Scotland','Ireland'],'Europe'))
# continents.update(dict.fromkeys(['Iran'],'Asia'))
##########

# ### Finish

# Some columns are not so relevant since we are to use decision trees for classification

# In[217]:

df.drop(['sample-weight'], axis=1, inplace=True)

# In[218]:

df.replace(to_replace='?', value=np.nan, inplace=True) # because of Imputer later

# Save polished but not preserving all information, some additional information added, missing values & outliers still remain

# In[219]:

display(df.head())

# In[220]:

save_csv(df, FILE_PATH_POLISHED.format(file_name_base))


import numpy as np
import cv2
import math

class FingerFinder(object):
    """docstring for FingerFinder"""

    def __init__(self, background_reduction=False):
        super(FingerFinder, self).__init__()
        self.bg_reduction = background_reduction
        self.kernel = cv2.getStructuringElement(cv2.MORPH_RECT, (20, 20))
        self.fgbg = cv2.bgsegm.createBackgroundSubtractorMOG()

    def process(self, frame):
        res = cv2.flip(frame, 1)
        if self.bg_reduction:
            res = self.apply_mask(res)
        fingers1 = self.find_hand(res, 50, 50, 300, 450, 1)
        fingers2 = self.find_hand(res, 50, 590, 900, 450, 2)
        self.draw_bounding(res, 50, 50, 300, 450, fingers1)
        self.draw_bounding(res, 590, 50, 900, 450, fingers2)

    def find_border(self, contours):
        areas = [cv2.contourArea(c) for c in contours]
        max_index = np.argmax(areas)
        cnt = contours[max_index]
        return cnt

    def apply_mask(self, frame):
        fgmask = self.fgbg.apply(frame)
        fgmask = cv2.dilate(fgmask, self.kernel, iterations=10)
        # fgmask = cv2.morphologyEx(fgmask, cv2.MORPH_OPEN, self.kernel)
        return cv2.bitwise_and(frame, frame, mask=fgmask)

    def make_thresh(self, res):
        grey = cv2.cvtColor(res, cv2.COLOR_BGR2GRAY)
        _, thresh1 = cv2.threshold(grey, 127, 255,
                                   cv2.THRESH_BINARY_INV + cv2.THRESH_OTSU)
        _, contours, hierarchy = cv2.findContours(thresh1.copy(),
                                                  cv2.RETR_TREE,
                                                  cv2.CHAIN_APPROX_NONE)
        return contours

    def count_fingers(self, cnt, img):
        hull = cv2.convexHull(cnt, returnPoints=False)
        defects = cv2.convexityDefects(cnt, hull)
        count_defects = 0
        for i in range(defects.shape[0]):
            s, e, f, d = defects[i, 0]
            start = tuple(cnt[s][0])
            end = tuple(cnt[e][0])
            far = tuple(cnt[f][0])
            a = math.sqrt((end[0] - start[0])**2 + (end[1] - start[1])**2)
            b = math.sqrt((far[0] - start[0])**2 + (far[1] - start[1])**2)
            c = math.sqrt((end[0] - far[0])**2 + (end[1] - far[1])**2)
            angle = math.acos((b**2 + c**2 - a**2) / (2 * b * c)) * 57
            if angle <= 90:
                count_defects += 1
                cv2.circle(img, far, 1, [0, 0, 255], -1)
            # dist = cv2.pointPolygonTest(cnt,far,True)
            cv2.line(img, start, end, [0, 255, 0], 2)
            # cv2.circle(crop_img,far,5,[0,0,255],-1)
        return count_defects

    def find_hand(self, res, xpos, ypos, width, height, handnum):
        crop_img = res[xpos:height, ypos:width]
        cv2.imshow('hand {0}'.format(handnum), crop_img)
        contours = self.make_thresh(crop_img)
        cnt = self.find_border(contours)
        drawing = np.zeros(crop_img.shape, np.uint8)
        cv2.drawContours(drawing, [cnt], 0, (0, 255, 0), 0)
        #
        #
        x, y, w, h = cv2.boundingRect(cnt)
        cv2.rectangle(crop_img, (x, y), (x + w, y + h), (0, 0, 255), 0)
        fingers = self.count_fingers(cnt, crop_img)
        return fingers

    def draw_bounding(self, res, xpos, ypos, width, height, fingers):
        cv2.rectangle(res, (width, height), (xpos, ypos), (0, 255, 0), 0)
        cv2.putText(res, "{0} Fingers".format(fingers), (xpos, ypos),
                    cv2.FONT_HERSHEY_SIMPLEX, 2, (0, 255, 255))


import torch

class LinearAttention1d(torch.nn.Module):
    """
    General linear attention with softmax normalization.
    """
    def __init__(self, in_features, out_features):
        super(LinearAttention1d, self).__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.gate = torch.nn.Linear(self.in_features, self.out_features, bias=False)

    def forward(self, x, g):
        g = g.unsqueeze(2)
        c = torch.bmm(self.gate(x), g)
        a = torch.softmax(c, dim=1)
        g = torch.sum(a * x, dim=1)
        return a.squeeze(2), g

class LinearAttention2d(torch.nn.Module):
    """
    Linear attention based on parametrized compatibility score function with softmax normalization.
    """
    def __init__(self, in_features, out_features):
        super(LinearAttention2d, self).__init__()
        self.in_features = in_features
        self.out_features = out_features
        self.proj = None
        if self.in_features != self.out_features:
            self.proj = torch.nn.Conv2d(
                self.in_features, self.out_features,
                kernel_size=(1, 1), padding=(0, 0), bias=False
            )
        self.score = torch.nn.Conv2d(
            self.out_features, out_channels=1,
            kernel_size=(1, 1), padding=(0, 0), bias=False
        )

    def forward(self, x, g):
        b, _, h, w = x.size()
        if self.proj is not None:
            g = self.proj(g)
        c = self.score(x + g)
        a = torch.softmax(c.view(b, 1, -1), dim=2).view(b, 1, h, w)
        g = torch.mul(a.expand_as(x), x)
        g = g.view(b, self.out_features, -1).sum(dim=2)
        return a, g


from commands.base import CommandBase
from py_utils.emu_utils import run, error
from py_utils.emu_utils import UPDATE_PATH

class Update(CommandBase):
  def __init__(self):
    super().__init__()
    self.name = 'update'
    self.description = 'ðŸŽ‰ Updates this tool'

  @staticmethod
  def _update():
    if not run(['sh', UPDATE_PATH]):
      error('Error updating!')


def solution(nums):
    if len(nums) < 3:
        return []
    nums.sort()
    answer = []
    for i in range(len(nums) - 2):
        print(i)
        if i > 0 and nums[i] == nums[i-1]:
            continue
        l, r = i + 1, len(nums) - 1
        sum = nums[i] + nums[l] + nums[r]
        while l < r:
            print(l)
            if sum < 0:
                l += 1
            elif sum > 0:
                r -= 1
            else:
                answer.append([nums[i], nums[l], nums[r]])
                l += 1
                r -= 1
    return answer

nums = [-1,0,1,2,-1,-4]
print(solution(nums))  # [[-1,-1,2],[-1,0,1]]


from typing import List
from uuid import UUID, uuid4

from fastapi import Depends

from app.models import Product
from app.repositories.errors import EntityNotFound
from app.repositories.product_repo import ProductRepository
from app.services.abstract_srv import AbstractService
from app.services.errors import ProductNotFound

class ProductSrv(AbstractService):
    def __init__(self, repo: ProductRepository = Depends(ProductRepository)):
        super().__init__(repo)

    # Get product by id
    async def get_product(self, product_id: UUID) -> Product:
        try:
            return await self._repository.get(Product, product_id)
        except EntityNotFound:
            raise ProductNotFound()

    # Create new product in the database
    async def new_product(
        self, name: str, calories: float, protein: float, fat: float, carbs: float
    ) -> Product:
        instance = Product(
            id=uuid4(),
            name=name,
            calories=calories,
            protein=protein,
            fat=fat,
            carbs=carbs,
            upvotes=0,
            downvotes=0,
        )
        return await self._repository.create(instance)

    # List all products
    async def list_products(self) -> List[Product]:
        return await self._repository.list(Product)

    # Update product
    async def update_product(
        self,
        product_id: UUID,
        name: str | None,
        calories: float | None,
        protein: float | None,
        fat: float | None,
        carbs: float | None,
        upvotes: int | None,
        downvotes: int | None,
    ) -> Product:
        try:
            instance = await self.get_product(product_id)
        except EntityNotFound:
            raise ProductNotFound()

        instance.name = name or instance.name
        instance.calories = calories or instance.calories
        instance.protein = protein or instance.protein
        instance.fat = fat or instance.fat
        instance.carbs = carbs or instance.carbs
        instance.upvotes = upvotes or instance.upvotes
        instance.downvotes = downvotes or instance.downvotes
        return await self._repository.update(instance)

    # Delete product
    async def delete_product(self, product_id: UUID) -> None:
        try:
            instance = await self.get_product(product_id)
        except EntityNotFound:
            raise ProductNotFound()
        return await self._repository.delete(instance)

    async def search_product(self, product_string):
        return await self._repository.search_product(product_string)


"""Common functionality for handling SWMM input."""

section_formats = {
    '': 'txt',
    'TITLE': 'txt',
    'CONTROLS': 'txt',
}
"""The formats for each section. If not specified, assume space-separated."""

data_indices = {
    'OPTIONS': {
        'Name': 0,
        'Value': 1,
    },
    'SUBCATCHMENTS': {
        'Name': 0,
        'Rgage': 1,
        'OutID': 2,
        'Area': 3,
        '%Imperv': 4,
        'Width': 5,
        'Slope': 6,
        'Clength': 7,
        'Spack': 8,
    },
    'TIMESERIES': {
        'Name': 0,
        'Date': 1,
        'Time': 2,
        'Value': 3,
    },
    'LID_CONTROLS': {
        'Common': {
            'Name': 0,
        },
        'Type': {
            'Type': 1,
        },
    },
    'POLYGONS': {
        'Subcat': 0,
        'Xcoord': 1,
        'Ycoord': 2,
    },
}
"""The indices of values for input lines."""

def get_section_format(section):
    """Get the format for a section.

    Args:
        section (string): The section to get the format for.

    Returns:
        string: The format of the given section.
    """
    return section_formats.get(section, 'ssv')

def get_flow_units(swmm_input):
    """Get the flow units used by the given input.

    Args:
        swmm_input (dict): The input to extract the flow units from.

    Returns:
        string: The flow units being used by the input.
    """
    flow_units = 'CFS'
    if 'OPTIONS' in swmm_input:
        options_name_index = data_indices['OPTIONS']['Name']
        flow_units_line = next((
            line
            for line
            in swmm_input['OPTIONS']['lines']
            if line['values']
            and line['values'][options_name_index] == 'FLOW_UNITS'
        ), None)

        if flow_units_line:
            options_value_index = data_indices['OPTIONS']['Value']
            flow_units = flow_units_line['values'][options_value_index]

    return flow_units

def get_unit_system(swmm_input):
    """Get the unit system used by the given input.

    Args:
        swmm_input (dict): The input to extract the unit system from.

    Returns:
        string: The unit system being used by the input.

    Raises:
        ValueError: The flow units used by the input are not recognized.
    """
    flow_units = get_flow_units(swmm_input)

    if flow_units in {'CFS', 'GPM', 'MGD'}:
        return 'US'
    elif flow_units in {'CMS', 'LPS', 'MLD'}:
        return 'SI'

    raise ValueError('Unrecognized flow units "{0}".'.format(flow_units))


import math
x = int(input())
y = math.ceil(x/2)

for row in range(y):
    for col in range(y+1):
        if col==0:
            print("*",end="")
        elif(col+row==y):
            print("*")
            break
        else:
            print(end=" ")

if(x%2==0):
    print("**")

for row in range(y-1):
    for col in range(y+1):
        if col==0:
            print("*",end="")
        elif(col-row==2):
            print("*")
            break
        else:
            print(end=" ")

end = input()


t = int(input())

for _ in range(t):
    n = int(input())
    arr = list(map(int, input().split()))
    maxyet = float('-inf')
    res = None
    for i in range(n):
        if maxyet != float('-inf') and arr[i] > maxyet:
            res = i
            break
        maxyet = max(maxyet, arr[i])
    if res == None:
        print(-1)
        continue
    print(res)
    print(*arr[:res])
    print(n - res)
    print(*arr[res:])


import gymnasium as gym
import sys
import torch
import torch.nn as nn
import torch.nn.functional as F

import skrl
from skrl.models.torch import Model, DeterministicMixin
from skrl.memories.torch import RandomMemory
from skrl.agents.torch.ddpg import DDPG, DDPG_DEFAULT_CONFIG
from skrl.resources.noises.torch import OrnsteinUhlenbeckNoise
from skrl.trainers.torch import SequentialTrainer, ParallelTrainer
from skrl.envs.torch import wrap_env
from skrl.resources.noises.torch import GaussianNoise
from torch.optim.lr_scheduler import StepLR

# Define the models (deterministic models) for the DDPG agent using mixin
# - Actor (policy): takes as input the environment's observation/state and returns an action
# - Critic: takes the state and action as input and provides a value to guide the policy
class DeterministicActor(DeterministicMixin, Model):
    def __init__(self, observation_space, action_space, device, clip_actions=False):
        Model.__init__(self, observation_space, action_space, device)
        DeterministicMixin.__init__(self, clip_actions)

        self.linear_layer_1 = nn.Linear(self.num_observations, 10)
        self.linear_layer_2 = nn.Linear(10, 10)
        self.action_layer = nn.Linear(10, self.num_actions)

    def compute(self, inputs, role):
        states = inputs["states"].to(self.device)
        x = F.relu(self.linear_layer_1(states))
        x = F.relu(self.linear_layer_2(x))
        # action space is 1 - -1, useful action space is smaller
        return 0.5 * torch.tanh(self.action_layer(x)), {}

class DeterministicCritic(DeterministicMixin, Model):
    def __init__(self, observation_space, action_space, device, clip_actions=False):
        Model.__init__(self, observation_space, action_space, device)
        DeterministicMixin.__init__(self, clip_actions)

        self.linear_layer_1 = nn.Linear(self.num_observations + self.num_actions, 10)
        self.linear_layer_2 = nn.Linear(10, 10)
        self.linear_layer_3 = nn.Linear(10, 1)

    def compute(self, inputs, role):
        x = F.relu(
            self.linear_layer_1(
                torch.cat([inputs["states"], inputs["taken_actions"]], dim=1)
            )
        )
        x = F.relu(self.linear_layer_2(x))
        return self.linear_layer_3(x), {}

def init_models(env, device, pretrain_path=None):
    # Instantiate the agent's models (function approximators).
    # DDPG requires 4 models, visit its documentation for more details
    # https://skrl.readthedocs.io/en/latest/modules/skrl.agents.ddpg.html#spaces-and-models
    models_ddpg = {}
    models_ddpg["policy"] = DeterministicActor(
        env.observation_space, env.action_space, device
    )
    models_ddpg["target_policy"] = DeterministicActor(
        env.observation_space, env.action_space, device
    )
    models_ddpg["critic"] = DeterministicCritic(
        env.observation_space, env.action_space, device
    )
    models_ddpg["target_critic"] = DeterministicCritic(
        env.observation_space, env.action_space, device
    )

    # Initialize the models' parameters (weights and biases) using a Gaussian distribution
    for model in models_ddpg.values():
        model.init_parameters(method_name="normal_", mean=0.0, std=0.1)
    return models_ddpg

def load_models(path, action_space, observation_space, device):
    models_ddpg = {}
    models_ddpg["policy"] = DeterministicActor(observation_space, action_space, device)
    models_ddpg["target_policy"] = DeterministicActor(
        observation_space, action_space, device
    )
    models_ddpg["critic"] = DeterministicCritic(observation_space, action_space, device)
    models_ddpg["target_critic"] = DeterministicCritic(
        observation_space, action_space, device
    )

    old = DDPG(models=models_ddpg)
    old.load(path)
    return old.models


notebook.width = 10
plt.rcParams['figure.figsize'] = (notebook.width, 3)

# only display [0, 20] timerange
notebook.crop = Segment(0, 40)

# plot reference
plt.subplot(211)
reference = Annotation()
reference[Segment(0, 10)] = 'A'
reference[Segment(12, 20)] = 'B'
reference[Segment(24, 27)] = 'A'
reference[Segment(30, 40)] = 'C'
notebook.plot_annotation(reference, legend=True, time=False)
plt.gca().text(0.6, 0.15, 'reference', fontsize=16)

# plot hypothesis
plt.subplot(212)
hypothesis = Annotation()
hypothesis[Segment(2, 13)] = 'a'
hypothesis[Segment(13, 14)] = 'd'
hypothesis[Segment(14, 20)] = 'b'
hypothesis[Segment(22, 38)] = 'c'
hypothesis[Segment(38, 40)] = 'd'
notebook.plot_annotation(hypothesis, legend=True, time=True)
plt.gca().text(0.6, 0.15, 'hypothesis', fontsize=16)

plt.show()


# pyright: basic
import dataclasses
from typing import Callable

import jsonrpcserver

from .. import generator
from ..tracing import with_tracing
from . import overridables

RPC_FAILED_ERROR_CODE = 42

class GeneratorRpcs:
    rd: generator.RefData

    def __init__(self, rd: generator.RefData):
        self.rd = rd

    def wrap_result(self, f: Callable[[], object]) -> jsonrpcserver.Result:
        try:
            result = jsonrpcserver.Success(f())
        except Exception as e:
            result = jsonrpcserver.Error(RPC_FAILED_ERROR_CODE, str(e))
        return result

    def do_list_ags(self):
        def guess_short_name_from_description(d: str) -> str:
            return d.split(",", maxsplit=1)[0].split("(", maxsplit=1)[0]

        # TODO: Add Federal State
        all_ags = self.rd.ags_master()
        return [
            {
                "ags": ags,
                "desc": description,
                "short": guess_short_name_from_description(description),
            }
            for (ags, description) in all_ags.items()
        ]

    def list_ags(self) -> jsonrpcserver.Result:
        return self.wrap_result(self.do_list_ags)

    def make_entries(self, ags: str, year: int, trace: bool) -> jsonrpcserver.Result:
        return self.wrap_result(
            lambda: with_tracing(
                enabled=trace,
                f=lambda: dataclasses.asdict(
                    generator.make_entries(self.rd, ags, year)
                ),
            )
        )

    def calculate(
        self, ags: str, year: int, overrides: dict[str, int | float | str], trace: bool
    ) -> jsonrpcserver.Result:
        def calculate():
            defaults = dataclasses.asdict(generator.make_entries(self.rd, ags, year))
            defaults.update(overrides)
            entries = generator.Entries(**defaults)

            if ags == "DG000000":
                entries_germany = entries
            else:
                entries_germany = generator.make_entries(
                    self.rd, ags="DG000000", year=year
                )

            inputs = generator.Inputs(
                facts=self.rd.facts(),
                assumptions=self.rd.assumptions(),
                entries=entries,
            )
            inputs_germany = generator.Inputs(
                facts=self.rd.facts(),
                assumptions=self.rd.assumptions(),
                entries=entries_germany,
            )
            g = generator.calculate(inputs, inputs_germany)
            return g.result_dict()

        return self.wrap_result(lambda: with_tracing(enabled=trace, f=calculate))

    def get_overridables(self, ags: str, year: int) -> jsonrpcserver.Result:
        return self.wrap_result(
            lambda: overridables.sections_with_defaults(self.rd, ags, year)
        )

    def info(self, key: str) -> jsonrpcserver.Result:
        if key.startswith("Fact_"):
            return self.wrap_result(
                lambda: dataclasses.asdict(self.rd.facts().complete_fact(key))
            )
        elif key.startswith("Ass_"):
            return self.wrap_result(
                lambda: dataclasses.asdict(self.rd.assumptions().complete_ass(key))
            )
        else:
            return self.wrap_result(lambda: None)

    def methods(self) -> jsonrpcserver.methods.Methods:
        return {
            "make-entries": self.make_entries,
            "get-overridables": self.get_overridables,
            "list-ags": self.list_ags,
            "calculate": self.calculate,
            "info": self.info,
        }


import asyncio

from typing import Callable, Any, Set, List, Dict

from utils.logger import Logger, LoggerLevel
from .event_listener import EventListener, Priority
from .event import Event

class EventDispatcher:
    """
    EventDispatcher handles event listeners, triggers events, and manages asynchronous execution of listeners.
    """

    _busy_listeners: Set['Callable'] = set()

    def __init__(self, debug_mode: bool = False):
        """
        Initialize the EventDispatcher.

        :param debug_mode: Enable debug mode for logging.
        """
        self.debug_mode = debug_mode
        self._listeners: Dict[str, List['EventListener']] = {}
        self._cancel_events = False

        self._event_loop = asyncio.get_event_loop()
        self._event_queue = asyncio.Queue()
        self._is_event_loop_running = False

    def start(self):
        """
        Start the event loop if not already running.
        """
        if not self._is_event_loop_running:
            self._event_loop.create_task(self._event_loop_runner())
            self._is_event_loop_running = True

    async def close(self):
        """
        Close the event loop and wait for queued events to be processed and ran.
        """

        # wait for all events in the queue to be processed
        while self._event_queue.qsize():
            await asyncio.sleep(0.1)

        tasks = []
        for task in asyncio.all_tasks(loop=self._event_loop):
            if task.get_coro().__name__ == "_async_trigger":
                tasks.append(task)
        # wait for all the running events to finish
        await asyncio.gather(*tasks)
        self._is_event_loop_running = False

    def add_listener(self, event_name: str, listener: Callable, priority: Priority = Priority.NORMAL) -> None:
        """
        Add a listener to the event.

        :param event_name: Name of the event.
        :param listener: Callable object representing the listener function.
        :param priority: Priority of the listener.
        """
        if callable(listener):
            self._register_event_listener(event_name, listener, priority)
            self._sort_listeners(event_name)
        else:
            raise ValueError("Listener must be callable (a function or method).")

    def remove_listener(self, event_name: str, listener: Callable) -> None:
        """
        Remove a listener from the event.

        :param event_name: Name of the event.
        :param listener: Callable object representing the listener function.
        """
        for event_listener in self._listeners.get(event_name):
            if event_listener.callback == listener:
                self._listeners.get(event_name).remove(event_listener)
                return  # To ensure only one instance is removed

    def trigger(self, event: Event, *args, **kwargs) -> None:
        """
        Trigger the event and notify all registered listeners.

        :param event: The event to trigger.
        :param args: Additional arguments to pass to listeners.
        :param kwargs: Additional keyword arguments to pass to listeners.
        """
        if not self._is_event_loop_running:
            raise Exception("No event loop running")
        self._event_queue.put_nowait((self._trigger, event, args, kwargs))

    def _trigger(self, event: Event, *args, **kwargs) -> None:
        """
        Internal method to trigger the event and notify all registered listeners.

        :param event: The event to trigger.
        :param args: Additional arguments to pass to listeners.
        :param kwargs: Additional keyword arguments to pass to listeners.
        """
        if event.event_name not in self._listeners or self._cancel_events:
            return

        responses = 0
        for listener in self._listeners[event.event_name]:
            if self.debug_mode:
                Logger.console_log(f"calling: [{listener.callback.__name__}] from event: [{event.event_name}]",
                                   LoggerLevel.INFO, include_time=True)

            if event.max_responders == -1 or responses < event.max_responders:
                listener.callback(event, *args, **kwargs)
                responses += 1
            # max responses reached exit the function
            else:
                return

    async def async_trigger(self, event: Event, *args: Any, **kwargs: Any) -> None:
        """
        Asynchronously trigger the event and notify registered listeners.

        :param event: The event to trigger.
        :param args: Additional arguments to pass to listeners.
        :param kwargs: Additional keyword arguments to pass to listeners.
        """
        if not self._is_event_loop_running:
            raise Exception("No event loop running")
        self._event_queue.put_nowait((self._async_trigger, event, args, kwargs))

    async def _async_trigger(self, event: Event, *args: Any, **kwargs: Any) -> None:
        """
        Internal method to asynchronously trigger the event and notify registered listeners.

        :param event: The event to trigger.
        :param args: Additional arguments to pass to listeners.
        :param kwargs: Additional keyword arguments to pass to listeners.
        """
        if self._cancel_events:
            return

        listeners = self._listeners.get(event.event_name, [])
        max_responders = event.max_responders if event.max_responders != -1 else len(listeners)

        await asyncio.gather(*[self._run_listener(listener, event, *args, **kwargs) for listener in listeners[:max_responders]])

    async def _run_listener(self, listener: EventListener, event: Event, *args, **kwargs):
        """
        Asynchronously run the specified listener for the given event.

        :param listener: The listener to run.
        :param event: The event being processed.
        :param args: Additional arguments to pass to the listener.
        :param kwargs: Additional keyword arguments to pass to the listener.
        """
        if self.debug_mode:
            Logger.console_log(
                f"async calling: [{listener.callback.__name__}] from event: [{event.event_name}]",
                LoggerLevel.INFO, include_time=True)

            if listener.callback in self._busy_listeners:
                Logger.console_log(
                    f"skipping call to: [{listener.callback.__name__}] as its busy",
                    LoggerLevel.INFO, include_time=True)

        if listener.callback not in self._busy_listeners or event.allow_busy_trigger:
            self._busy_listeners.add(listener.callback)
            await listener.callback(event, *args, **kwargs)
            self._remove_busy_listener(listener.callback)

    def disable_all_events(self) -> None:
        """
        Disable all events from being triggered.
        """
        self._cancel_events = True

    def enable_all_events(self) -> None:
        """
        Enable all events to be triggered.
        """
        self._cancel_events = False

    def is_queue_empty(self) -> bool:
        """
        Check if the event queue is empty.

        :return: True if the event queue is empty, False otherwise.
        """
        return self._event_queue.empty()

    def queue_size(self) -> int:
        """
        Get the size of the event queue.

        :return: The number of events in the queue.
        """
        return self._event_queue.qsize()

    def _register_event_listener(self, event_name: str, callback: Callable, priority: Priority) -> None:
        """
        Register an event listener for the specified event.

        :param event_name: Name of the event.
        :param callback: Callable object representing the listener function.
        :param priority: Priority of the listener.
        """
        listener = EventListener(callback=callback, priority=priority)

        # if the callback is already registered in the event, return
        if listener.callback in [lstener for lstener in self._listeners.get(event_name, [])]:
            return

        if event_name in self._listeners:
            self._listeners[event_name].append(listener)
        else:
            self._listeners.update({event_name: [listener]})

    def _sort_listeners(self, event_name: str) -> None:
        """
        Sort the listeners for the specified event based on their priorities.

        :param event_name: Name of the event.
        """
        if event_name not in self._listeners:
            return
        self._listeners[event_name] = sorted(self._listeners[event_name], key=lambda event_listener: event_listener.priority.value)

    def _remove_busy_listener(self, callback: Callable) -> None:
        """
        Remove a busy listener from the set of busy listeners.

        :param callback: Callable object representing the listener function.
        """
        if callback in self._busy_listeners:
            self._busy_listeners.remove(callback)

    async def _event_loop_runner(self):
        """
        Run the event loop to process queued events.
        """
        while self._is_event_loop_running:
            task = await self._event_queue.get()
            func, event, args, kwargs = task
            if asyncio.iscoroutinefunction(func):
                self._event_loop.create_task(func(event, *args, **kwargs))
            else:
                func(event, *args, **kwargs)
            self._event_queue.task_done()


"""
==============
Normalized Cut
==============

This example constructs a Region Adjacency Graph (RAG) and recursively performs
a Normalized Cut on it.

References
----------
.. [1] Shi, J.; Malik, J., "Normalized cuts and image segmentation",
       Pattern Analysis and Machine Intelligence,
       IEEE Transactions on, vol. 22, no. 8, pp. 888-905, August 2000.
"""

from skimage import data, segmentation, color
from skimage.io import imread
from skimage import data
from skimage.future import graph
from matplotlib import pyplot as plt

img = data.astronaut()

img_segments = segmentation.slic(img, compactness=30, n_segments=200)
out1 = color.label2rgb(img_segments, img, kind='avg')

segment_graph = graph.rag_mean_color(img, img_segments, mode='similarity')
img_cuts = graph.cut_normalized(img_segments, segment_graph)
normalized_cut_segments = color.label2rgb(img_cuts, img, kind='avg')

fig, ax = plt.subplots(nrows=1, ncols=2, sharex=True, sharey=True, figsize=(6, 8))

ax[0].imshow(img)
ax[1].imshow(normalized_cut_segments)

for a in ax:
    a.axis('off')

plt.tight_layout()
plt.show()


# Uses python3
import sys

def fibonacci_partial_sum_naive2(from_, to):
    _sum = 0

    current = 0
    _next  = 1

    for i in range(to + 1):
        if i >= from_:
            _sum += current

        current, _next = _next, current + _next

    return _sum % 10

def fibonacci_partial_sum_naive(from_, to):
    f = fibPeriod(10)
    p = len(f)
    last_index = to % p
    first_index = from_ %p
    noOfperiods = int(to/p)
    sumOfperiod = sum(f)
    sumOflast = sum(f[:last_index+1])
    sumOfAllTolast = noOfperiods * sumOfperiod + sumOflast
    return (sumOfAllTolast - sum(f[:first_index]))%10

def fibPeriod(m):
    f = []
    f.append(0)
    f.append(1)

    i = 2
    while(1):
        next = (f[i - 1] + f[i - 2])%m
        f.append(next)
        i+=1

        if(f[i-1] == 1 and f[i - 2] == 0):
            return f[:-2]

if __name__ == '__main__':
    input = sys.stdin.read()
    from_, to = map(int, input.split())
    print(fibonacci_partial_sum_naive(from_, to))
    #print(fibonacci_partial_sum_naive2(from_, to))


import numpy as np
import string

def main_algorithm(A):

    A_length = len(A[0])  # indices start with zero in python.
    i = 0
    for j in range(A_length):
        if A[0][i] == 1:
            key = A[0][i]
            key_alpha = A[1][i]
            A[0][i:A_length - 1] = A[0][i + 1: A_length]
            A[1][i:A_length - 1] = A[1][i + 1: A_length]
            A[0][A_length - 1] = key
            A[1][A_length - 1] = key_alpha
        else:
            i += 1

    return A

def bare_algorithm(a):

    i = 0
    length_a = len(a)
    for j in range(length_a):
        if a[i] == 1:
            key = a[i]
            a[i:length_a - 1] = a[i + 1: length_a]
            a[length_a - 1] = key
        else:
            i += 1

    return a

if __name__ == '__main__':

    array_length = 26
    random_ones_zeros = list(np.random.choice([0, 1], array_length))  # Uniformly random one's and zeros.
    match_alphabet = string.ascii_uppercase[0:array_length]
    A = [random_ones_zeros, list(match_alphabet)]
    print(A[0])
    print(A[1])
    print()
    A = main_algorithm(A)
    print(A[0])
    print(A[1])
    print()

    a = list(np.random.choice([0, 1], array_length))
    b = bare_algorithm(a)
    print(b)


# -*- coding: utf-8 -*-

"""
Kuplung - OpenGL Viewer, python port
supudo.net
"""
__author__ = 'supudo'
__version__ = "1.0.0"

import copy
import os
import numpy
import imgui
from OpenGL.GL import *
from PIL import Image
from settings import Settings
from ui.ui_helpers import UIHelpers
from gl_utils.objects.Material import MaterialTextureType

class DialogControlsModels():

    def __init__(self):
        self.cmenu_deleteYn = False
        self.cmenu_renameModel = False

        self.showTextureWindow_Ambient = False
        self.showTexture_Ambient = False
        self.showTextureWindow_Diffuse = False
        self.showTexture_Diffuse = False
        self.showTextureWindow_Dissolve = False
        self.showTexture_Dissolve = False
        self.showTextureWindow_Bump = False
        self.showTexture_Bump = False
        self.showTextureWindow_Specular = False
        self.showTexture_Specular = False
        self.showTextureWindow_SpecularExp = False
        self.showTexture_SpecularExp = False
        self.showTextureWindow_Displacement = False
        self.showTexture_Displacement = False
        self.showUVEditor = False
        self.vboTextureAmbient = -1
        self.vboTextureDiffuse = -1
        self.vboTextureDissolve = -1
        self.vboTextureBump = -1
        self.vboTextureDisplacement = -1
        self.vboTextureSpecular = -1
        self.vboTextureSpecularExp = -1

        self.textureAmbient_Width = self.textureAmbient_Height = self.textureDiffuse_Width = self.textureDiffuse_Height = 0
        self.textureDissolve_Width = self.textureDissolve_Height = self.textureBump_Width = self.textureBump_Height = 0
        self.textureSpecular_Width = self.textureSpecular_Height = self.textureSpecularExp_Width = self.textureSpecularExp_Height = 0
        self.textureDisplacement_Width = self.textureDisplacement_Height = 0

        self.selectedObject = 0
        self.selectedTabScene = 0
        self.selectedTabGUICamera = 0
        self.selectedTabGUIGrid = 0
        self.selectedTabGUILight = 0
        self.selectedTabPanel = 1

        self.height_top_panel = 170.0
        self.ui_helper = UIHelpers

        self.multi_handler_ro = False

    def render(self, delegate, is_opened, managerObjects, meshModelFaces, is_frame, sceneSelectedModelObject):
        self.selectedObject = sceneSelectedModelObject
        self.is_frame = is_frame

        imgui.set_next_window_size(300, 600, imgui.FIRST_USE_EVER)
        imgui.set_next_window_position(10, 28, imgui.FIRST_USE_EVER)

        _, is_opened = imgui.begin('Scene Settings', is_opened, 0)

        tab_labels = ['Models', 'Create']
        tab_icons = ['ICON_MD_BUILD', 'ICON_MD_ADD']
        self.selectedTabPanel = self.ui_helper.draw_tabs(tab_labels, tab_icons, self.selectedTabPanel)

        if self.selectedTabPanel == 0:
            if meshModelFaces is not None and len(meshModelFaces) > 0:
                meshModelFaces = self.render_models(meshModelFaces, managerObjects, delegate)
            else:
                imgui.text_colored('No models in the current scene.', 255, 0, 0, 255)
        else:
            self.render_create(delegate)

        imgui.end()

        sceneSelectedModelObject = self.selectedObject

        return is_opened, meshModelFaces, sceneSelectedModelObject

    def render_create(self, delegate):
        # shapes
        for shape in Settings.ShapeTypes:
            if shape.name != 'ShapeType_None' and shape.name != 'ShapeType_Separator':
                if imgui.button(shape.value[1], -1, 0):
                    delegate.add_shape(shape)
            if shape.name == 'ShapeType_Separator':
                imgui.separator()
                imgui.separator()

        imgui.separator()
        imgui.separator()

        # lights
        for light in Settings.LightSourceTypes:
            if imgui.button(light.value[0], -1, 0):
                delegate.add_light(light)

    def render_models(self, mmfs, mo, delegate):
        # reset defaults button
        imgui.push_style_color(imgui.COLOR_BUTTON, .6, .1, .1, 1)
        imgui.push_style_color(imgui.COLOR_BUTTON_HOVERED, .9, .1, .1, 1)
        imgui.push_style_color(imgui.COLOR_BUTTON_ACTIVE, .8, .2, .2, 1)
        if imgui.button('Reset values to default', -1, 0):
            for i in range(len(mmfs)):
                mmfs[i].initModelProperties()
        imgui.pop_style_color(3)

        # scene items
        imgui.begin_child("Scene Items", 0.0, self.height_top_panel, True)

        scene_items = []
        for item in mmfs:
            scene_items.append(item.mesh_model.ModelTitle)

        imgui.push_item_width(-1)
        imgui.push_style_var(imgui.STYLE_ITEM_SPACING, (0, 6))
        imgui.push_style_var(imgui.STYLE_WINDOW_MIN_SIZE, (0, 100))
        imgui.push_style_color(imgui.COLOR_FRAME_BACKGROUND, 0, 0, 0, 1)
        _, self.selectedObject = imgui.listbox('', self.selectedObject, scene_items)
        imgui.pop_style_color(1)
        imgui.pop_style_var(2)
        if self.selectedObject > -1 and imgui.begin_popup_context_item('Actions'):
            _, clicked_rename = imgui.menu_item('Rename', None, None, False)
            _, clicked_duplicate = imgui.menu_item('Duplicate')
            if clicked_duplicate:
                new_model = copy.deepcopy(mmfs[self.selectedObject])
                mmfs.append(new_model)
            if imgui.begin_menu('Delete'):
                _, clicked_delete_ok = imgui.menu_item('OK')
                if clicked_delete_ok:
                    delegate.remove_model(self.selectedObject)
                imgui.end_menu()
            imgui.end_popup()

        imgui.pop_item_width()

        imgui.end_child()

        imgui_io = imgui.get_io()
        imgui_io.mouse_draw_cursor = True
        imgui.push_style_color(imgui.COLOR_BUTTON, 89 / 255.0,
                               91 / 255.0, 94 / 255.0, 1.0)
        imgui.push_style_color(imgui.COLOR_BUTTON_HOVERED, 119 / 255.0,
                               122 / 255.0, 124 / 255.0, 1.0)
        imgui.push_style_color(imgui.COLOR_BORDER, 0, 0, 0, 1)
        imgui.button("###splitterModels", -1, 8.0)
        imgui.pop_style_color(3)
        if imgui.is_item_active():
            self.height_top_panel += imgui.get_mouse_drag_delta().y
        if imgui.is_item_hovered():
            imgui.set_mouse_cursor(imgui.MOUSE_CURSOR_RESIZE_NS)
        else:
            imgui_io.mouse_draw_cursor = False

        # properties
        imgui.begin_child("Properties Pane", 0.0, 0.0, False)
        imgui.push_item_width(imgui.get_window_width() * 0.75)

        if self.selectedObject > -1:
            mmf = mmfs[self.selectedObject]
            imgui.text_colored('OBJ File:', 255, 0, 0, 255)
            imgui.same_line()
            imgui.text(mmf.mesh_model.file.replace('resources/shapes/', ''))
            imgui.text_colored('Model Face:', 255, 0, 0, 255)
            imgui.same_line()
            imgui.text(mmf.mesh_model.ModelTitle)
            imgui.text_colored('Material:', 255, 0, 0, 255)
            imgui.same_line()
            imgui.text(mmf.mesh_model.MaterialTitle)
            imgui.text_colored('Vertices:', 255, 0, 0, 255)
            imgui.same_line()
            imgui.text(str(mmf.mesh_model.countVertices))
            imgui.text_colored('Normals:', 255, 0, 0, 255)
            imgui.same_line()
            imgui.text(str(mmf.mesh_model.countNormals))
            imgui.text_colored('Indices:', 255, 0, 0, 255)
            imgui.same_line()
            imgui.text(str(mmf.mesh_model.countIndices))

            has_textures = False
            if mmf.mesh_model.ModelMaterial.texture_ambient.Image != '':
                has_textures = True
            if mmf.mesh_model.ModelMaterial.texture_diffuse.Image != '':
                has_textures = True
            if mmf.mesh_model.ModelMaterial.texture_normal.Image != '':
                has_textures = True
            if mmf.mesh_model.ModelMaterial.texture_displacement.Image != '':
                has_textures = True
            if mmf.mesh_model.ModelMaterial.texture_specular.Image != '':
                has_textures = True
            if mmf.mesh_model.ModelMaterial.texture_specular_exp.Image != '':
                has_textures = True
            if mmf.mesh_model.ModelMaterial.texture_dissolve.Image != '':
                has_textures = True

            if has_textures:
                imgui.separator()
                imgui.text_colored('Textures:', 255, 0, 0, 255)

            mmfs, self.showTextureWindow_Ambient, self.showTexture_Ambient = self.show_texture_line('##001', mmfs, MaterialTextureType.MaterialTextureType_Ambient, self.showTextureWindow_Ambient, self.showTexture_Ambient)
            mmfs, self.showTextureWindow_Diffuse, self.showTexture_Diffuse = self.show_texture_line('##002', mmfs, MaterialTextureType.MaterialTextureType_Diffuse, self.showTextureWindow_Diffuse, self.showTexture_Diffuse)
            mmfs, self.showTextureWindow_Dissolve, self.showTexture_Dissolve = self.show_texture_line('##003', mmfs, MaterialTextureType.MaterialTextureType_Dissolve, self.showTextureWindow_Dissolve, self.showTexture_Dissolve)
            mmfs, self.showTextureWindow_Bump, self.showTexture_Bump = self.show_texture_line('##004', mmfs, MaterialTextureType.MaterialTextureType_Bump, self.showTextureWindow_Bump, self.showTexture_Bump)
            mmfs, self.showTextureWindow_Displacement, self.showTexture_Displacement = self.show_texture_line('##005', mmfs, MaterialTextureType.MaterialTextureType_Displacement, self.showTextureWindow_Displacement, self.showTexture_Displacement)
            mmfs, self.showTextureWindow_Specular, self.showTexture_Specular = self.show_texture_line('##006', mmfs, MaterialTextureType.MaterialTextureType_Specular, self.showTextureWindow_Specular, self.showTexture_Specular)
            mmfs, self.showTextureWindow_SpecularExp, self.showTexture_SpecularExp = self.show_texture_line('##007', mmfs, MaterialTextureType.MaterialTextureType_SpecularExp, self.showTextureWindow_SpecularExp, self.showTexture_SpecularExp)

            if self.showTextureWindow_Ambient:
                self.showTextureWindow_Ambient, self.showTexture_Ambient, self.vboTextureAmbient, self.textureAmbient_Width, self.textureAmbient_Height = self.show_texture_image(mmfs[self.selectedObject], MaterialTextureType.MaterialTextureType_Ambient, 'Ambient', self.showTextureWindow_Ambient, self.showTexture_Ambient, self.vboTextureAmbient, self.textureAmbient_Width, self.textureAmbient_Height)
            if self.showTextureWindow_Diffuse:
                self.showTextureWindow_Diffuse, self.showTexture_Diffuse, self.vboTextureDiffuse, self.textureDiffuse_Width, self.textureDiffuse_Height = self.show_texture_image(mmfs[self.selectedObject], MaterialTextureType.MaterialTextureType_Diffuse, 'Diffuse', self.showTextureWindow_Diffuse, self.showTexture_Diffuse, self.vboTextureDiffuse, self.textureDiffuse_Width, self.textureDiffuse_Height)
            if self.showTextureWindow_Dissolve:
                self.showTextureWindow_Dissolve, self.showTexture_Dissolve, self.vboTextureDissolve, self.textureDissolve_Width, self.textureDissolve_Height = self.show_texture_image(mmfs[self.selectedObject], MaterialTextureType.MaterialTextureType_Dissolve, 'Dissolve', self.showTextureWindow_Dissolve, self.showTexture_Dissolve, self.vboTextureDissolve, self.textureDissolve_Width, self.textureDissolve_Height)
            if self.showTextureWindow_Bump:
                self.showTextureWindow_Bump, self.showTexture_Bump, self.vboTextureBump, self.textureBump_Width, self.textureBump_Height = self.show_texture_image(mmfs[self.selectedObject], MaterialTextureType.MaterialTextureType_Bump, 'Normal', self.showTextureWindow_Bump, self.showTexture_Bump, self.vboTextureBump, self.textureBump_Width, self.textureBump_Height)
            if self.showTextureWindow_Displacement:
                self.showTextureWindow_Displacement, self.showTexture_Displacement, self.vboTextureDisplacement, self.textureDisplacement_Width, self.textureDisplacement_Height = self.show_texture_image(mmfs[self.selectedObject], MaterialTextureType.MaterialTextureType_Displacement, 'Displacement', self.showTextureWindow_Displacement, self.showTexture_Displacement, self.vboTextureDisplacement, self.textureDisplacement_Width, self.textureDisplacement_Height)
            if self.showTextureWindow_Specular:
                self.showTextureWindow_Specular, self.showTexture_Specular, self.vboTextureSpecular, self.textureSpecular_Width, self.textureSpecular_Height = self.show_texture_image(mmfs[self.selectedObject], MaterialTextureType.MaterialTextureType_Specular, 'Specular', self.showTextureWindow_Specular, self.showTexture_Specular, self.vboTextureSpecular, self.textureSpecular_Width, self.textureSpecular_Height)
            if self.showTextureWindow_SpecularExp:
                self.showTextureWindow_SpecularExp, self.showTexture_SpecularExp, self.vboTextureSpecularExp, self.textureSpecularExp_Width, self.textureSpecularExp_Height = self.show_texture_image(mmfs[self.selectedObject], MaterialTextureType.MaterialTextureType_SpecularExp, 'Specular Exp', self.showTextureWindow_SpecularExp, self.showTexture_SpecularExp, self.vboTextureSpecularExp, self.textureSpecularExp_Width, self.textureSpecularExp_Height)

            imgui.separator()

            tab_labels = [
                'General', 'Scale', 'Rotate', 'Translate', 'Displace',
                'Material', 'Effects', 'Illumination'
            ]
            tab_icons = [
                'ICON_MD_TRANSFORM', 'ICON_MD_PHOTO_SIZE_SELECT_SMALL',
                'ICON_MD_3D_ROTATION', 'ICON_MD_OPEN_WITH',
                'ICON_MD_TOLL', 'ICON_MD_FORMAT_PAINT', 'ICON_MD_BLUR_ON',
                'ICON_MD_LIGHTBULB_OUTLINE'
            ]
            self.selectedTabScene = self.ui_helper.draw_tabs(tab_labels, tab_icons, self.selectedTabScene, 4, 1.0)

            if self.selectedTabScene == 0:
                mmfs = self.render_properties(mmfs)
            if self.selectedTabScene == 1:
                mmfs = self.render_scale(mmfs, mo.Setting_GridSize)
            if self.selectedTabScene == 2:
                mmfs = self.render_rotate(mmfs)
            if self.selectedTabScene == 3:
                mmfs = self.render_translate(mmfs, mo.Setting_GridSize)
            if self.selectedTabScene == 4:
                mmfs = self.render_displace(mmfs, mo.Setting_GridSize)
            if self.selectedTabScene == 5:
                mmfs = self.render_material(mmfs)
            if self.selectedTabScene == 6:
                mmfs = self.render_effects(mmfs)
            if self.selectedTabScene == 7:
                mmfs = self.render_illumination_type(mmfs)

            imgui.separator()

        imgui.pop_item_width()
        imgui.end_child()

        return mmfs

    def render_properties(self, mmfs):
        imgui.text_colored('Properties', 1, 0, 0, 1)
        _, mmfs[self.selectedObject].Setting_CelShading = imgui.checkbox('Cel Shading', mmfs[self.selectedObject].Setting_CelShading)
        _, mmfs[self.selectedObject].Setting_Wireframe = imgui.checkbox('Wireframe', mmfs[self.selectedObject].Setting_Wireframe)
        _, mmfs[self.selectedObject].Setting_EditMode = imgui.checkbox('Edit Mode', mmfs[self.selectedObject].Setting_EditMode)
        _, mmfs[self.selectedObject].Setting_ShowShadows = imgui.checkbox('Shadows', mmfs[self.selectedObject].Setting_ShowShadows)
        imgui.text_colored('Alpha Blending', 1, 0, 0, mmfs[self.selectedObject].Setting_Alpha)
        mmfs[self.selectedObject].Setting_Alpha = self.ui_helper.add_slider_control('', 1, 0.0, 1.0, mmfs[self.selectedObject].Setting_Alpha)
        return mmfs

    def render_scale(self, mmfs, gs):
        imgui.text_colored('Scale Model', 1, 0, 0, 1)
        _, mmfs[self.selectedObject].Setting_ScaleAllParts = imgui.checkbox('Scale All', mmfs[self.selectedObject].Setting_ScaleAllParts)
        if mmfs[self.selectedObject].Setting_ScaleAllParts:
            _, mmfs[self.selectedObject].scaleX.point = imgui.slider_float('##001', mmfs[self.selectedObject].scaleX.point, 0.05, gs / 2, "%.03f", 1.0)
            imgui.same_line()
            imgui.text('X')
            _, mmfs[self.selectedObject].scaleY.point = imgui.slider_float('##001', mmfs[self.selectedObject].scaleY.point, 0.05, gs / 2, "%.03f", 1.0)
            imgui.same_line()
            imgui.text('Y')
            _, mmfs[self.selectedObject].scaleZ.point = imgui.slider_float('##001', mmfs[self.selectedObject].scaleZ.point, 0.05, gs / 2, "%.03f", 1.0)
            imgui.same_line()
            imgui.text('Z')
        else:
            _, mmfs[self.selectedObject].scaleX.point = imgui.slider_float('##001', mmfs[self.selectedObject].scaleX.point, 0.05, gs / 2, "%.03f", 1.0)
            imgui.same_line()
            imgui.text('X')
            _, mmfs[self.selectedObject].scaleY.point = imgui.slider_float('##002', mmfs[self.selectedObject].scaleY.point, 0.05, gs / 2, "%.03f", 1.0)
            imgui.same_line()
            imgui.text('Y')
            _, mmfs[self.selectedObject].scaleZ.point = imgui.slider_float('##003', mmfs[self.selectedObject].scaleZ.point, 0.05, gs / 2, "%.03f", 1.0)
            imgui.same_line()
            imgui.text('Z')
        return mmfs

    def render_rotate(self, mmfs):
        imgui.text_colored('Rotate model around axis', 1, 0, 0, 1)
        mmfs[self.selectedObject].rotateX.animate, mmfs[self.selectedObject].rotateX.point = self.ui_helper.add_controls_slider_same_line('X', 4, 1.0, -180.0, 180.0, True, mmfs[self.selectedObject].rotateX.animate, mmfs[self.selectedObject].rotateX.point, True, self.is_frame)
        mmfs[self.selectedObject].rotateY.animate, mmfs[self.selectedObject].rotateY.point = self.ui_helper.add_controls_slider_same_line('Y', 5, 1.0, -180.0, 180.0, True, mmfs[self.selectedObject].rotateY.animate, mmfs[self.selectedObject].rotateY.point, True, self.is_frame)
        mmfs[self.selectedObject].rotateZ.animate, mmfs[self.selectedObject].rotateZ.point = self.ui_helper.add_controls_slider_same_line('Z', 6, 1.0, -180.0, 180.0, True, mmfs[self.selectedObject].rotateZ.animate, mmfs[self.selectedObject].rotateZ.point, True, self.is_frame)
        return mmfs

    def render_translate(self, mmfs, gs):
        imgui.text_colored('Translate model by axis', 1, 0, 0, 1)
        mmfs[self.selectedObject].positionX.animate, mmfs[self.selectedObject].positionX.point = self.ui_helper.add_controls_slider_same_line('X', 7, 1.0, -1 * gs, gs, True, mmfs[self.selectedObject].positionX.animate, mmfs[self.selectedObject].positionX.point, True, self.is_frame)
        mmfs[self.selectedObject].positionY.animate, mmfs[self.selectedObject].positionY.point = self.ui_helper.add_controls_slider_same_line('Y', 8, 1.0, -1 * gs, gs, True, mmfs[self.selectedObject].positionY.animate, mmfs[self.selectedObject].positionY.point, True, self.is_frame)
        mmfs[self.selectedObject].positionZ.animate, mmfs[self.selectedObject].positionZ.point = self.ui_helper.add_controls_slider_same_line('Z', 9, 1.0, -1 * gs, gs, True, mmfs[self.selectedObject].positionZ.animate, mmfs[self.selectedObject].positionZ.point, True, self.is_frame)
        return mmfs

    def render_displace(self, mmfs, gs):
        imgui.text_colored('Displace model', 1, 0, 0, 1)
        mmfs[self.selectedObject].displaceX.animate, mmfs[self.selectedObject].displaceX.point = self.ui_helper.add_controls_slider_same_line('X', 10, 1.0, -1 * gs, gs, True, mmfs[self.selectedObject].displaceX.animate, mmfs[self.selectedObject].displaceX.point, True, self.is_frame)
        mmfs[self.selectedObject].displaceY.animate, mmfs[self.selectedObject].displaceY.point = self.ui_helper.add_controls_slider_same_line('Y', 11, 1.0, -1 * gs, gs, True, mmfs[self.selectedObject].displaceY.animate, mmfs[self.selectedObject].displaceY.point, True, self.is_frame)
        mmfs[self.selectedObject].displaceZ.animate, mmfs[self.selectedObject].displaceZ.point = self.ui_helper.add_controls_slider_same_line('Z', 12, 1.0, -1 * gs, gs, True, mmfs[self.selectedObject].displaceZ.animate, mmfs[self.selectedObject].displaceZ.point, True, self.is_frame)
        return mmfs

    def render_material(self, mmfs):
        imgui.text_colored('Material of the model', 1, 0, 0, 1)
        # TODO: material editor
        _, mmfs[self.selectedObject].Setting_ParallaxMapping = imgui.checkbox('Parallax Mapping', mmfs[self.selectedObject].Setting_ParallaxMapping)
        imgui.separator()
        _, mmfs[self.selectedObject].Setting_UseTessellation = imgui.checkbox('Use Tessellation', mmfs[self.selectedObject].Setting_UseTessellation)
        if mmfs[self.selectedObject].Setting_UseTessellation:
            _, mmfs[self.selectedObject].Setting_UseCullFace = imgui.checkbox('Culling', mmfs[self.selectedObject].Setting_UseCullFace)
            mmfs[self.selectedObject].Setting_TessellationSubdivision = self.ui_helper.add_int_slider_control('Subdivision', 24, 0, 100, mmfs[self.selectedObject].Setting_TessellationSubdivision)
            imgui.separator()
            if mmfs[self.selectedObject].mesh_model.ModelMaterial.texture_displacement.UseTexture:
                mmfs[self.selectedObject].displacementHeightScale.animate, mmfs[self.selectedObject].displacementHeightScale.point = self.ui_helper.add_slider('Displacement', 15, 0.05, -2.0, 2.0, True, mmfs[self.selectedObject].displacementHeightScale.animate, mmfs[self.selectedObject].displacementHeightScale.point, False, self.is_frame)
                imgui.separator()
        else:
            imgui.separator()
        imgui.text('Refraction')
        mmfs[self.selectedObject].Setting_MaterialRefraction.animate, mmfs[self.selectedObject].Setting_MaterialRefraction.point = self.ui_helper.add_controls_slider_same_line('', 13, 0.05, -10, 10, True, mmfs[self.selectedObject].Setting_MaterialRefraction.animate, mmfs[self.selectedObject].Setting_MaterialRefraction.point, True, self.is_frame)
        imgui.text('Specular Exponent')
        mmfs[self.selectedObject].Setting_MaterialSpecularExp.animate, mmfs[self.selectedObject].Setting_MaterialSpecularExp.point = self.ui_helper.add_controls_slider_same_line('', 14, 10, 0, 1000, True, mmfs[self.selectedObject].Setting_MaterialSpecularExp.animate, mmfs[self.selectedObject].Setting_MaterialSpecularExp.point, True, self.is_frame)
        imgui.separator()
        mmfs[self.selectedObject].materialAmbient.color, mmfs[self.selectedObject].materialAmbient.colorPickerOpen = self.ui_helper.add_color3('Ambient Color', mmfs[self.selectedObject].materialAmbient.color, mmfs[self.selectedObject].materialAmbient.colorPickerOpen)
        mmfs[self.selectedObject].materialDiffuse.color, mmfs[self.selectedObject].materialDiffuse.colorPickerOpen = self.ui_helper.add_color3('Diffuse Color', mmfs[self.selectedObject].materialDiffuse.color, mmfs[self.selectedObject].materialDiffuse.colorPickerOpen)
        mmfs[self.selectedObject].materialSpecular.color, mmfs[self.selectedObject].materialSpecular.colorPickerOpen = self.ui_helper.add_color3('Specular Color', mmfs[self.selectedObject].materialSpecular.color, mmfs[self.selectedObject].materialSpecular.colorPickerOpen)
        mmfs[self.selectedObject].materialEmission.color, mmfs[self.selectedObject].materialEmission.colorPickerOpen = self.ui_helper.add_color3('Emission Color', mmfs[self.selectedObject].materialEmission.color, mmfs[self.selectedObject].materialEmission.colorPickerOpen)
        return mmfs

    def render_effects(self, mmfs):
        opened_gb, _ = imgui.collapsing_header('Gaussian Blur')
        if opened_gb:
            imgui.indent()
            imgui.begin_group()
            gb_items = ['No Blur', 'Horizontal', 'Vertical']
            _, mmfs[self.selectedObject].Effect_GBlur_Mode = imgui.combo("Mode##228", mmfs[self.selectedObject].Effect_GBlur_Mode, gb_items)
            mmfs[self.selectedObject].Effect_GBlur_Radius.animate, mmfs[self.selectedObject].Effect_GBlur_Radius.point = self.ui_helper.add_controls_slider_same_line('Radius', 16, 0.0, 0.0, 1000.0, True, mmfs[self.selectedObject].Effect_GBlur_Radius.animate, mmfs[self.selectedObject].Effect_GBlur_Radius.point, True, self.is_frame)
            mmfs[self.selectedObject].Effect_GBlur_Width.animate, mmfs[self.selectedObject].Effect_GBlur_Width.point = self.ui_helper.add_controls_slider_same_line('Radius', 17, 0.0, 0.0, 1000.0, True, mmfs[self.selectedObject].Effect_GBlur_Width.animate, mmfs[self.selectedObject].Effect_GBlur_Width.point, True, self.is_frame)
            imgui.end_group()
            imgui.unindent()
        opened_ftm, _ = imgui.collapsing_header('Filmic Tone Mapping')
        if opened_ftm:
            imgui.indent()
            imgui.begin_group()
            _, mmfs[self.selectedObject].Effect_ToneMapping_ACESFilmRec2020 = imgui.checkbox('ACES Film Rec2020', mmfs[self.selectedObject].Effect_ToneMapping_ACESFilmRec2020)
            imgui.end_group()
            imgui.unindent()
        return mmfs

    def render_illumination_type(self, mmfs):
        imgui.text('Illumination type')
        ilt_items = [
            '[0] Color on and Ambient off',
            '[1] Color on and Ambient on',
            '[2] Highlight on',
            '[3] Reflection on and Raytrace on',
            '[4] Transparency: Glass on\n    Reflection: Raytrace on',
            '[5] Reflection: Fresnel on\n    Raytrace on',
            '[6] Transparency: Refraction on\n    Reflection: Fresnel off\n    Raytrace on',
            '[7] Transparency: Refraction on\n    Reflection: Fresnel on\n    Raytrace on',
            '[8] Reflection on\n    Raytrace off',
            '[9] Transparency: Glass on\n    Reflection: Raytrace off',
            '[10] Casts shadows onto invisible surfaces'
        ]
        _, mmfs[self.selectedObject].materialIlluminationModel = imgui.combo("", mmfs[self.selectedObject].materialIlluminationModel, ilt_items)
        return mmfs

    def show_texture_line(self, chkLabel, meshModelFaces, texType, showWindow, loadTexture):
        mmf = meshModelFaces[self.selectedObject]
        title = ''
        useTexture = False
        image = ''

        if texType == MaterialTextureType.MaterialTextureType_Ambient:
            title = 'Ambient'
            useTexture = mmf.mesh_model.ModelMaterial.texture_ambient.UseTexture
            image = mmf.mesh_model.ModelMaterial.texture_ambient.Image
        elif texType == MaterialTextureType.MaterialTextureType_Diffuse:
            title = 'Diffuse'
            useTexture = mmf.mesh_model.ModelMaterial.texture_diffuse.UseTexture
            image = mmf.mesh_model.ModelMaterial.texture_diffuse.Image
        elif texType == MaterialTextureType.MaterialTextureType_Dissolve:
            title = 'Dissolve'
            useTexture = mmf.mesh_model.ModelMaterial.texture_dissolve.UseTexture
            image = mmf.mesh_model.ModelMaterial.texture_dissolve.Image
        elif texType == MaterialTextureType.MaterialTextureType_Bump:
            title = 'Normal'
            useTexture = mmf.mesh_model.ModelMaterial.texture_normal.UseTexture
            image = mmf.mesh_model.ModelMaterial.texture_normal.Image
        elif texType == MaterialTextureType.MaterialTextureType_Specular:
            title = 'Specular'
            useTexture = mmf.mesh_model.ModelMaterial.texture_specular.UseTexture
            image = mmf.mesh_model.ModelMaterial.texture_specular.Image
        elif texType == MaterialTextureType.MaterialTextureType_SpecularExp:
            title = 'Specular Exp'
            useTexture = mmf.mesh_model.ModelMaterial.texture_specular_exp.UseTexture
            image = mmf.mesh_model.ModelMaterial.texture_specular_exp.Image
        elif texType == MaterialTextureType.MaterialTextureType_Displacement:
            title = 'Displacement'
            useTexture = mmf.mesh_model.ModelMaterial.texture_displacement.UseTexture
            image = mmf.mesh_model.ModelMaterial.texture_displacement.Image

        if image != '':
            _, useTexture = imgui.checkbox(chkLabel, useTexture)
            if imgui.is_item_hovered():
                imgui.set_tooltip('Show/Hide ' + title + ' Texture')
            if texType == MaterialTextureType.MaterialTextureType_Ambient:
                meshModelFaces[self.selectedObject].mesh_model.ModelMaterial.texture_ambient.UseTexture = useTexture
            elif texType == MaterialTextureType.MaterialTextureType_Diffuse:
                meshModelFaces[self.selectedObject].mesh_model.ModelMaterial.texture_diffuse.UseTexture = useTexture
            elif texType == MaterialTextureType.MaterialTextureType_Dissolve:
                meshModelFaces[self.selectedObject].mesh_model.ModelMaterial.texture_dissolve.UseTexture = useTexture
            elif texType == MaterialTextureType.MaterialTextureType_Bump:
                meshModelFaces[self.selectedObject].mesh_model.ModelMaterial.texture_normal.UseTexture = useTexture
            elif texType == MaterialTextureType.MaterialTextureType_Specular:
                meshModelFaces[self.selectedObject].mesh_model.ModelMaterial.texture_specular.UseTexture = useTexture
            elif texType == MaterialTextureType.MaterialTextureType_SpecularExp:
                meshModelFaces[self.selectedObject].mesh_model.ModelMaterial.texture_specular_exp.UseTexture = useTexture
            elif texType == MaterialTextureType.MaterialTextureType_Displacement:
                meshModelFaces[self.selectedObject].mesh_model.ModelMaterial.texture_displacement.UseTexture = useTexture
            imgui.same_line()
            if imgui.button('X' + chkLabel):
                loadTexture = False
                if texType == MaterialTextureType.MaterialTextureType_Ambient:
                    meshModelFaces[self.selectedObject].mesh_model.ModelMaterial.texture_ambient.UseTexture = False
                elif texType == MaterialTextureType.MaterialTextureType_Diffuse:
                    meshModelFaces[self.selectedObject].mesh_model.ModelMaterial.texture_diffuse.UseTexture = False
                elif texType == MaterialTextureType.MaterialTextureType_Dissolve:
                    meshModelFaces[self.selectedObject].mesh_model.ModelMaterial.texture_dissolve.UseTexture = False
                elif texType == MaterialTextureType.MaterialTextureType_Bump:
                    meshModelFaces[self.selectedObject].mesh_model.ModelMaterial.texture_normal.UseTexture = False
                elif texType == MaterialTextureType.MaterialTextureType_Specular:
                    meshModelFaces[self.selectedObject].mesh_model.ModelMaterial.texture_specular.UseTexture = False
                elif texType == MaterialTextureType.MaterialTextureType_SpecularExp:
                    meshModelFaces[self.selectedObject].mesh_model.ModelMaterial.texture_specular_exp.UseTexture = False
                elif texType == MaterialTextureType.MaterialTextureType_Displacement:
                    meshModelFaces[self.selectedObject].mesh_model.ModelMaterial.texture_displacement.UseTexture = False
            imgui.same_line()
            if imgui.button('V' + chkLabel):
                showWindow = not showWindow
                loadTexture = True
            imgui.same_line()
            if imgui.button('E' + chkLabel):
                # TODO: show UV editor
                pass
            imgui.same_line()
            k = image.rfind('/')
            if k == 0:
                tex_image = image
            else:
                tex_image = image[k + 1:]
            imgui.text(title + ': ' + tex_image)
        else:
            btnLabel = 'Add Texture ' + title
            if imgui.button(btnLabel, -1, 0):
                # TODO: show UV editor
                pass

        return meshModelFaces, showWindow, loadTexture

    def show_texture_image(self, mmf, texType, title, showWindow, genTexture, vboBuffer, width, height):
        wWidth = Settings.AppWindowWidth
        wHeight = Settings.AppWindowHeight
        img = ''
        if texType == MaterialTextureType.MaterialTextureType_Ambient:
            img = mmf.mesh_model.ModelMaterial.texture_ambient.Image
        elif texType == MaterialTextureType.MaterialTextureType_Diffuse:
            img = mmf.mesh_model.ModelMaterial.texture_diffuse.Image
        elif texType == MaterialTextureType.MaterialTextureType_Dissolve:
            img = mmf.mesh_model.ModelMaterial.texture_dissolve.Image
        elif texType == MaterialTextureType.MaterialTextureType_Bump:
            img = mmf.mesh_model.ModelMaterial.texture_normal.Image
        elif texType == MaterialTextureType.MaterialTextureType_Displacement:
            img = mmf.mesh_model.ModelMaterial.texture_displacement.Image
        elif texType == MaterialTextureType.MaterialTextureType_Specular:
            img = mmf.mesh_model.ModelMaterial.texture_specular.Image
        elif texType == MaterialTextureType.MaterialTextureType_SpecularExp:
            img = mmf.mesh_model.ModelMaterial.texture_specular_exp.Image

        if genTexture:
            vboBuffer, width, height = self.create_texture_buffer(img, vboBuffer, width, height)

        tWidth = width + 20
        if tWidth > wWidth:
            tWidth = wWidth - 20
        tHeight = height + 20
        if tHeight > wHeight:
            tHeight = wHeight - 40

        imgui.set_next_window_position(20, 30, imgui.FIRST_USE_EVER)
        imgui.set_next_window_size(tWidth, tHeight, imgui.FIRST_USE_EVER)

        title = title + ' Texture'
        imgui.begin(title, showWindow, imgui.WINDOW_HORIZONTAL_SCROLLING_BAR)

        imgui.text('Image: ' + img)
        imgui.text('Image Dimensions: ' + str(width) + ' x ' + str(height))
        imgui.separator()
        imgui.image(vboBuffer, width, height)

        imgui.end()

        genTexture = False

        return showWindow, genTexture, vboBuffer, width, height

    def create_texture_buffer(self, imageFile, vboBuffer, width, height):
        if not os.path.exists(imageFile):
            imageFile = Settings.Settings_CurrentFolder + '/' + imageFile

        texture_image = Image.open(imageFile, 'r')
        texture_image_data = numpy.array(list(texture_image.getdata()), numpy.uint8)
        width = texture_image.width
        height = texture_image.height
        vboBuffer = glGenTextures(1)
        glBindTexture(GL_TEXTURE_2D, vboBuffer)
        glPixelStorei(GL_UNPACK_ALIGNMENT, 1)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR)
        glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR)
        glGenerateMipmap(GL_TEXTURE_2D)
        if texture_image.mode == "RGBA":
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGBA, width, height, 0, GL_RGBA, GL_UNSIGNED_BYTE, texture_image_data)
        elif texture_image.mode == "RGB":
            glTexImage2D(GL_TEXTURE_2D, 0, GL_RGB, width, height, 0, GL_RGB, GL_UNSIGNED_BYTE, texture_image_data)
        texture_image.close()

        return vboBuffer, width, height


#! /usr/bin/env python

def max_pieces(k):
    horizontal = int(k / 2)
    vertical = k - horizontal
    return horizontal * vertical

if __name__ == '__main__':
    t = int(input())
    for _ in range(t):
        print(max_pieces(int(input())))


class Solution(object):
    def plusOne(self, digits):
        """
        :type digits: List[int]
        :rtype: List[int]
        """
        if not len(digits):
            digits.append(1)
            return digits
        else:
            ans = ""
            for i in digits:
                ans+=str(i)
            return list(str(int(ans)+1))


class Reimbursements:
    def __init__(self, transaction_id: int, employee_id: int,
                 reimbursement_amount: int, expense_reason: str, status: str, manager_comment: str,
                 date: str):
        self.transaction_id = transaction_id
        self.employee_id = employee_id
        self.reimbursement_amount = reimbursement_amount
        self.expense_reason = expense_reason
        self.status = status
        self.manager_comment = manager_comment
        self.date = date

    def __str__(self):
        return "transactionId {}," "employeeId {}," \
               "reimbursementAmount {}," \
               "expenseReason {}," "status {}," \
               "managerComment {}""date {}," \
            .format(self.transaction_id, self.employee_id,
                    self.reimbursement_amount,
                    self.expense_reason, self.status,
                    self.date, self.manager_comment)

    def make_reimbursement_dictionary(self):
        return {
            "transactionId": self.transaction_id,
            "employeeId": self.employee_id,
            "reimbursementAmount": self.reimbursement_amount,
            "expenseReason": self.expense_reason,
            "status": self.status,
            "managerComment": self.manager_comment,
            "date": self.date
        }


"""
    Cant figure out how to est that far out will come back
"""
import time
def main():
    start = time.time()
    print(champernowneConstant())
    print(time.time() - start)

def champernowneConstant():
    constant = 0.123456789
    mul = pow(10,-9)
    div = 991 / 9801
    return ('%.80f' % (constant + mul  * div))

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


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

"""Manage AWS S3 Buckets."""

# pylint: disable=invalid-name,dangerous-default-value

from typing import Dict

import boto3

def create_s3_bucket(
    s3_bucket_name: str, aws_region: str, acl: str = "public-read"
) -> Dict:
    """Create S3 bucket."""
    s3_client = boto3.client("s3", region_name=aws_region)
    bucket_creation_response = s3_client.create_bucket(
        # ACL=acl,
        Bucket=s3_bucket_name,
        CreateBucketConfiguration={"LocationConstraint": aws_region},
    )
    return bucket_creation_response

def delete_bucket_objects(s3_bucket_name: str, region: str) -> None:
    """Delete objects in bucket."""
    s3_resource = boto3.resource("s3", region_name=region)
    s3_bucket = s3_resource.Bucket(s3_bucket_name)
    # Deleting objects
    for s3_object in s3_bucket.objects.all():
        s3_object.delete()
    # Deleting objects versions if S3 versioning enabled
    for s3_object_ver in s3_bucket.object_versions.all():
        s3_object_ver.delete()
    print(f"Bucket {s3_bucket_name} has been cleaned up")

def delete_s3_bucket(s3_bucket_name: str, aws_region: str) -> Dict:
    """Delete S3 bucket."""
    s3_client = boto3.client("s3", region_name=aws_region)
    delete_bucket_objects(s3_bucket_name, aws_region)
    bucket_delete_response = s3_client.delete_bucket(Bucket=s3_bucket_name)
    print(f"Bucket {s3_bucket_name} has been deleted")
    return bucket_delete_response

def check_s3_bucket_deletion(s3_bucket_name: str, aws_region: str):
    """Verify that S3 bucket is deleted."""
    s3_client = boto3.client("s3", region_name=aws_region)
    buckets_list_response = s3_client.list_buckets()
    # print(buckets_list_response["Buckets"])
    if buckets_list_response:
        assert s3_bucket_name not in buckets_list_response["Buckets"]
    else:
        assert not buckets_list_response


# Origin of the method below somewhat dubious. Believed to be in the public domain. - AC
# http://gamedev.stackexchange.com/questions/20881/handling-random-with-unique-chance-in-python
# http://eli.thegreenplace.net/2010/01/22/weighted-random-generation-in-python/
# http://stackoverflow.com/questions/4113307/pythonic-way-to-select-list-elements-with-different-probability

import random
import bisect

# Returns a random value, considering the weights of each item.
class WeightedChoice(object):
    def __init__(self, weights):
        self.totals = []
        self.weights = weights
        running_total = 0

        for w in weights:
            running_total += w[1]
            self.totals.append(running_total)

    def next(self):
        rnd = random.random() * self.totals[-1]
        i = bisect.bisect_right(self.totals, rnd)
        return self.weights[i][0]