# Reconstructing atmospheric O2 using artifical neural network with global magic igneous geochemical data
# No labels during Boring billion
# initiated by Guoxiong Chen, 2020,2,12
# updated 2020,1,10

import matplotlib.pyplot as plt
import numpy as np
import pandas as pd
import math
from sklearn.model_selection import KFold
from sklearn.model_selection import GridSearchCV
from mpl_toolkits.axes_grid1 import make_axes_locatable
from sklearn.utils import shuffle
from sklearn.metrics import r2_score
from sklearn.model_selection import ParameterGrid
from sklearn.model_selection import train_test_split
from scipy.interpolate import make_interp_spline
from sklearn.neural_network import MLPRegressor
from sklearn.metrics import mean_squared_error,r2_score

def train(file_path,models,epochs):

    data=pd.read_excel(file_path,'Sheet1',index_col='Time')
    data=data.apply(pd.to_numeric, errors='coerce')

    predic=data.loc[:,'SIO2':'CS'].values  # input data for prediction
    ### data nomalization
    predic=(predic-np.min(predic,axis=0))/(np.max(predic,axis=0)-np.min(predic,axis=0))
    #predic=np.log(predic-np.min(predic,axis=0)+[[1] * 45 for _ in range(79)])
    data.loc[:,'SIO2':'CS']=predic
    final = data.index

#     Loss = np.zeros(shape=(models,epochs))
    pre_fit = np.zeros(shape=(models,len(final)))
    Loss = pd.DataFrame()
    r2 = []
    for k in range(models):
        ## training data preparation
        time_index=[(0,500),(2500,3850)]
        s1 = np.random.randint(6,8,1)
        s2 = np.random.randint(10,20,1)
        sample=[s1,s2]
        O2=[0,-7]
        train_data=pd.DataFrame()
        for i in range(2):
            # random sampling
            train_data1=data.iloc[(data.index>time_index[i][0])&(data.index<time_index[i][1]),:].sample(n=sample[i])
            train_data1['O2']=O2[i]
            train_data=pd.concat([train_data,train_data1])
        #noise=np.random.randint(1,10,len(train_data['O2']))*0.2-1
        noise1 = np.random.randint(0, 10, s1) * 0.08 - 0.6 # 0-500 Ma, 20% O2, (1) 0.08 - 0.6; (2) 0.04 - 0.3; (3) 0.13 - 1
        noise2 = np.random.randint(0, 10, s2) * 0.2 - 1    # 2500-4000 Ma,(1) 0.2-1; (2) 0.1 - 0.5 ；(3) 0.4 - 2
        noise = np.hstack((noise1, noise2))
        datay=train_data['O2']+noise # add uncertainty
        datax=train_data.loc[:,'SIO2':'CS']

        kl=KFold(n_splits=5)
        pre_fiti = pd.DataFrame()
        true_y = pd.DataFrame()
        for x,y in  kl.split(datax):
            train_x,valid_x=datax.values[x,:],datax.values[y,:]
            train_y,valid_y=datay.values[x],datay.values[y]
            # building the network of three layers (128,64,32)
            mlp = MLPRegressor(hidden_layer_sizes = (256,128,64,32),activation='tanh',
                               solver='adam',alpha=0.0001,max_iter=epochs,
                               random_state=2022,early_stopping=False,tol=0.0001)
            mlp.fit(train_x,train_y)
            # test dataset R2
            pre_fit_y_valid = pd.DataFrame(mlp.predict(valid_x))

            pre_fiti = pre_fiti.append(pre_fit_y_valid)
            true_y = true_y.append(pd.DataFrame(valid_y))

        valid_r2 =  r2_score(true_y,pre_fiti)
        print("number of models",k,"testd_r2=",valid_r2)

        r2.append(valid_r2)
        pre_fitx = mlp.predict(predic)
        pre_fit[k] = pre_fitx
        loss = np.array(mlp.loss_curve_)
        loss = pd.DataFrame(loss)
        Loss = Loss.append(loss.T)

    r2 = np.array(r2)
    r2[r2<0]=0
    valid_r2_mean = np.mean(np.array(r2))
    print("mean r2",valid_r2_mean)
    return Loss,pre_fit,final

def plot(final,pre_fit):

    final = pd.DataFrame(final)
    pre_fit = pd.DataFrame(pre_fit)
    final_data = pd.concat([final,pre_fit.T],axis=1)
    final_res = final_data.set_index('Time')
    final_mean=np.mean(final_res,axis=1)
    final_std=np.std(final_res,axis=1)
    final_res['mean']=final_mean
    final_res['std']=final_std

    figure2=plt.figure(2,figsize=(9, 4))

    xnew = np.linspace(final_mean.index.min(), final_mean.index.max(), 300)  # 300 represents number of points to make between T.min and T.max

    power_smooth = make_interp_spline(final_mean.index, final_mean.values)(xnew)
    plt.plot(xnew,power_smooth,'b-', linewidth=1.5)
    plt.errorbar(final_mean.index,final_mean.values,final_std.values,fmt='ro',
                ecolor='lightskyblue',
                elinewidth = 10,
                ms=3,
                mfc='red',
                mec='red')
    plt.xticks(fontsize=12)
    plt.yticks(fontsize=12)
    plt.xlabel('Age (Ma)',fontsize=12)
    plt.ylabel('$\mathregular{Log_{10}}$ ($\mathregular{O_2}$) PAL',fontsize=12)
    plt.xlim(0, 4000)
    plt.ylim(-8.5, 0.5)
    plt.savefig('MLP.jpg',dpi=300)
    plt.show()

def loss_plot(Loss):
    Loss_res = pd.DataFrame(Loss.T)
    loss_mean=np.mean(Loss_res,axis=1)
    loss_std=np.std(Loss_res,axis=1)
    Loss_res['mean']=loss_mean
    Loss_res['std']=loss_std
#     print(Loss_res)

    figure=plt.figure(2,figsize=(9, 4))

    xnew = np.linspace(loss_mean.index.min(), loss_mean.index.max(), 100)  # 300 represents number of points to make between T.min and T.max

    power_smooth = make_interp_spline(loss_mean.index, loss_mean.values)(xnew)
    plt.plot(xnew,power_smooth,'b-', linewidth=1.5)
    plt.errorbar(loss_mean.index,loss_mean.values,loss_std.values,fmt='ro',
                ecolor='lightskyblue',
                elinewidth = 10,
                ms=3,
                mfc='red',
                mec='red')
    plt.xticks(fontsize=12)
    plt.yticks(fontsize=12)
    plt.xlabel('Epochs',fontsize=12)
    plt.ylabel('Loss',fontsize=12)
    plt.xlim(0, Loss_res.shape[0])
    plt.savefig('Loss.jpg',dpi=300)
    plt.show()

models = 100
epochs = 500
file_path = 'D:\\Pycharm\\DeeptimeML\\Ign\\data\\Data source\\New_ign1_mafic_ts_final.xlsx'
Loss,pre_fit,final = train(file_path,models,epochs)
plot(final,pre_fit)
loss_plot(Loss)


import os

import discord
import random
import re

#To-Do
# 1. Bot commands (?)

#Text channel ids in the AECES Discord
text_channels = {
    "intros" : 760703291892957215,
    "welcome" : 760697489711693880,
    "announce" : 760702549643755530,
    "rules" : 760698388001325067,
    "roles" : 760698326386999296
}

#Mappings for roles
mapping = {
    763466119990083595:{
        "🌱" : 763462230540812298,
        "🍦" : 763462194473074718,
        "🥲" : 763462159534653451,
        "🧟♂" : 763462130317131846,
        "👨🎓" : 763461855578161192,
        "👴" : 763462275277127682
    },
    763598798776827904:{
        '⚽': 763595482429653043,
        '🎮': 763595543602921512,
        '📱': 763595591531102218,
        '🔨' : 763598078258315275
    }
}

#Batch roles message
batch_roles_id = 763466119990083595

#Set Discord intents
intents = discord.Intents.default()
intents.members = True
intents.reactions = True

#Get environment variables
def get_tokens():
    load_dotenv()
    TOKEN = os.getenv('DISCORD_TOKEN')
    return TOKEN

#Run bot and verify if connected to AECES server
def run_bot():
    client = discord.Client(intents = intents)
    TOKEN = get_tokens()
    GUILD = "AECES"

    @client.event
    async def on_ready():
        guild = discord.utils.get(client.guilds, name=GUILD)

        print(
            f'{client.user} is connected to the following guild:\n'
            f'{guild.name}(id: {guild.id})'
        )

        channel = client.get_channel(text_channels["roles"])
        #RULES Message
        #groovy = client.get_user(234395307759108106)
        # await channel.send(f"**1. First of all, kindly change your nickname!**\n To do this right click on your profile at the right side and click on 'Change Nickname' OR click the arrow beside the server name on the top left of your screen and click on 'Change Nickname'. Follow the format [Nickname || Yr. and Course]\n\n **2. This is a safe space. Be nice and respectful.**\n Discrimination, racism, homophobia, or any other derogatory behavior will not be tolerated on this server.\n\n **3. There are different topics for each respective channel. Please post content in the correct channels.**\n {groovy.mention} is bound to #📻music , use that channel for any music requests\n\n **4. Avoid spamming the chatrooms, leave announcements and recruitments in their respective channels. Do not ping other roles for unnecessary reasons.**\n\n **5. Don't forget to constantly check out the announcements tab for upcoming AECES events or changes in the server.**")

        #ROLES Message
        # message = await channel.send("Please react to this message with the following according to your batch\n🌱 : Batch 2025\n🍦 : Batch 2024\n🥲 : Batch 2023\n🧟♂ : Batch 2022\n👨🎓 : Batch 2021\n👴 : Alumni")
        # for emoji in mapping:
        #     await message.add_reaction(emoji)

        #INTEREST ROLES Message
        # content = "Please react to this message with your interests to be able to access the relevant channels!\n⚽ : Sports\n🎮 : Video Games\n📱 : Technology\n🔨 : Opportunities"
        # message = await send_message(channel, content)
        # emojis = ['⚽', '🎮', '📱', '🔨']
        # for emoji in emojis:
        #     await message.add_reaction(emoji)

    #Message utility function
    async def send_message(channel, content):
        message = await channel.send(content)
        return message

    #Reply to messages
    @client.event
    async def on_message(message):
        if message.author == client.user:
            return

        user_message = re.findall(r'\w+', message.content.lower())
        if message.channel == client.get_channel(text_channels["intros"]): #Reply to intro channel
            greetings = ["hello", "hi"]

            for greeting in greetings:
                if greeting in user_message:
                    channel = client.get_channel(text_channels["intros"])
                    await channel.send(f"Hello, {message.author.mention}!")
                    return

        if "bong" in user_message:
            channel = message.channel
            await channel.send("Sir Bong ❤")
            #mika = client.get_user(751054032679993435)
            #await channel.send(f"{mika.mention} pls help {message.author.mention}")

        if "ohms" in user_message or "ohm" in user_message:
            channel = message.channel
            await channel.send("V = IR")

        if "papasa" in user_message:
            channel = message.channel
            await channel.send("Syempre papasa!!")
            return

        if "shift" in user_message:
            channel = message.channel
            await channel.send("ECCE :heart:")
            return

        if "inom" in user_message:
            channel = message.channel
            await channel.send("Tara Pop up!")
            return

    #Welcome new members
    @client.event
    async def on_member_join(member):
        greetings = [
            "Hello {}! Welcome to the AECES Discord server!!",
            "Welcome to the AECES Discord server, {}!",
            "Hi there {}!! Welcome to the AECES Discord server!",
            "{} joined the party! Welcome to the AECES Discord server!"
        ]
        channel = client.get_channel(text_channels["welcome"])
        await channel.send(random.choice(greetings).format(member.mention))

    #Role assignment
    @client.event
    async def on_raw_reaction_add(payload):
        await manage_roles(payload, True)

    @client.event
    async def on_raw_reaction_remove(payload):
        await manage_roles(payload, False)

    async def manage_roles(payload, add_role: bool):

        if not payload.message_id in mapping:
            print("returned on message id")
            return

        if not str(payload.emoji) in mapping[payload.message_id]:
            print("returned on mapping")
            return

        role_emoji = mapping[payload.message_id][str(payload.emoji)]
        role = discord.utils.get(client.get_guild(payload.guild_id).roles, id=role_emoji)
        member = discord.utils.get(client.get_guild(payload.guild_id).members, id=payload.user_id)

        if add_role:
            await payload.member.add_roles(role)
            msg = f"You have given yourself the **{role.name}** role on the **{role.guild} discord server**!"
            await payload.member.send(content = msg)

        else:
            await member.remove_roles(role)

    client.run(TOKEN)

run_bot()


from datetime import datetime, timedelta

from airflow import DAG
from airflow.operators.bash import BashOperator

dag_args = {
    'owner': 'safarnejad',
    'retries': 1,
    'retry_delay': timedelta(minutes=2),
}

with DAG(
    dag_id='catchup_and_backfill_dag',
    description='this is my first dag',
    start_date=datetime(2023, 10, 1),
    default_args=dag_args,
    schedule_interval='@daily',
    catchup=False  # Older tasks also should be run
) as dag:

    task_a = BashOperator(
        task_id='task_a',
        bash_command="echo Hello World.",
        dag=dag
    )

'''
    If we set catchup = False
    then we have to run
    ```
        airflow dags backfill -s 2023-10-1 -e 2023-11-5 \
            catchup_and_backfill_dag
    ```
    to run previous tasks.
'''


from hangman_art import logo, stages, won_display
from word_bank import word_list
import random
import os

print(logo)
secret_word = random.choice(word_list)
# print(secret_word)

display = []

for i in range(len(secret_word)):
    display.append('_')

print(display)

def start_new_game():
    print(logo)
    display = []
    secret_word = random.choice(word_list)
    print(secret_word)
    for i in range(len(secret_word)):
        display.append('_')
    return display, secret_word

game_on = True
lives = 6
guesses = []
def hangman(game_on, lives, secret_word, display, guesses):
    while game_on:
        user_guess = input("\nGuess a letter: ").lower()

        for letter_index in range(len(secret_word)):
            if user_guess == secret_word[letter_index]:
                display[letter_index] = user_guess
        os.system('cls')

        if user_guess not in secret_word and user_guess not in guesses:
            lives -= 1
        if lives == 0:
            os.system('cls')
            print(f'You Lose! \n The word was {secret_word}')
            continue_playing = input('Play again? (Yes/no) ')
            if continue_playing.lower() == 'yes':
                os.system('cls')
                # start_new_game()
                # print(logo)
                display = []
                lives = 6
                guesses = []
                secret_word = random.choice(word_list)
                # print(secret_word)
                for i in range(len(secret_word)):
                    display.append('_')
                game_on = True
            else:
                game_on = False
                os.system('cls')
                print('Thanks for playing. Bye!')
                return None

        print(logo)
        print(stages[lives])
        if user_guess in guesses:
            print(f"You already guessed {user_guess}\n")
        guesses.append(user_guess)
        print(display)
        if "_" not in display:
            os.system('cls')
            print(won_display)
            continue_playing = input('Play again? (Yes/no) ')
            if continue_playing.lower() == 'yes':
                os.system('cls')
                # start_new_game()
                print(logo)
                display = []
                lives = 6
                guesses = []
                secret_word = random.choice(word_list)
                # print(secret_word)
                print(stages[lives])
                for i in range(len(secret_word)):
                    display.append('_')
                game_on = True

            else:
                game_on = False
                os.system('cls')
                print('Thanks for playing. Bye!')
                return None

        print("\nPress Ctrl-C to stop playing...")

hangman(game_on, lives, secret_word, display, guesses)


import matplotlib.pyplot as plt
import numpy as np
import os
import PIL
import tensorflow as tf
from tensorflow import keras
from tensorflow.keras import layers
from tensorflow.keras.models import Sequential
from tensorflow.keras.applications.resnet50 import ResNet50

import pathlib
data_dir = pathlib.Path("presivir/Games by Gameness")

batch_size = 32
img_height = 272
img_width = 480

train_ds = tf.keras.preprocessing.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="training",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)

val_ds = tf.keras.preprocessing.image_dataset_from_directory(
  data_dir,
  validation_split=0.2,
  subset="validation",
  seed=123,
  image_size=(img_height, img_width),
  batch_size=batch_size)

class_names = train_ds.class_names
print(class_names)

size = (136, 240)

train_ds = train_ds.map(lambda x, y: (tf.image.resize(x, size), y))
val_ds = val_ds.map(lambda x, y: (tf.image.resize(x, size), y))

input_shape = (136, 240, 3)

base_model = ResNet50(weights='imagenet', input_shape=input_shape, include_top=False)
base_model.trainable = False

inputs = keras.Input(shape=input_shape)
x = base_model(inputs, training=False)
x = keras.layers.GlobalAveragePooling2D()(x)
x = keras.layers.Dropout(0.2)(x)
x = keras.layers.Dense(1)(x)
outputs = keras.activations.sigmoid(x)
model = keras.Model(inputs, outputs)

model.compile(optimizer = keras.optimizers.Adam(lr=0.0001),
              loss=tf.keras.losses.BinaryCrossentropy(from_logits=False),
              metrics=[keras.metrics.BinaryAccuracy(name='accuracy'),
                      keras.metrics.Precision(),
                      keras.metrics.Recall()])

model.summary()
print(model.optimizer.get_config())

epochs=5

checkpoint_path = "labs/cp.ckpt"
checkpoint_dir = os.path.dirname(checkpoint_path)

# Create a callback that saves the model's weights
cp_callback = tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_path,
                                                 save_weights_only=True,
                                                 verbose=1)

history = model.fit(
  train_ds,
  validation_data=val_ds,
  callbacks=[cp_callback],
  epochs=epochs
)

acc = history.history['accuracy']
val_acc = history.history['val_accuracy']

loss = history.history['loss']
val_loss = history.history['val_loss']

epochs_range = range(epochs)

plt.figure(figsize=(8, 8))
plt.subplot(1, 2, 1)
plt.plot(epochs_range, acc, label='Training Accuracy')
plt.plot(epochs_range, val_acc, label='Validation Accuracy')
plt.legend(loc='lower right')
plt.title('Training and Validation Accuracy')

plt.subplot(1, 2, 2)
plt.plot(epochs_range, loss, label='Training Loss')
plt.plot(epochs_range, val_loss, label='Validation Loss')
plt.legend(loc='upper right')
plt.title('Training and Validation Loss')
plt.show()

model.save_weights('./labs/resnet50_' + str(epochs))

# model = Sequential([
#   layers.experimental.preprocessing.Rescaling(1./255, input_shape=(img_height, img_width, 3)),
#   layers.Conv2D(16, 3, padding='same', activation='relu'),
#   layers.MaxPooling2D(),
#   layers.Conv2D(32, 3, padding='same', activation='relu'),
#   layers.MaxPooling2D(),
#   layers.Flatten(),
#   layers.Dense(32, activation='relu'),
#   layers.Dropout(0.5),
#   layers.Dense(1, activation='sigmoid')
# ])


# Multithreading examples with queue
from threading import Thread, Lock, current_thread
from queue import Queue
# import time

# Function for "target=" in the "Thread()" function below
# The function to 'do stuff' in multiple threads
def worker(q, lock):
    while True:
        value = q.get()  # Gets blocked here when there are no items in q, q.put below puts items in

        # Processing
        with lock:
            print(f'in {current_thread().name} got {value}')
        q.task_done()

if __name__ == "__main__":  # If in the main module
    q = Queue()       # Create queue object
    lock = Lock()     # Create lock object
    num_threads = 10  # Number of threads you want

    # Create threads
    for i in range(num_threads):  # Iterate through the amount of threads you want
        # Create thread objects using function and arguments
        thread = Thread(target=worker, args=(q, lock))  # Arguments are "q" and "lock" in the form of a tuple
        # The daemon thread dies after the main thread dies. This thread starts the worker function
        thread.daemon = True  # This breaks the infinite 'while loop' in worker
        # Start the thread you just created
        thread.start()

    # Insert elements into the queue
    for i in range(1, 21):
        q.put(i)  # Will insert values 1 through 20 for each element

    # Join
    # Wait until all threads are finished while blocking the main thread
    q.join()

    print('end main')


import traceback

from slack_logger import SlackLogger

def get_traceback(e):
    tb = (
        "Traceback (most recent call last):\n"
        + "".join(traceback.format_list(traceback.extract_tb(e.__traceback__)))
        + type(e).__name__
        + ": "
        + str(e)
    )
    return tb

token = "your slack app token"
options = {
    "service_name": "Backend API",
    "service_environment": "Production",
    "default_level": "info",
}

err = KeyError("'email' field cannot be None")

logger = SlackLogger(token=token, **options)

channel = "#my_channel"
response = logger.send(
    channel=channel,
    title="Runtime Exception",
    description=err.__str__(),
    error=get_traceback(err),
    metadata={"email": None, "module": "auth", "method": "POST"},
)


import numpy as np
import matplotlib.pyplot as plt
import matplotlib.pylab as pylab
from matplotlib import rc

rc('mathtext', default='regular')
params = {'legend.fontsize': 'x-large',
          'figure.figsize': (10, 10),
         'axes.labelsize': 'x-large',
         'axes.titlesize':'x-large',
         'xtick.labelsize':'x-large',
         'ytick.labelsize':'x-large'}
pylab.rcParams.update(params)

none_train = np.load('logs/attempt12/train_history_BCE_lr0.01_sc0.001_model_BCE_50_0.0321.npy')
none_val = np.load('logs/attempt12/val_history_BCE_lr0.01_sc0.001_model_BCE_50_0.0321.npy')
none_ap = np.load('logs/attempt12/AP_history_1_50.npy')

none2_train = np.load('logs/attempt11/train_history_BCE_lr0.01_sc0.001_model_BCE_50_0.0324.npy')
none2_val = np.load('logs/attempt11/val_history_BCE_lr0.01_sc0.001_model_BCE_50_0.0324.npy')
none2_ap = np.load('logs/attempt11/AP_history_1_50.npy')

none3_train = np.load('logs/attempt13/train_history_BCE_lr0.01_sc0.001_model_BCE_50_0.0334.npy')
none3_val = np.load('logs/attempt13/val_history_BCE_lr0.01_sc0.001_model_BCE_50_0.0334.npy')
none3_ap = np.load('logs/attempt13/AP_history_1_50.npy')

fig, ax = plt.subplots(nrows=1,ncols=1,figsize=(25,15))
ax2=ax.twinx()

epoch_list = np.arange(1, 51)
xticks = np.arange(0, 51, 10)

ax.tick_params(labelsize=30)
ax2.tick_params(labelsize=30)
ax.set_xticks(xticks)
ax.set_title("Training phase", fontsize=30)
ax.set_xlabel("Epoch", fontsize=30)
ax.set_ylabel("Loss", fontsize=30)
ax2.set_ylabel("AP", fontsize=30)

ax.plot(epoch_list, none_train, linewidth=4, color='blue', linestyle=':', label="Training loss")
ax.plot(epoch_list, none_val, linewidth=4, color='blue', linestyle='--', label="Validation loss")
ax2.plot(epoch_list, none_ap, linewidth=4, color='blue', linestyle='-', label="Average Precision")

ax.plot(epoch_list, none2_train, linewidth=4, color='green', linestyle=':')
ax.plot(epoch_list, none2_val, linewidth=4, color='green', linestyle='--')
ax2.plot(epoch_list, none2_ap, linewidth=4, color='green', linestyle='-')

ax.plot(epoch_list, none3_train, linewidth=4, color='red', linestyle=':')
ax.plot(epoch_list, none3_val, linewidth=4, color='red', linestyle='--')
ax2.plot(epoch_list, none3_ap, linewidth=4, color='red', linestyle='-')

ax.legend(loc='center', bbox_to_anchor=(0.8, 0.3), fontsize=30)
ax2.legend(loc='center', bbox_to_anchor=(0.8, 0.6), fontsize=30)

plt.savefig('train_flipped_rot.png', format='png', bbox_inches='tight')


from django.urls import path
from .views import Courses, course_detail, SearchCoursesView, CoursesByCategory

urlpatterns = [
    path('courses', Courses.as_view()),
    path('courses/<category_name>', CoursesByCategory.as_view()),
    path('course/<pk>/<slug>', course_detail),
    path('search', SearchCoursesView.as_view()),

]


matriz=[[],[],[]]
pares = col3 = mai2 = 0
for l in range(0,3):
    for c in range(0,3):
        num = int(input(f'Digite o valor da [{l},{c}]: '))
        if num%2==0:
            pares+=num
        if c == 2:
            col3+=num
        if l == 1:
            if mai2 < num:
                mai2 = num
        matriz[l].append(num)
print(matriz)
print('=-'*30)
for l in range(0,3):
    for c in range(0,3):
        print(f'[{matriz[l][c]:^5}]',end='')
    print()
print('=-'*30)
print(f'A soma dos valores pares é {pares}')
print(f'A soma dos valores da terceira coluna é {col3}')
print(f'O maior valor da segunda linha é {mai2}')


from data_loader import DataLoader
from config import Config

import numpy as np
import os
import tensorflow as tf
import keras.backend as K
import keras
from keras import optimizers
from keras.engine.topology import Layer
from keras.layers import Activation, Lambda, Conv1D, SpatialDropout1D, Dense, BatchNormalization
from keras.models import Input, Model

from sklearn.metrics import confusion_matrix,classification_report
from sklearn.metrics import precision_recall_fscore_support

# Define TCN layer
class tcn_layer:
    """
        Input shape:
            A tensor of shape (batch_size, timesteps, input_dim).
        Args:
            nb_filters: The number of filters to use in the convolutional layers.
            kernel_size: The size of the kernel to use in each convolutional layer.
            dilations: The list of the dilations. Example is: [1, 2, 4, 8, 16, 32, 64].
            nb_stacks : The number of stacks of residual blocks to use.
            padding: The padding to use in the convolutional layers, 'causal' or 'same'.
            use_skip_connections: Boolean. If we want to add skip connections from input to each residual block.
            return_sequences: Boolean. Whether to return the last output in the output sequence, or the full sequence.
            activation: The activation used in the residual blocks o = Activation(x + F(x)).
            dropout_rate: Float between 0 and 1. Fraction of the input units to drop.
            kernel_initializer: Initializer for the kernel weights matrix (Conv1D).
            use_batch_norm: Whether to use batch normalization in the residual layers or not.
        Returns:
            A TCN layer.
        """

    def __init__(self,
                 nb_filters=64,
                 kernel_size=2,
                 nb_stacks=1,
                 dilations=(1, 2, 4, 8, 16, 32),
                 padding='causal',
                 use_skip_connections=True,
                 dropout_rate=0.0,
                 return_sequences=False,
                 activation='linear',
                 kernel_initializer='he_normal',
                 use_batch_norm=False):
        self.return_sequences = return_sequences
        self.dropout_rate = dropout_rate
        self.use_skip_connections = use_skip_connections
        self.dilations = dilations
        self.nb_stacks = nb_stacks
        self.kernel_size = kernel_size
        self.nb_filters = nb_filters
        self.activation = activation
        self.padding = padding
        self.kernel_initializer = kernel_initializer
        self.use_batch_norm = use_batch_norm

        if padding != 'causal' and padding != 'same':
            raise ValueError("Only 'causal' or 'same' padding are compatible for this layer.")

        if not isinstance(nb_filters, int):
            print('An interface change occurred after the version 2.1.2.')
            print('Before: tcn.TCN(x, return_sequences=False, ...)')
            print('Now should be: tcn.TCN(return_sequences=False, ...)(x)')
            print('The alternative is to downgrade to 2.1.2 (pip install keras-tcn==2.1.2).')
            raise Exception()

    def __call__(self, inputs, training=None):
        x = inputs
        # 1D FCN.
        x = Conv1D(self.nb_filters, 1, padding=self.padding, kernel_initializer=self.kernel_initializer)(x)
        skip_connections = []
        for s in range(self.nb_stacks):
            for d in self.dilations:

                # Residual block for WaveNet TCN
                prev_x = x
                for k in range(2):
                    x = Conv1D(filters=self.nb_filters,
                            kernel_size=self.kernel_size,
                            dilation_rate=d,
                            kernel_initializer=self.kernel_initializer,
                            padding=self.padding)(x)
                    if self.use_batch_norm:
                        x = BatchNormalization()(x)
                    x = Activation('relu')(x)
                    x = SpatialDropout1D(rate=self.dropout_rate)(inputs=x, training=training)

                # 1x1 conv to match the shapes (channel dimension)
                prev_x = Conv1D(self.nb_filters, 1, padding='same')(prev_x)
                skip_out = keras.layers.add([prev_x, x])
                skip_out = Activation(self.activation)(skip_out)

                skip_connections.append(skip_out)
        if self.use_skip_connections:
            x = keras.layers.add(skip_connections)
        if not self.return_sequences:
            x = Lambda(lambda tt: tt[:, -1, :])(x)
        return x

# Metrics for model training
def precision_threshold(threshold=0.5):
    def precision(y_true, y_pred):
        """
        Computes the precision over the whole batch using threshold_value.
        """
        threshold_value = threshold

        y_pred = K.cast(K.greater(K.clip(y_pred, 0, 1), threshold_value), K.floatx())
        y_true = K.cast(K.greater(K.clip(y_true, 0, 1), threshold_value), K.floatx())
        true_positives = K.round(K.sum(K.clip(y_true * y_pred, 0, 1)))

        predicted_positives = K.sum(K.cast(K.greater(K.clip(y_pred,0,1),threshold_value), K.floatx()))
        precision_ratio = true_positives / (predicted_positives + K.epsilon())
        return precision_ratio
    return precision

def recall_threshold(threshold=0.5):
    def recall(y_true, y_pred):
        """
        Computes the recall over the whole batch using threshold_value.
        """
        threshold_value = threshold

        y_pred = K.cast(K.greater(K.clip(y_pred, 0, 1), threshold_value), K.floatx())
        y_true = K.cast(K.greater(K.clip(y_true, 0, 1), threshold_value), K.floatx())
        true_positives = K.round(K.sum(K.clip(y_true * y_pred, 0, 1)))

        possible_positives = K.sum(K.cast(K.greater(K.clip(y_true,0,1),threshold_value), K.floatx()))
        recall_ratio = true_positives / (possible_positives + K.epsilon())
        return recall_ratio
    return recall

# TCN model
class TCN:

    # Load weight from pre-trained model
    def load_weight(self, filepath):
        self.m.load_weights(filepath)

    # Compile model
    def compile(self):
        batch_size, timesteps, input_dim = None, 6, 70

        i = Input(batch_shape=(batch_size, timesteps, input_dim))
        o = tcn_layer(nb_filters=128,
                      kernel_size=4,
                      dilations=(1,2,4,8,16,32,64),
                      padding='causal',
                      dropout_rate=0.01,
                      return_sequences=False,
                      kernel_initializer='he_normal',
                      use_batch_norm=True)(i)
        o = Dense(1)(o)

        self.m = Model(inputs=[i], outputs=[o])
        self.m.compile(optimizer='adam',loss='hinge', metrics=['accuracy',precision_threshold(0),recall_threshold(0)])

    # Helper function
    # The output should be in the form of 1 and -1 given the hinge loss function
    def reshape(self, y_train):
        for i in range(y_train.shape[0]):
            if y_train[i] == 0:
                y_train[i] = -1
        return y_train

    # Train model
    def train(self, X_train, y_train):
        self.num_epochs = 1
        y_train = self.reshape(y_train)

        # Directory where the checkpoints will be saved
        checkpoint_dir = '/Users/zhiyun/Desktop/Fall19-20/TEMG4000/startup_prediction/src/model'
        checkpoint_prefix = os.path.join(checkpoint_dir, "ckpt_1")

        checkpoint_callback=tf.keras.callbacks.ModelCheckpoint(filepath=checkpoint_prefix,
                                                               save_weights_only=True,
                                                               save_freq=1024)

        self.history = self.m.fit(X_train, y_train, epochs=self.num_epochs, validation_split=0.25, callbacks=[checkpoint_callback])

    # Predict test data
    def predict(self, X_test):
        return self.m.predict(X_test)

    # Evaluate model performance with metrics
    def evaluate(self, y_pred, y_test):
        y_pred_rounded = np.clip(y_pred, 0, 1)
        for i in range(y_pred_rounded.shape[0]):
            if y_pred_rounded[i] > 0:
                y_pred_rounded[i] = 1

        precision, recall, f1, _ = precision_recall_fscore_support(y_test, y_pred_rounded)
        print('Precision:', precision.mean())
        print('Recall:', recall.mean())
        print('f1-score:', f1.mean())

        print('Classification report:')
        print(classification_report(y_test, y_pred_rounded))

        print('Confusion matrix:')
        print(confusion_matrix(y_test, y_pred_rounded))

    # Save model
    def save_model(self):
        self.m.save('src/model/tcn.hdf5')

if __name__ == "__main__":
    config = Config()
    d = DataLoader(config)
    X_train, y_train = d.get_batch_train()
    X_test, y_test = d.get_batch_test()
    model = TCN()
    model.compile()
    model.train(X_train, y_train)
    y_pred = model.predict(X_test)
    model.evaluate(y_pred, y_test)
    model.save_model()


import cv2
import numpy as np

cap = cv2.VideoCapture(-1)

while(True):
    ret, frame = cap.read()

    # Convert to grayscale
    gray = cv2.cvtColor(frame, cv2.COLOR_BGR2GRAY)

    # Find edges using Canny
    edges = cv2.Canny(gray, 100, 200)

    # Find contours of hand
    contours, hierarchy = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)
    contours = max(contours, key=cv2.contourArea)

    # Draw contour on frame
    cv2.drawContours(frame, [contours], -1, (0, 255, 0), 2)

    # Define color ranges to detect
    lower_blue = np.array([100, 0, 0])
    upper_blue = np.array([255, 50, 50])
    lower_green = np.array([0, 100, 0])
    upper_green = np.array([50, 255, 50])
    lower_red = np.array([0, 0, 100])
    upper_red = np.array([50, 50, 255])

    # Create mask for each color and apply to frame
    mask_blue = cv2.inRange(frame, lower_blue, upper_blue)
    mask_green = cv2.inRange(frame, lower_green, upper_green)
    mask_red = cv2.inRange(frame, lower_red, upper_red)
    frame_blue = cv2.bitwise_and(frame, frame, mask=mask_blue)
    frame_green = cv2.bitwise_and(frame, frame, mask=mask_green)
    frame_red = cv2.bitwise_and(frame, frame, mask=mask_red)

    # Display frames and histograms
    cv2.imshow('Original', frame)
    cv2.imshow('Blue', frame_blue)
    cv2.imshow('Green', frame_green)
    cv2.imshow('Red', frame_red)
    cv2.imshow('Edges', edges)
    hist_blue = cv2.calcHist([frame_blue], [0], None, [256], [0, 256])
    hist_green = cv2.calcHist([frame_green], [0], None, [256], [0, 256])
    hist_red = cv2.calcHist([frame_red], [0], None, [256], [0, 256])
    cv2.imshow('Blue Histogram', hist_blue)
    cv2.imshow('Green Histogram', hist_green)
    cv2.imshow('Red Histogram', hist_red)

    if cv2.waitKey(1) & 0xFF == ord('q'):
        break

cap.release()
cv2.destroyAllWindows()


from angar import Angar
from flag import Flag
from random import randint
from menu import Menu
from viking import GameSprite
from trees import Tree
from mouse.mouse import Mouse
import pygame

class CameraGroup(pygame.sprite.Group):
    def __init__(self) -> None:
        super().__init__()
        self.display_surface = pygame.display.get_surface()

    def custom_draw(self):
        for sprite in sorted(self.sprites(), key=lambda sprite:sprite.rect.centery):
            self.display_surface.blit(sprite.image, (sprite.rect.centerx - sprite.rect.centerx//2, sprite.rect.centery - sprite.rect.centery//2))

pygame.init()
game = True

W = 600
H = 600
FPS = 60

window = pygame.display.set_mode((W,H), flags=pygame.RESIZABLE)
clock = pygame.time.Clock()

mouse = Mouse()
#group = CameraGroup()

menu = Menu(0,0, filename='ambar.png')

viking = GameSprite(100,100, w=100, h=100)
group_heroes = pygame.sprite.Group()
group_heroes.add(viking)

group_tree = pygame.sprite.Group()

for t in [Tree(randint(0, 2000), randint(0,2000), 'tree.png', w=150, h=150) for i in range(50)]:
    group_tree.add(t)

flag = Flag(0,0,'flag.png', w=50, h=50)
angar = Angar(0,0,'ambar.png')

while game:
    window.fill((0,75,0))

    viking.move()

    for event in pygame.event.get():
        if event.type == pygame.QUIT:
            game = False

        if event.type == pygame.KEYDOWN:
            if event.key == pygame.K_SPACE: #при нажатии ан пробел отменяем движение убираем флажок
                viking.STATE = 1
                flag.is_shown = False
            elif event.key == pygame.K_m and menu.is_shown == False: #при нажатии НА m открывакм меню
                menu.is_shown = True
            elif event.key == pygame.K_m and menu.STATE == 2:
                menu.STATE = 1
            else:
                menu.is_shown = False

        if event.type == pygame.MOUSEBUTTONDOWN:

            mouse.is_mouse_clicked = True
            mouse.x_mouse = pygame.mouse.get_pos()[0]
            mouse.y_mouse = pygame.mouse.get_pos()[1]
            mouse.check_state_mouse()

            #ЕСЛИ НАЖАЛИ НА ПКМ
            if pygame.mouse.get_pressed()[2]:

                mouse.x_mouse = pygame.mouse.get_pos()[0]
                mouse.y_mouse = pygame.mouse.get_pos()[1]
                #показываем флаг и выставляем ему x и y
                flag.is_shown = True
                flag.rect.centerx = mouse.x_mouse
                flag.rect.centery = mouse.y_mouse
                #print(f'Место клика {mouse.x_mouse} {mouse.y_mouse}')
                viking.STATE = 3 #викинг получил указание идти до клика
                viking.click_to_map(mouse, window) #ОПРЕДЕЛЯЕМ УГОЛ И ШАГ ПО ОСИ X И Y дО МЕСТА КЛИКА

        if event.type == pygame.MOUSEBUTTONUP:
            mouse.is_mouse_clicked = False

    #ГЕРОЙ ДВИЖЕТСЯ ПО КЛИКУ
    if viking.STATE == 3:
        #pygame.draw.line(window, (255,0,0), (viking.rect.centerx, viking.rect.centery), (mouse.x_mouse, mouse.y_mouse))
        viking.move_to_click(flag)

    #ЕСЛИ ГЕРОЙ ДВИГАЛСЯ ВЛЕВО ОСТАВИТЬ ФРЕЙМ КАРТИНКИ С ФЛИПОМ
    if viking.is_move_left:
        viking.image = pygame.transform.flip(viking.image, True, False)

    #ФУНКЦИОНАЛ ВЫДЕЛЕНИЯ ОБЪЕКТОВ
    mouse.check_state_mouse()
    if pygame.mouse.get_pressed()[0] and mouse.is_mouse_clicked:
        mouse.draw_mouse_rect_on_window(window=window)

    #ОПРЕДЕЛЯЮ ВЫДЕЛЕННЫЕ ОБЪЕКТЫ
    result = pygame.sprite.spritecollide(mouse, group_tree, False, False)
    result = pygame.sprite.spritecollide(mouse, group_heroes, False, False ) + result

    #ОТРИСОВЫВАЮ РАМКИ У ВЫДЕЛЕННЫХ ОБЪЕКТОВ
    for r in result:
        pygame.draw.rect(window, (0,0,255), r.rect, width=1)

    #отрисоввываем группы
    group_tree.draw(window)
    viking.draw(window)

    #показан флаг
    if flag.is_shown:
        flag.draw(window)

    #показано меню
    if menu.is_shown:
        menu.rect.centerx = viking.rect.centerx + menu.width
        menu.rect.centery = viking.rect.centery

        k = 1
        for elem in menu.menu:
            elem.rect.x = viking.rect.centerx + menu.width // 2
            elem.rect.y = viking.rect.centery - menu.height_point_menu - menu.height//2 + k*menu.height_point_menu
            k += 1

        menu.draw(window)

    if menu.STATE == 2:
        menu.is_shown = False
        angar.placement()
        if pygame.key.get_pressed()[pygame.K_p]:
            print('СОЗДАЛИ!')
            group_tree.add(angar.create())
            menu.STATE = 1

    clock.tick(FPS)
    pygame.display.update()


# learn Python - 14-dec-17
# 11 - SLanguage

# ===============
# 11.1 lists

empty = []
nums = [10, 20]
anything = ['lorem', True, 10, 123.456]
multi_dimensional = [20, 30, 30, [1, 2, 3]]

# slicing - similar to strings
greetings = ['hi', 'hello', 'good morning', 'good day']
greetings[0]
greetings[1:3]
greetings[3:]
greetings[:7]

# .append()
# adds a new item to the end of the list, returns nothing (or None ?)

slang = ['cheerio']
slang.append('cheeky')
slang.append('yonks')

# .remove()
# removes the item by-index or by-value, returns nothing (or None ?)

slang.remove('cheeky')

# del operator (note - the index should be valid - otherwise error raised)
# can use with dictionaries too, but not with strings
del slang[1]

# del with slice
del slang[3:]

# ===============
# 11.2 Dictionaries (objects in JavaScript)

# legacy with lists
slang = ['apple', 'banana']
translations = ['soof', 'kelo']

del slang[0]
del translations[0]
print(slang)

# the dictionary
slang = {
    'cheerio': 'goodbye',
    'foo': True,
    'lorem ipsum': 15.4,
    15: 'int as key',
    16.345: 'float as key'
}

# dynamic keys addition or updates

slang['new-key'] = 'the value'
slang[16] = False
# slang.16 = False # invalid syntax - error on dot "."

# delete the key (note - the index should be valid - otherwise error)
del slang['cheerio']

# .get() - get value by key (or to check if value so that to delete it)
slang.get('cheerio')  # returned value is 'goodbye'

# None - (like undefined in JavaScript)
result = slang.get('unknown-key')  # returned is None

if result:
    print('do something') # None evaluated as False in a conditional
else:
    print('key does\'nt exist')

# reading values from dictionaries
# slang['cheero'] # (can used with string, list too) - avoid, error raised if not available.
# slang.get('cheero') # recommended. no errors

translation = 'Sorry, my ' + slang.get('mate') + ' is a bit cheeky !'
print(translation)

# ===============
# 11.3 comparing and combining lists and dictionaries

# comparing lists
my_list = [1, 2, 3, 4]
his_list = [2, 3, 3, 4]
your_list = [1, 2, 3, 4]

# should have the same values and same order
print(my_list == his_list)  # False
print(my_list == your_list)  # True

# comparing dictionaries
my_dict = {1: 15, 'foo': 'bar'}
his_dict = {1: 15, 'baz': 'bar'}
your_dict = {'foo': 'bar', 1: 15}

# should have the same values only (no same order required)
print(my_dict == his_dict)  # False - values are diff
print(my_dict == your_dict)  # True - values are same, order not matter

# ---
# combining list and dictionaries, and reading 2 dimensional L & D

menus = {
    'lunch': ['SLT', 'ABC'],
    'dinner': {'FOO': 'xoxo'}
}

menus['lunch']
menus['lunch'][0]
menus['dinner']
menus['dinner']['FOO']

# ===============


import os
import json
import copy
import random
import pathlib
import matplotlib.pyplot as plt
import matplotlib.patches as patches
from PIL import Image
import numpy as np

# directory constants
ROOT_DIR = pathlib.Path('/home/weixin/neuralPoolTest/')

#  specials = list(OrderedDict.fromkeys(
            # tok for tok in [self.unk_token, self.pad_token, self.init_token,
            #                 self.eos_token] + kwargs.pop('specials', [])
PAD = 1
EOS = 3
UNK = 0
SOS = 2
# T = 1
NUM_BBOX = 36
VISUAL_FEAT = 2048
BIAS = 1000
EMB_DIM = 100

OBJECT_FUNCS = ['relate', 'relate_inv', 'relate_name', 'relate_inv_name', 'select', 'relate_attr', 'filter', 'filter_not', 'filter_h']
STRING_FUNCS = ['query_n', 'query_h', 'query', 'query_f', 'choose_n', 'choose_f', 'choose', 'choose_attr', 'choose_h', 'choose_v', 'choose_rel_inv', 'choose_subj', 'common']
BINARY_FUNCS = ['verify', 'verify_f', 'verify_h', 'verify_v', 'verify_rel', 'verify_rel_inv', 'exist', 'or', 'and', 'different', 'same', 'same_attr', 'different_attr']

BBOX_ONTOLOGY = {'darkness': ['dark', 'bright'],
                 'dryness': ['wet', 'dry'],
                 'colorful': ['colorful', 'shiny'],
                 'leaf': ['leafy', 'bare'],
                 'emotion': ['happy', 'calm'],
                 'sports': ['baseball', 'tennis'],
                 'flatness': ['flat', 'curved'],
                 'lightness': ['light', 'heavy'],
                 'gender': ['male', 'female'],
                 'width': ['wide', 'narrow'],
                 'depth': ['deep', 'shallow'],
                 'hardness': ['hard', 'soft'],
                 'cleanliness': ['clean', 'dirty'],
                 'switch': ['on', 'off'],
                 'thickness': ['thin', 'thick'],
                 'openness': ['open', 'closed'],
                 'height': ['tall', 'short'],
                 'length': ['long', 'short'],
                 'fullness': ['full', 'empty'],
                 'age': ['young', 'old'],
                 'size': ['large', 'small'],
                 'pattern': ['checkered', 'striped', 'dress', 'dotted'],
                 'shape': ['round', 'rectangular', 'triangular', 'square'],
                 'activity': ['waiting', 'staring', 'drinking', 'playing', 'eating', 'cooking', 'resting', 'sleeping', 'posing', 'talking',
                              'looking down', 'looking up', 'driving', 'reading', 'brushing teeth', 'flying', 'surfing', 'skiing', 'hanging'],
                 'pose': ['walking', 'standing', 'lying', 'sitting', 'running', 'jumping', 'crouching', 'bending', 'smiling', 'grazing'],
                 'material': ['wood', 'plastic', 'metal', 'glass', 'leather', 'leather', 'porcelain', 'concrete', 'paper', 'stone', 'brick'],
                 'color': ['white', 'red', 'black', 'green', 'silver', 'gold', 'khaki', 'gray', 'dark', 'pink', 'dark blue', 'dark brown',
                           'blue', 'yellow', 'tan', 'brown', 'orange', 'purple', 'beige', 'blond', 'brunette', 'maroon', 'light blue', 'light brown']}

SCENE_ONTOLOGY = {'location': ['indoors', 'outdoors'],
                 'weather': ['clear', 'overcast', 'cloudless', 'cloudy', 'sunny', 'foggy', 'rainy'],
                 'room': ['bedroom', 'kitchen', 'bathroom', 'living room'],
                 'place': ['road', 'sidewalk', 'field', 'beach', 'park', 'grass', 'farm', 'ocean', 'pavement',
                           'lake', 'street', 'train station', 'hotel room', 'church', 'restaurant', 'forest', 'path',
                           'display', 'store', 'river', 'sea', 'yard', 'airport', 'parking lot']}

ONTOLOGY = copy.deepcopy(BBOX_ONTOLOGY)
ONTOLOGY.update(SCENE_ONTOLOGY)

BBOX_ATTR = list(BBOX_ONTOLOGY.keys())

SCENE_ATTR = list(SCENE_ONTOLOGY.keys())

BBOX_ATTRIBUTES = {}
for k, v in BBOX_ONTOLOGY.items():
    for i, item in enumerate(v):
        if item in BBOX_ATTRIBUTES:
            BBOX_ATTRIBUTES[item].append((BBOX_ATTR.index(k), i))
        else:
            BBOX_ATTRIBUTES[item] = [(BBOX_ATTR.index(k), i)]

SCENE_ATTRIBUTES = {}
for k, v in SCENE_ONTOLOGY.items():
    for i, item in enumerate(v):
        if item in SCENE_ATTRIBUTES:
            SCENE_ATTRIBUTES[item].append((SCENE_ATTR.index(k), i))
        else:
            SCENE_ATTRIBUTES[item] = [(SCENE_ATTR.index(k), i)]

# with open(ROOT_DIR / 'GraphVQA/meta_info/GQA_hypernym.json') as f:
#     hypernym = json.load(f)

with open(ROOT_DIR / 'GraphVQA/meta_info/objects.json') as f:
    OBJECTS_INV = json.load(f)
    OBJECTS = {k: i for i, k in enumerate(OBJECTS_INV)}

with open(ROOT_DIR / 'GraphVQA/meta_info/predicates.json') as f:
    RELATIONS_INV = json.load(f)
    RELATIONS = {k: i for i, k in enumerate(RELATIONS_INV)}

with open(ROOT_DIR / 'GraphVQA/meta_info/attributes.json') as f:
    ATTRIBUTES_INV = json.load(f)
    ATTRIBUTES = {k: i for i, k in enumerate(ATTRIBUTES_INV)}

with open(ROOT_DIR / 'GraphVQA/meta_info/obj2attribute.json') as f:
    mapping = json.load(f)

OBJ2ATTRIBUTES = {}
for k, vs in mapping.items():
    tmp = set()
    for v in vs:
        if v in BBOX_ATTRIBUTES:
            for attr_k, _ in BBOX_ATTRIBUTES[v]:
                tmp.add(attr_k)
    OBJ2ATTRIBUTES[k] = list(tmp)

def show_im(k, x, y, w, h, title):
    im = np.array(Image.open(ROOT_DIR / "Downloads/allImages/images/{}.jpg".format(k)), dtype=np.uint8)
    # Create figure and axes
    fig, ax = plt.subplots(1)
    ax.imshow(im)
    # Create a Rectangle patch
    rect = patches.Rectangle((x, y), w, h, linewidth=1, edgecolor='r', facecolor='none')
    # Add the patch to the Axes
    ax.set_title(title)
    ax.add_patch(rect)

    plt.show()

def show_im_bboxes(k, coordinates):
    im = np.array(Image.open(ROOT_DIR / "Downloads/allImages/images/{}.jpg".format(k)), dtype=np.uint8)
    height = im.shape[0]
    width = im.shape[1]
    # Create figure and axes
    fig, ax = plt.subplots(1)
    ax.imshow(im)
    colors = ['red', 'yellow', 'black', 'blue', 'orange', 'grey', 'cyan', 'green', 'purple']
    # Create a Rectangle patch
    for coordinate in coordinates:
        x, y = coordinate[0] * width, coordinate[1] * height
        w, h = (coordinate[2] - coordinate[0]) * width, (coordinate[3] - coordinate[1]) * height
        color = random.choice(colors)
        rect1 = patches.Rectangle((x, y), w, h, linewidth=1, edgecolor=color, facecolor='none')
        ax.add_patch(rect1)

    plt.show()

def intersect(bbox1, bbox2, contained=False, option="xywh"):
    if option == 'xywh':
        x_inter = max(bbox1[0], bbox2[0])
        y_inter = max(bbox1[1], bbox2[1])
        x_p_inter = min(bbox1[0] + bbox1[2], bbox2[0] + bbox2[2])
        y_p_inter = min(bbox1[1] + bbox1[3], bbox2[1] + bbox2[3])
        intersect_area = max(x_p_inter - x_inter, 0) * max(y_p_inter - y_inter, 0)
        whole = bbox1[2] * bbox1[3] + bbox2[2] * bbox2[3] - intersect_area
    elif option == 'x1y1x2y2':
        x_inter = max(bbox1[0], bbox2[0])
        y_inter = max(bbox1[1], bbox2[1])
        x_p_inter = min(bbox1[2], bbox2[2])
        y_p_inter = min(bbox1[3], bbox2[3])
        intersect_area = max(x_p_inter - x_inter, 0) * max(y_p_inter - y_inter, 0)
        whole = (bbox1[2] - bbox1[0]) * (bbox1[3] - bbox1[1]) + (bbox2[2] - bbox2[0]) * (bbox2[3] - bbox2[1]) - intersect_area
    else:
        raise NotImplementedError

    if contained:
        return intersect_area / (whole + 0.01), intersect_area / (bbox1[2] * bbox1[3] + 0.01)
    else:
        return intersect_area / (whole + 0.01)

def parse_program(string):
    if '=' in string:
        result, function = string.split('=')
    else:
        function = string
        result = "?"

    func, arguments = function.split('(')
    if len(arguments) == 1:
        return result, func, []
    else:
        arguments = list(map(lambda x: x.strip(), arguments[:-1].split(',')))
        return result, func, arguments


import unittest

from arreter_programme import MauvaiseEntreeException
from module_matrice import puissance
from utils import TestBasique

class ModuleMatricePuissanceTest(TestBasique):

    def test_mauvaises_matrices(self):
        mauvaisesMatrices = [
            [[]],
            [[1, 2]],
            [[1, 2], [3, 4], [5, 6]],
            [[1, 2, 3, 4], [1, 2, 3, 4], [1, 2, 3, 4]],
            [[1, 2], [1, float('nan')]],
            [[1, 2], [1, float('inf')]],
            [[1, 10], [1, float('-inf')]],
            [[1, 2, 3], [-1, -2, -3], [0, 0, 0], [0]]
        ]
        for matrice in mauvaisesMatrices:
            def fonction():
                try:
                    puissance(matrice, 2)
                    self.fail(
                        f'{matrice} n\'est pas une matrice carrée valide. La fonction puissance() devrait appeler la fonction arreter_programme() quand un tel cas survient')
                except MauvaiseEntreeException:
                    pass
            self.executerTest(fonction, f'puissance({matrice}, 2)')

    def test_puissance(self):
        casDeTests = [
            (([[1]], 0), [[1]]),
            (([[1]], 1), [[1]]),
            (([[1]], 2), [[1]]),
            (([[1]], 20), [[1]]),
            (([[1, 0, 0], [0, 1, 0], [0, 0, 1]], 20),
             [[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
            (([[0, 1, 2], [3, 4, 5], [6, 7, 8]], 0),
             [[1, 0, 0], [0, 1, 0], [0, 0, 1]]),
            (([[0, 1, 2], [3, 4, 5], [6, 7, 8]], 10), [[13732435440, 17713440288, 21694445136], [
             42154372512, 54374838624, 66595304736], [70576309584, 91036236960, 111496164336]]),
        ]
        for (matrice, exposant), matriceAttendue in casDeTests:
            def fonction():
                matriceObtenue = puissance(matrice, exposant)
                self.assertEqual(
                    matriceObtenue,
                    matriceAttendue,
                    f'La matrice retournée par l\'appel fonction puissance({matrice}, {exposant}) n\'est pas valide. La valeur attendue est {matriceAttendue}. La valeur obtenue est {matriceObtenue}.')
            self.executerTest(fonction, f'puissance({matrice}, {exposant})')

if __name__ == '__main__':
    unittest.main(verbosity=2)


import torch
import torch.optim as optim
import time
import sys
import os
from utiles import CriticUpdater, mask_norm, mkdir, mask_data,one_hot,GeneratorLoss
from pathlib import Path
use_cuda = torch.cuda.is_available()
device = torch.device('cuda' if use_cuda else 'cpu')
Tensor = torch.cuda.FloatTensor if use_cuda else torch.Tensor

def scMultiGAN_impute(args, data_gen, imputer,
                   impu_critic,
                  data_loader):
    impute_dir = args.output_dir
    checkpoint = args.checkpoint
    mkdir(Path(impute_dir)/'model_impute')
    model_dir = Path(os.path.join(impute_dir,"model_impute"))
    n_critic = args.n_critic
    lambd = args.lambd
    batch_size = args.batch_size
    nz = args.latent_dim
    epochs = args.epoch
    save_model_interval = args.save_interval
    alpha = args.alpha
    beta = args.beta
    gamma = args.gamma
    tau = args.tau
    img_size = args.img_size
    update_all_networks = not args.imputeronly

    n_batch = len(data_loader)
    data_noise = torch.FloatTensor(batch_size, nz).to(device)
    impu_noise = torch.FloatTensor(batch_size, args.channels,img_size,img_size).to(device)
    eps = torch.FloatTensor(batch_size, 1, 1, 1).to(device)
    ones = torch.ones(batch_size).to(device)
    #lrate = 1e-4
    imputer_lrate = args.lr

    generator_loss = GeneratorLoss()
    imputer_optimizer = optim.Adam(
        imputer.parameters(), lr=imputer_lrate)
    impu_critic_optimizer = optim.Adam(
        impu_critic.parameters(), lr=imputer_lrate)
    update_impu_critic = CriticUpdater(
        impu_critic, impu_critic_optimizer, eps, ones, lambd)

    start_epoch = 0
    critic_updates = 0

    pretrain = torch.load(args.pretrain, map_location='cpu')
    data_gen.load_state_dict(pretrain['data_gen'])

    if checkpoint:
        print("Using pretained model {}".format(checkpoint))
        checkpoint = torch.load(Path(checkpoint))
        imputer.load_state_dict(checkpoint['imputer'])
        impu_critic.load_state_dict(checkpoint['impu_critic'])
        start_epoch = checkpoint['epoch']-1
        critic_updates = checkpoint['critic_updates']

    def save_model(path, epoch, critic_updates=0):
        torch.save({
            'imputer': imputer.state_dict(),
            'impu_critic': impu_critic.state_dict(),
            'epoch': epoch + 1,
            'critic_updates': critic_updates,
            'args': args,
        }, str(path))
    start = time.time()
    epoch_start = start

    for epoch in range(start_epoch, epochs):
        #print('start train')
        sum_data_loss, sum_mask_loss, sum_impu_loss = 0, 0, 0
        for i,real_sample in enumerate(data_loader):
            real_data = real_sample['real_data'].to(device)
            real_mask = real_sample['real_mask'].to(device)
            label = real_sample['label'].to(device)
            label_hot = one_hot((label).type(torch.LongTensor),args.ncls).type(Tensor).to(device)
            data_noise.normal_()
            fake_data = data_gen(data_noise,label_hot)

            impu_noise.uniform_()
            imputed_data = imputer(real_data, real_mask, impu_noise,label_hot)
            masked_imputed_data = mask_data(real_data, real_mask, imputed_data)

            update_impu_critic(fake_data, masked_imputed_data,label_hot)
            sum_impu_loss += update_impu_critic.loss_value
            critic_updates += 1
            sys.stdout.write("\r[Epoch %d/%d] [Batch %d/%d] [D_impute loss: %f]" % (
                epoch + 1, args.epoch, i + 1, len(data_loader),
                sum_impu_loss))
            sys.stdout.flush()
            if critic_updates == n_critic:
                critic_updates = 0
                for p in impu_critic.parameters():
                    p.requires_grad_(False)
                impu_noise.uniform_()
                imputed_data = imputer(real_data, real_mask, impu_noise,label_hot)
                masked_imputed_data = mask_data(real_data, real_mask,
                                                imputed_data)
                impu_loss = 1-impu_critic(masked_imputed_data,label_hot).mean()
                impu_loss = generator_loss(impu_loss,fake_data,masked_imputed_data)
                imputer.zero_grad()
                if gamma > 0:
                    imputer_mismatch_loss = mask_norm(
                        (imputed_data - real_data) ** 2, real_mask)
                    (impu_loss + imputer_mismatch_loss * gamma).backward()
                else:
                    impu_loss.backward()
                imputer_optimizer.step()
                for p in impu_critic.parameters():
                    p.requires_grad_(True)
                print("\r[Epoch %d/%d] [Batch %d/%d] [G_impute loss: %f]" % (
                    epoch + 1, args.epoch, i + 1, len(data_loader),
                    impu_loss.detach().cpu().numpy().item()))
        mean_impu_loss = sum_impu_loss / n_batch
        print("epoch {} data_loss is {}".format(epoch + 1, mean_impu_loss))

        if save_model_interval > 0 and (epoch + 1) % save_model_interval == 0:
            save_model(os.path.join(model_dir , f'{epoch:04d}.pth'), epoch, critic_updates)
        epoch_end = time.time()
        time_elapsed = epoch_end - start
        epoch_time = epoch_end - epoch_start
        epoch_start = epoch_end


from PIL import Image
import pytesseract
from pprint import pprint

# Set path for pytesseract
pytesseract.pytesseract.tesseract_cmd = (
    r"C:\Users\David\AppData\Local\Programs\Tesseract-OCR\tesseract.exe"
)

def remove_colors(image: Image, chosen_colours: list) -> Image:
    """Input an image and a list of colours. The function will scan all pixels and will set any pixels within the threshold of the colours given to black (3, 3, 3), and all other pixels to white.

    Args:
        image: Image object from PIL
        chosen_colours (list of tuples): Colours to pass through (R, G, B)

    Returns:
       Image object with valid pixels in black, all else white
    """

    # Creates a new image with the same size as the image to be tested
    new_image = Image.new("RGB", image.size)

    # Threshold, RGB values must match within +/- threshold

    threshold = 40

    # Iterates through each colour at a time
    for chosen_colour in chosen_colours:
        for x in range(image.width):
            for y in range(image.height):
                pixel_rgb = image.getpixel((x, y))

                # Checks test image pixel for match, or if new_image pixel has been set to valid (3, 3, 3)
                if all(
                    (
                        chosen_colour[0] - threshold
                        <= pixel_rgb[0]
                        <= chosen_colour[0] + threshold,
                        chosen_colour[1] - threshold
                        <= pixel_rgb[1]
                        <= chosen_colour[1] + threshold,
                        chosen_colour[2] - threshold
                        <= pixel_rgb[2]
                        <= chosen_colour[2] + threshold,
                    )
                ) or new_image.getpixel((x, y)) == (3, 3, 3):
                    new_image.putpixel((x, y), (3, 3, 3))
                else:
                    new_image.putpixel((x, y), (255, 255, 255))

    return new_image

# List of colours to be checked
chosen_colors = [(225, 30, 30), (63, 72, 204), (50, 170, 80)]

# Open image to be tested
image = Image.open("test.jpg")

processed_image = remove_colors(image, chosen_colors)
image.close()

processed_image.show()
processed_image.save("processed_image.jpg")

text1 = pytesseract.image_to_string(processed_image)

print(text1)

processed_image.close()


from django.shortcuts import render, get_object_or_404, redirect
from .models import Create_Class, Name_of_classes, Students
from .forms import (Creat_Class_Form, Create_Class_Model_Form,
                    Student_Model_Form)
from django.contrib.auth.decorators import login_required
from django.contrib import messages
from django.db.models import Count
from django.http import JsonResponse, HttpResponse
from datetime import datetime, date
import datetime as dt

from datetime import timedelta
from django.utils import timezone
# Create your views here.

def home(request):
    fieldname = 'class_name'
    to_bday, tmr_bday = Birthday_alert()
    #tmr_bday, to_bday = Birthday_alert()
    objs = Create_Class.objects.values(fieldname).order_by(
        fieldname).annotate(the_count=Count(fieldname))
    # print(objs)
    template_name = 'genius/home.html'
    context = {'head_title': "Little Genius",
               'data': 'Little Genius-School of Science & Technology',
               'count': objs,
               'tmr':tmr_bday,
               'to':to_bday,
               }
    return render(request, template_name, context)

def Add_name(request):
    if request.method == 'POST':
        print('JS got here')
        class_name = request.POST['class-name']
        print(class_name)
        data = None
        if len(class_name) > 0:
            is_there = Name_of_classes.objects.filter(name__iexact=class_name)
            if not is_there:
                inst = Name_of_classes.objects.create(name=class_name)
                data = {
                    'bool': True,
                    'msg': 'Created Successfully'
                }
            else:
                data = {
                    'bool': False,
                    'msg': 'Name already exists!'
                }
        else:
            data = {
                'bool': False,
                'msg': 'Name should not be empty!'
            }
        return JsonResponse(data)
    else:
        print('JS has not arrived')
        return redirect('/')

def Classes(request):
    objs = Create_Class.objects.all()
    names = Name_of_classes.objects.all()
    templatename = 'genius/classes.html'
    context = {'classes': objs, 'class': names}
    return render(request, templatename, context)

# @login_required(login_url='/login/')

def Class_create(request):
    form = Create_Class_Model_Form(request.POST or None)
    name = request.POST.get('select')
    fromday = request.POST.get('from_days')
    today = request.POST.get('to_days')
    fromtime = request.POST.get('from_time')
    to_time = request.POST.get('to_time')
    # get class_names from classname table
    fieldname = 'class_name'
    objs = Create_Class.objects.values(fieldname).order_by(
        fieldname).annotate(the_count=Count(fieldname))
    # Check whether data already exists in database
    already = Create_Class.objects.filter(
        class_name__iexact=name).filter(from_days__iexact=fromday).filter(to_days__iexact=today).filter(from_time__iexact=fromtime).filter(to_time__iexact=to_time)
    if not already:
        if name != "Click to select Class Name":
            if form.is_valid():
                obj = form.save(commit=False)
                obj.class_name = name
                #obj.created_by = request.user.username
                obj.save()
                print('successful')
                messages.success(request, 'Saved Successfully')
                form = Create_Class_Model_Form()
            else:
                #messages.error(request, 'Something wrong with data')
                form = Create_Class_Model_Form()

        else:
            messages.error(request, 'Please select the class name')
    else:
        messages.error(request, 'This class already exists')
    c_names = Name_of_classes.objects.values('name')
    templatename = 'genius/class_create.html'
    context = {'form': form, 'c_names': c_names, 'count': objs}
    return render(request, templatename, context)

def Class_Detail(request, id):
    objs = get_object_or_404(Create_Class, id=id)
    templatename = 'genius/class_detail.html'
    context = {'obj': objs, 'form': None}
    return render(request, templatename, context)

def Class_Update(request, id):
    obj = get_object_or_404(Create_Class, id=id)
    form = Create_Class_Model_Form(request.POST or None, instance=obj)
    if form.is_valid():
        form.save()
        messages.success(request, 'Class Updated Successfully.')
    templatename = 'genius/class_update.html'
    context = {'form': form,
               'head_title': f"Update {obj.class_name}",
               'title': f"Update : {obj.class_name}"}
    return render(request, templatename, context)

def Class_Delete(request, id):
    objs = get_object_or_404(Create_Class, id=id)
    templatename = 'genius/class_delete.html'
    if request.method == "POST":
        objs.delete()
        return redirect("/class")
    context = {'obj': objs, 'form': None}
    return render(request, templatename, context)

def Student_Main(request):
    objs= Students.objects.values().all()
    std_count=Students.objects.all().count()
    template_name = 'genius/students.html'
    context = {'head_title': 'Little Genius Students', 'students':objs,'count':std_count}
    return render(request, template_name, context)

def Student_Create(request):
    form = Student_Model_Form(request.POST or None)
    print('Student view came')
    cls=get_class_parent_detail()
    if request.method =='POST':
        # get class names and days
        for_age= form.data['dob']
        to_date=datetime.strptime(for_age, '%Y-%m-%d').date()
        get_age=Calculate_Age(to_date)
        print('MEthod is post')
        #now start storing the Student information
        print(form.data)
        if form.is_valid():
            print('form is valid')
            obj = form.save(commit=False)
            obj.age = get_age
            obj.save()
            messages.success(request, 'Student is registered successfully')
            form=Student_Model_Form()
        else:
            messages.error(request,form.errors)
            print(form.errors)
    template_name = 'genius/students_create.html'
    context = {'form': form,'classes':cls}
    return render(request, template_name, context)

def Student_Detail(request, id):
    objs = get_object_or_404(Students, id=id)
    templatename = 'genius/students_detail.html'
    context = {'obj': objs, 'form': None}
    return render(request, templatename, context)

def Student_Update(request, id):
    obj = get_object_or_404(Students, id=id)
    form = Student_Model_Form(request.POST or None, instance=obj)
    if form.is_valid():
        form.save()
        messages.success(request, 'Student Updated Successfully.')
        return redirect('/stds')
    templatename = 'genius/student_update.html'
    context = {'form': form,
               'head_title': f"Update {obj.name}",
               'title': f"Update : {obj.name}"}
    return render(request, templatename, context)

def Student_Delete(request, id):
    objs = get_object_or_404(Students, id=id)
    templatename = 'genius/students_delete.html'
    if request.method == "POST":
        objs.delete()
        messages.success(request,'Deleted Successfully.')
        return redirect("/stds")
    context = {'obj': objs, 'form': None}
    return render(request, templatename, context)

def get_class_parent_detail():
    classes= Create_Class.objects.values('pk','class_name','from_days','to_days','from_time','to_time').all()
    return classes

def Calculate_Age(bday):
    today = date.today()
    age = today.year - bday.year - ((today.month, today.day) < (bday.month, bday.day))
    return age

def Birthday_alert():
    #students= Students.objects.all()
    datetime_now = timezone.now()
    now_day, now_month = datetime_now.day, datetime_now.month
    datetime_tomorrow = datetime_now + timedelta(days=1)
    tomorrow_day, tomorrow_month = datetime_tomorrow.day, datetime_tomorrow.month

    std_today = Students.objects.filter(dob__day=now_day, dob__month=now_month)
    std_tmr = Students.objects.filter(dob__day=tomorrow_day, dob__month=tomorrow_month)
    tday=[]
    tmr=[]

    for l in std_today:
        tday.append({
            'name':l.name,
            'course':l.course.class_name,
            'contact':l.parent_contact,
            'dob':l.dob
        })

    for l in std_tmr:
        tmr.append({
            'name':l.name,
            'course':l.course.class_name,
            'contact':l.parent_contact,
            'dob':l.dob
        })

    # putting into dictionary
    # for s in students:
    #     if s.dob == dt.date.today():
    #         to_bays.append({
    #             'name': 's.name',
    #             'course': 's.course.class_name',
    #             'dob' : 's.dob',
    #             'contact': 's.parent_contact',
    #         })
    #     elif s.dob + dt.timedelta(days=1) == tmr:
    #         tmr_bdays.append({
    #             'name': 's.name',
    #             'course': 's.course.class_name',
    #             'dob' : 's.dob',
    #             'contact': 's.parent_contact',
    #         })
    #     else:
    #         for m in students:
    #             print("else:",m.name)
    return (tday,tmr)

def Search(request):
    q= request.GET.get('q',None)
    print(q)
    results = Students.objects.search(query=q).values()
    std_count=Students.objects.all().count()
    template_name = 'genius/students.html'
    context = {'head_title': 'Little Genius Students', 'students':results,'count':std_count}
    return render(request, template_name, context)


from werkzeug.wsgi import ClosingIterator
from werkzeug.local import Local, release_local
import logging

logger = logging.getLogger(__name__)

def run_callback(cb):
    try:
        cb()
    except Exception as e:
        logger.error("Error in after response callback", exc_info=e)

MAIN_AFTER_RESPONSE_SET = False

class AfterResponse:
    def __init__(self, app, is_main=True):
        self.callbacks = []
        self.local = Local()

        if is_main:
            global MAIN_AFTER_RESPONSE_SET
            if MAIN_AFTER_RESPONSE_SET:
                raise RuntimeError("Main AfterResponse hook has already been defined")

            try:
                import uwsgi
                has_uwsgi = True
            except ImportError:
                has_uwsgi = False
        else:
            has_uwsgi = True

        if has_uwsgi:
            if hasattr(uwsgi, "after_req_hook"):
                old_hook = uwsgi.after_req_hook
                def combined_hook():
                    self._run()
                    old_hook()
                uwsgi.after_req_hook = combined_hook
            else:
                uwsgi.after_req_hook = self._run
        else:
            old_app = app.wsgi_app
            def new_wsgi_app(environ, after_response):
                iterator = old_app(environ, after_response)
                return ClosingIterator(iterator, [self._run])
            app.wsgi_app = new_wsgi_app

        if is_main:
            MAIN_AFTER_RESPONSE_SET = True

    def _run(self):
        if hasattr(self.local, "callbacks"):
            for cb in reversed(self.local.callbacks):
                run_callback(cb)
            # We clean local callbacks manually. LocalManager will do it too soon; we use
            # them after the response is sent.
            release_local(self.local)

        for cb in reversed(self.callbacks):
            run_callback(cb)

    def always(self, callback):
        self.callbacks.append(callback)
        return callback

    def once(self, callback):
        if not hasattr(self.local, "callbacks"):
            self.local.callbacks = []
        self.local.callbacks.append(callback)
        return callback


from bs4 import BeautifulSoup
import requests
import spotipy
from spotipy.oauth2 import SpotifyOAuth
from dotenv import load_dotenv, dotenv_values
import os

load_dotenv()

spotify_clientID = os.getenv("spotify_clientID")
spotify_client_secret = os.getenv("spotify_client_secret")
username = os.getenv("username")

song_uris = []

date = input('Which year do you want to travel to? Type the date in this format YYYY-MM-DD: ')

URL = f"https://www.billboard.com/charts/hot-100/{date}"

response = requests.get(URL)
billboard_webpage = response.content

# Creating our Soup
soup = BeautifulSoup(billboard_webpage, "html.parser")

titles = soup.select("li ul li h3")
artists = soup.find_all(name="span", class_="u-max-width-330")

song_names = [song.getText().strip() for song in titles]
artists_name = [artist.getText().strip() for artist in artists]

print(f"titles: {song_names}\nArtists: {artists_name}")

artist_count = 0

# Used to authenticate
sp = spotipy.Spotify(
    auth_manager=SpotifyOAuth(
        scope="playlist-modify-private",
        redirect_uri="http://example.com",
        client_id=spotify_clientID,
        client_secret=spotify_client_secret,
        show_dialog=True,
        cache_path="token.txt",
        username=username,
    )
)

user_id = sp.current_user()["id"]
year = date.split("-")[0]

for song in song_names:
    result = sp.search(q=f"{song} {artists_name[artist_count]} ", type="track")
    print(result)
    try:
        uri = result["tracks"]["items"][0]["uri"]
        song_uris.append(uri)
    except IndexError:
        print(f"{song} doesn't exist in Spotify. Skipped.")
    artist_count += 1

print(song_uris)

playlist = sp.user_playlist_create(user=user_id, name=f"{date} Billboard 100", public=False, description=f"Top 100 songs from {date}. Songs are listed in order.")

sp.playlist_add_items(playlist_id=playlist["id"], items=song_uris)


import seaborn as sn
import pandas as pd
import matplotlib.pyplot as plt
from keras.preprocessing.image import ImageDataGenerator
import numpy as np
import sys

with open('./confusion-oc-cnn-1528961158.067217.txt','rb') as f:
    m = np.loadtxt(f)

# Constants used
img_width, img_height = 224, 224
test_data_dir = './newWIDER\\test'

validation_datagen = ImageDataGenerator(rescale = 1./255)
validation_generator = validation_datagen.flow_from_directory(
    test_data_dir,
    target_size=(img_width, img_height),
    batch_size=25)

classes = len(validation_generator.class_indices)
categories = classes * ['']

for key, value in validation_generator.class_indices.items():
    categories[value] = key

sum = classes * [0]

for x in range(0, classes):
    for y in range(0, classes):
        m[x,y] = int(float("{0:.2f}".format(m[x,y])))
        sum[x] += m[x,y]

for x in range(0, classes):
    own_ratio = float(m[x,x]) / sum[x]
    if (own_ratio > 0.15):
        print ('Category ' + str(categories[x]) + ' has score ' + str(own_ratio))
        max_conf = 0
        max_y = 0
        for y in range(0, classes):
            if x != y and float(m[x,y])/sum[x] > max_y:
                max_conf = float(m[x,y])/sum[x]
                max_y = y
        print ('gets most confused with ' + str(categories[max_y]) + ' with score ' + str(max_conf))

for x in range(0, classes):
    for y in range(0, classes):
        m[x,y] = float(m[x,y])/sum[x] *100

m = m.astype(int)
df_cm = pd.DataFrame(m, categories, categories)
sn.set(font_scale=1.3) # for label size
sn.heatmap(df_cm, cmap="BuPu", annot=True, annot_kws={"size": 14}) # font size

plt.show()


# Converter for generating presets from CTP DICOM Anonymizer settings
import sys
import os

if __name__ == "__main__":
    with open('input.txt') as f:
        # Using for loop
        for line in f:
            if not line.strip():
                continue
            first_id = line[13:17]
            second_id = line[17:21]

            command = "INVALID"

            if "></e>" in line:
                command="safe"
            if ">@empty()</e>" in line:
                command="clear"
            if ">@remove()</e>" in line:
                command="remove"

            out_line = "res &= addTag(\"(" + first_id + "," + second_id + ")\", \""+command+"\");"
            print(out_line)


#!/usr/bin/env python3

r"""
This module provides functions which are useful to plug-ins call-point programs that wish to make external
robot program calls.
"""

import imp
import os
import re
import subprocess
import sys
import time

import gen_cmd as gc
import gen_misc as gm
import gen_print as gp
import gen_valid as gv

base_path = (
    os.path.dirname(os.path.dirname(imp.find_module("gen_robot_print")[1]))
    + os.sep
)

def init_robot_out_parms(extra_prefix=""):
    r"""
    Initialize robot output parms such as outputdir, output, etc.

    This function will set global values for the following robot output parms.

    outputdir, output, log, report, loglevel, consolecolors, consolemarkers

    This function would typically be called prior to calling create_robot_cmd_string.

    Description of argument(s):
    extra_prefix                    An extra prefix to be appended to the default prefix for output file
                                    names.
    """

    gp.dprint_executing()
    AUTOBOOT_OPENBMC_NICKNAME = gm.get_mod_global("AUTOBOOT_OPENBMC_NICKNAME")

    # Set values for call to create_robot_cmd_string.
    # Environment variable TMP_ROBOT_DIR_PATH can be set by the user to indicate that robot-generated output
    # should initially be written to the specified temporary directory and then moved to the normal output
    # location after completion.
    outputdir = os.environ.get(
        "TMP_ROBOT_DIR_PATH",
        os.environ.get(
            "STATUS_DIR_PATH", os.environ.get("HOME", ".") + "/status"
        ),
    )
    outputdir = gm.add_trailing_slash(outputdir)
    seconds = time.time()
    loc_time = time.localtime(seconds)
    time_string = time.strftime("%y%m%d.%H%M%S", loc_time)
    file_prefix = (
        AUTOBOOT_OPENBMC_NICKNAME + "." + extra_prefix + time_string + "."
    )
    # Environment variable SAVE_STATUS_POLICY governs when robot-generated output files (e.g. the log.html)
    # will be moved from TMP_ROBOT_DIR_PATH to FFDC_DIR_PATH.  Valid values are "ALWAYS", "NEVER" and "FAIL".
    SAVE_STATUS_POLICY = os.environ.get("SAVE_STATUS_POLICY", "ALWAYS")
    if SAVE_STATUS_POLICY == "NEVER":
        output = "NONE"
        log = "NONE"
        report = "NONE"
    else:
        output = file_prefix + "output.xml"
        log = file_prefix + "log.html"
        report = file_prefix + "report.html"
    loglevel = "TRACE"
    consolecolors = "off"
    consolemarkers = "off"

    # Make create_robot_cmd_string values global.
    gm.set_mod_global(outputdir)
    gm.set_mod_global(output)
    gm.set_mod_global(log)
    gm.set_mod_global(report)
    gm.set_mod_global(loglevel)
    gm.set_mod_global(consolecolors)
    gm.set_mod_global(consolemarkers)

    return (
        outputdir,
        output,
        log,
        report,
        loglevel,
        consolecolors,
        consolemarkers,
    )

def init_robot_test_base_dir_path():
    r"""
    Initialize and validate the environment variable, ROBOT_TEST_BASE_DIR_PATH and set corresponding global
    variable ROBOT_TEST_RUNNING_FROM_SB.

    If ROBOT_TEST_BASE_DIR_PATH is already set, this function will merely validate it.  This function will
    also set environment variable ROBOT_TEST_RUNNING_FROM_SB when ROBOT_TEST_BASE_DIR_PATH is not pre-set.
    """

    # ROBOT_TEST_BASE_DIR_PATH will be set as follows:
    # This function will determine whether we are running in a user sandbox or from a standard apolloxxx
    # environment.
    # - User sandbox:
    # If there is a <developer's home dir>/git/openbmc-test-automation/, ROBOT_TEST_BASE_DIR_PATH will be
    # set to that path.  Otherwise, we set it to <program dir path>/git/openbmc-test-automation/
    # - Not in user sandbox:
    #   ROBOT_TEST_BASE_DIR_PATH will be set to <program dir path>/git/openbmc-test-automation/

    ROBOT_TEST_BASE_DIR_PATH = os.environ.get("ROBOT_TEST_BASE_DIR_PATH", "")
    ROBOT_TEST_RUNNING_FROM_SB = int(
        os.environ.get("ROBOT_TEST_RUNNING_FROM_SB", "0")
    )
    if ROBOT_TEST_BASE_DIR_PATH == "":
        # ROBOT_TEST_BASE_DIR_PATH was not set by user/caller.
        AUTOIPL_VERSION = os.environ.get("AUTOIPL_VERSION", "")
        if AUTOIPL_VERSION == "":
            ROBOT_TEST_BASE_DIR_PATH = base_path
        else:
            suffix = "git/openbmc-test-automation/"

            # Determine whether we're running out of a developer sandbox or simply out of an apolloxxx/bin
            # path.
            shell_rc, out_buf = gc.shell_cmd(
                "dirname $(which gen_print.py)",
                quiet=(not debug),
                print_output=0,
            )
            executable_base_dir_path = os.path.realpath(out_buf.rstrip()) + "/"
            apollo_dir_path = (
                os.environ["AUTO_BASE_PATH"] + AUTOIPL_VERSION + "/bin/"
            )
            developer_home_dir_path = re.sub(
                "/sandbox.*", "", executable_base_dir_path
            )
            developer_home_dir_path = gm.add_trailing_slash(
                developer_home_dir_path
            )
            gp.dprint_vars(
                executable_base_dir_path,
                developer_home_dir_path,
                apollo_dir_path,
            )

            ROBOT_TEST_RUNNING_FROM_SB = 0
            if executable_base_dir_path != apollo_dir_path:
                ROBOT_TEST_RUNNING_FROM_SB = 1
                gp.dprint_vars(ROBOT_TEST_RUNNING_FROM_SB)
                ROBOT_TEST_BASE_DIR_PATH = developer_home_dir_path + suffix
                if not os.path.isdir(ROBOT_TEST_BASE_DIR_PATH):
                    gp.dprint_timen(
                        "NOTE: Sandbox directory "
                        + ROBOT_TEST_BASE_DIR_PATH
                        + " does not"
                        + " exist."
                    )
                    # Fall back to the apollo dir path.
                    ROBOT_TEST_BASE_DIR_PATH = apollo_dir_path + suffix
            else:
                # Use to the apollo dir path.
                ROBOT_TEST_BASE_DIR_PATH = apollo_dir_path + suffix

    OBMC_TOOLS_BASE_DIR_PATH = (
        os.path.dirname(ROBOT_TEST_BASE_DIR_PATH.rstrip("/"))
        + "/openbmc-tools/"
    )
    OPENBMCTOOL_DIR_PATH = OBMC_TOOLS_BASE_DIR_PATH + "openbmctool/"
    JSON_CHECKER_TOOLS_DIR_PATH = (
        OBMC_TOOLS_BASE_DIR_PATH + "expectedJsonChecker/"
    )

    gv.valid_value(ROBOT_TEST_BASE_DIR_PATH)
    gp.dprint_vars(
        ROBOT_TEST_RUNNING_FROM_SB,
        ROBOT_TEST_BASE_DIR_PATH,
        OBMC_TOOLS_BASE_DIR_PATH,
        OPENBMCTOOL_DIR_PATH,
        JSON_CHECKER_TOOLS_DIR_PATH,
    )
    gv.valid_dir_path(ROBOT_TEST_BASE_DIR_PATH)

    ROBOT_TEST_BASE_DIR_PATH = gm.add_trailing_slash(ROBOT_TEST_BASE_DIR_PATH)
    gm.set_mod_global(ROBOT_TEST_BASE_DIR_PATH)
    os.environ["ROBOT_TEST_BASE_DIR_PATH"] = ROBOT_TEST_BASE_DIR_PATH

    gm.set_mod_global(ROBOT_TEST_RUNNING_FROM_SB)
    os.environ["ROBOT_TEST_RUNNING_FROM_SB"] = str(ROBOT_TEST_RUNNING_FROM_SB)

    gm.set_mod_global(OBMC_TOOLS_BASE_DIR_PATH)
    os.environ["OBMC_TOOLS_BASE_DIR_PATH"] = str(OBMC_TOOLS_BASE_DIR_PATH)

    gm.set_mod_global(OPENBMCTOOL_DIR_PATH)
    os.environ["OPENBMCTOOL_DIR_PATH"] = str(OPENBMCTOOL_DIR_PATH)

    gm.set_mod_global(JSON_CHECKER_TOOLS_DIR_PATH)
    os.environ["JSON_CHECKER_TOOLS_DIR_PATH"] = str(
        JSON_CHECKER_TOOLS_DIR_PATH
    )

raw_robot_file_search_path = (
    "${ROBOT_TEST_BASE_DIR_PATH}:"
    + "${ROBOT_TEST_BASE_DIR_PATH}tests:${ROBOT_TEST_BASE_DIR_PATH}extended:"
    + "${ROBOT_TEST_BASE_DIR_PATH}scratch:${PATH}"
)

def init_robot_file_path(robot_file_path):
    r"""
    Determine full path name for the file path passed in robot_file_path and return it.

    If robot_file_path contains a fully qualified path name, this function will verify that the file exists.
    If robot_file_path contains a relative path, this function will search for the file and set
    robot_file_path so that it contains the absolute path to the robot file.  This function will search for
    the robot file using the raw_robot_file_search_path (defined above).  Note that if
    ROBOT_TEST_BASE_DIR_PATH is not set, this function will call init_robot_test_base_dir_path to set it.

    Description of arguments:
    robot_file_path                 The absolute or relative path to a robot file.
    """

    gv.valid_value(robot_file_path)

    try:
        if ROBOT_TEST_BASE_DIR_PATH is NONE:
            init_robot_test_base_dir_path()
    except NameError:
        init_robot_test_base_dir_path()

    if not re.match(r".*\.(robot|py)$", robot_file_path):
        # No suffix so we'll assign one of "\.robot".
        robot_file_path = robot_file_path + ".robot"

    abs_path = 0
    if robot_file_path[0:1] == "/":
        abs_path = 1

    gp.dprint_vars(abs_path, robot_file_path)

    if not abs_path:
        cmd_buf = 'echo -n "' + raw_robot_file_search_path + '"'
        shell_rc, out_buf = gc.shell_cmd(
            cmd_buf, quiet=(not debug), print_output=0
        )
        robot_file_search_paths = out_buf
        gp.dprint_var(robot_file_search_paths)
        robot_file_search_paths_list = robot_file_search_paths.split(":")
        for search_path in robot_file_search_paths_list:
            search_path = gm.add_trailing_slash(search_path)
            candidate_file_path = search_path + robot_file_path
            gp.dprint_var(candidate_file_path)
            if os.path.isfile(candidate_file_path):
                gp.dprint_timen("Found full path to " + robot_file_path + ".")
                robot_file_path = candidate_file_path
                break

    gp.dprint_var(robot_file_path)
    gv.valid_file_path(robot_file_path)

    return robot_file_path

def get_robot_parm_names():
    r"""
    Return a list containing all of the long parm names (e.g. --outputdir) supported by the robot program.
    Double dashes are not included in the names returned.
    """

    cmd_buf = (
        "robot -h | egrep "
        + "'^([ ]\\-[a-zA-Z0-9])?[ ]+--[a-zA-Z0-9]+[ ]+' | sed -re"
        + " s'/.*\\-\\-//g' -e s'/ .*//g' | sort -u"
    )
    shell_rc, out_buf = gc.shell_cmd(cmd_buf, quiet=1, print_output=0)

    return out_buf.split("\n")

def create_robot_cmd_string(robot_file_path, *parms):
    r"""
    Create a robot command string and return it.  On failure, return an empty string.

    Description of arguments:
    robot_file_path                 The path to the robot file to be run.
    parms                           The list of parms to be included in the command string.  The name of each
                                    variable in this list must be the same as the name of the corresponding
                                    parm.  This function figures out that name.  This function is also able
                                    to distinguish robot parms (e.g. --outputdir) from robot program parms
                                    (all other parms which will be passed as "-v PARM_NAME:parm_value")..

    Example:

    The following call to this function...
    cmd_buf = create_robot_cmd_string("tools/start_sol_console.robot", OPENBMC_HOST, quiet, test_mode, debug,
    outputdir, output, log, report)

    Would return a string something like this.
    robot -v OPENBMC_HOST:beye6 -v quiet:0 -v test_mode:1 -v debug:1
    --outputdir=/gsa/ausgsa/projects/a/status --output=beye6.OS_Console.output.xml
    --log=beye6.OS_Console.log.html --report=beye6.OS_Console.report.html tools/start_sol_console.robot
    """

    robot_file_path = init_robot_file_path(robot_file_path)

    robot_parm_names = get_robot_parm_names()

    robot_parm_list = []

    stack_frame = 2
    ix = 2
    for arg in parms:
        parm = arg
        parm = gm.quote_bash_parm(gm.escape_bash_quotes(str(parm)))
        var_name = gp.get_arg_name(None, ix, stack_frame)
        if var_name in robot_parm_names:
            p_string = "--" + var_name + "=" + str(parm)
            robot_parm_list.append(p_string)
        else:
            p_string = "-v " + var_name + ":" + str(parm)
            robot_parm_list.append(p_string)
        ix += 1

    robot_cmd_buf = (
        "robot " + " ".join(robot_parm_list) + " " + robot_file_path
    )

    return robot_cmd_buf

# Global variables to aid in cleanup after running robot_cmd_fnc.
gcr_last_robot_cmd_buf = ""
gcr_last_robot_rc = 0

def process_robot_output_files(robot_cmd_buf=None, robot_rc=None, gzip=None):
    r"""
    Process robot output files which can involve several operations:
    - If the files are in a temporary location, using SAVE_STATUS_POLICY to decide whether to move them to a
      permanent location or to delete them.
    - Gzipping them.

    Description of argument(s):
    robot_cmd_buf                   The complete command string used to invoke robot.
    robot_rc                        The return code from running the robot command string.
    gzip                            Indicates whether robot-generated output should be gzipped.
    """

    robot_cmd_buf = gm.dft(robot_cmd_buf, gcr_last_robot_cmd_buf)
    robot_rc = gm.dft(robot_rc, gcr_last_robot_rc)
    gzip = gm.dft(gzip, int(os.environ.get("GZIP_ROBOT", "1")))

    if robot_cmd_buf == "":
        # This can legitimately occur if this function is called from an exit_function without the program
        # having ever run robot_cmd_fnc.
        return

    SAVE_STATUS_POLICY = os.environ.get("SAVE_STATUS_POLICY", "ALWAYS")
    gp.qprint_vars(SAVE_STATUS_POLICY)

    # When SAVE_STATUS_POLICY is "NEVER" robot output files don't even get generated.
    if SAVE_STATUS_POLICY == "NEVER":
        return

    # Compose file_list based on robot command buffer passed in.
    robot_cmd_buf_dict = gc.parse_command_string(robot_cmd_buf)
    outputdir = robot_cmd_buf_dict["outputdir"]
    outputdir = gm.add_trailing_slash(outputdir)
    file_list = (
        outputdir
        + robot_cmd_buf_dict["output"]
        + " "
        + outputdir
        + robot_cmd_buf_dict["log"]
        + " "
        + outputdir
        + robot_cmd_buf_dict["report"]
    )

    # Double checking that files are present.
    shell_rc, out_buf = gc.shell_cmd(
        "ls -1 " + file_list + " 2>/dev/null", show_err=0
    )
    file_list = re.sub("\n", " ", out_buf.rstrip("\n"))

    if file_list == "":
        gp.qprint_timen(
            "No robot output files were found in " + outputdir + "."
        )
        return
    gp.qprint_var(robot_rc, gp.hexa())
    if SAVE_STATUS_POLICY == "FAIL" and robot_rc == 0:
        gp.qprint_timen(
            "The call to robot produced no failures."
            + "  Deleting robot output files."
        )
        gc.shell_cmd("rm -rf " + file_list)
        return

    if gzip:
        gc.shell_cmd("gzip -f " + file_list)
        # Update the values in file_list.
        file_list = re.sub(" ", ".gz ", file_list) + ".gz"

    # It TMP_ROBOT_DIR_PATH is set, it means the caller wanted the robot output initially directed to
    # TMP_ROBOT_DIR_PATH but later moved to FFDC_DIR_PATH.  Otherwise, we're done.

    if os.environ.get("TMP_ROBOT_DIR_PATH", "") == "":
        return

    # We're directing these to the FFDC dir path so that they'll be subjected to FFDC cleanup.
    target_dir_path = os.environ.get(
        "FFDC_DIR_PATH", os.environ.get("HOME", ".") + "/ffdc"
    )
    target_dir_path = gm.add_trailing_slash(target_dir_path)

    targ_file_list = [
        re.sub(".*/", target_dir_path, x) for x in file_list.split(" ")
    ]

    gc.shell_cmd(
        "mv " + file_list + " " + target_dir_path + " >/dev/null", time_out=600
    )

    gp.qprint_timen("New robot log file locations:")
    gp.qprintn("\n".join(targ_file_list))

def robot_cmd_fnc(
    robot_cmd_buf,
    robot_jail=os.environ.get("ROBOT_JAIL", ""),
    quiet=None,
    test_mode=0,
):
    r"""
    Run the robot command string.

    This function will set the various PATH variables correctly so that you are running the proper version of
    all imported files, etc.

    Description of argument(s):
    robot_cmd_buf                   The complete robot command string.
    robot_jail                      Indicates that this is to run in "robot jail" meaning without visibility
                                    to any apolloxxx import files, programs, etc.
    test_mode                       If test_mode is set, this function will not actually run the command.
    """

    quiet = int(gm.dft(quiet, gp.get_stack_var("quiet", 0)))
    gv.valid_value(robot_cmd_buf)

    # Set global variables to aid in cleanup with process_robot_output_files.
    global gcr_last_robot_cmd_buf
    global gcr_last_robot_rc
    gcr_last_robot_cmd_buf = robot_cmd_buf

    # Get globals set by init_robot_test_base_dir_path().
    module = sys.modules["__main__"]
    try:
        ROBOT_TEST_BASE_DIR_PATH = getattr(module, "ROBOT_TEST_BASE_DIR_PATH")
    except NameError:
        init_robot_test_base_dir_path()
        ROBOT_TEST_BASE_DIR_PATH = getattr(module, "ROBOT_TEST_BASE_DIR_PATH")

    ROBOT_TEST_RUNNING_FROM_SB = gm.get_mod_global(
        "ROBOT_TEST_RUNNING_FROM_SB"
    )
    OPENBMCTOOL_DIR_PATH = gm.get_mod_global("OPENBMCTOOL_DIR_PATH")

    if robot_jail == "":
        if ROBOT_TEST_RUNNING_FROM_SB:
            robot_jail = 0
        else:
            robot_jail = 1

    robot_jail = int(robot_jail)
    ROBOT_JAIL = os.environ.get("ROBOT_JAIL", "")
    gp.dprint_vars(
        ROBOT_TEST_BASE_DIR_PATH,
        ROBOT_TEST_RUNNING_FROM_SB,
        ROBOT_JAIL,
        robot_jail,
    )

    # Save PATH and PYTHONPATH to be restored later.
    os.environ["SAVED_PYTHONPATH"] = os.environ.get("PYTHONPATH", "")
    os.environ["SAVED_PATH"] = os.environ.get("PATH", "")

    if robot_jail:
        # Make sure required programs like python and robot can be found in the new restricted PATH.
        required_programs = "python robot"
        # It is expected that there will be a "python" program in the tool base bin path which is really a
        # link to select_version.  Ditto for "robot".  Call each with the --print_only option to get the
        # paths to the "real" programs.
        cmd_buf = (
            "for program in "
            + required_programs
            + " ; do dirname $(${program} --print_only) ; done 2>/dev/null"
        )
        rc, out_buf = gc.shell_cmd(cmd_buf, quiet=1, print_output=0)
        PYTHONPATH = ROBOT_TEST_BASE_DIR_PATH + "lib"
        NEW_PATH_LIST = [ROBOT_TEST_BASE_DIR_PATH + "bin"]
        NEW_PATH_LIST.extend(list(set(out_buf.rstrip("\n").split("\n"))))
        NEW_PATH_LIST.extend(
            [
                "/usr/local/sbin",
                "/usr/local/bin",
                "/usr/sbin",
                "/usr/bin",
                "/sbin",
                "/bin",
                OPENBMCTOOL_DIR_PATH.rstrip("/"),
            ]
        )
        PATH = ":".join(NEW_PATH_LIST)
    else:
        PYTHONPATH = (
            os.environ.get("PYTHONPATH", "")
            + ":"
            + ROBOT_TEST_BASE_DIR_PATH
            + "lib"
        )
        PATH = (
            os.environ.get("PATH", "")
            + ":"
            + ROBOT_TEST_BASE_DIR_PATH
            + "bin"
            + ":"
            + OPENBMCTOOL_DIR_PATH.rstrip("/")
        )

    os.environ["PYTHONPATH"] = PYTHONPATH
    os.environ["PATH"] = PATH
    gp.dprint_vars(PATH, PYTHONPATH)

    os.environ["FFDC_DIR_PATH_STYLE"] = os.environ.get(
        "FFDC_DIR_PATH_STYLE", "1"
    )
    gp.qpissuing(robot_cmd_buf, test_mode)
    if test_mode:
        os.environ["PATH"] = os.environ.get("SAVED_PATH", "")
        os.environ["PYTHONPATH"] = os.environ.get("SAVED_PYTHONPATH", "")
        return True

    if quiet:
        DEVNULL = open(os.devnull, "wb")
        stdout = DEVNULL
    else:
        stdout = None
    sub_proc = subprocess.Popen(robot_cmd_buf, stdout=stdout, shell=True)
    sub_proc.communicate()
    shell_rc = sub_proc.returncode
    os.environ["PATH"] = os.environ.get("SAVED_PATH", "")
    os.environ["PYTHONPATH"] = os.environ.get("SAVED_PYTHONPATH", "")
    gcr_last_robot_rc = shell_rc
    process_robot_output_files()
    if shell_rc != 0:
        gp.print_var(shell_rc, gp.hexa())
        return False

    return True


def reverseVowels(s: str) -> str:
    left, right = 0, len(s) - 1
    vowels = {"a", "e", "i", "o", "u", "A", "E", "I", "O", "U"}
    s_arr = list(s)
    while left < right:
        while s_arr[left] not in vowels:
            left += 1
        while s_arr[right] not in vowels:
            right -= 1
        if left < right:
            s_arr[left], s_arr[right] = s_arr[right], s_arr[left]
        left += 1
        right -= 1

    return "".join(s_arr)

def main():
    print(reverseVowels("hello"))  # holle
    print(reverseVowels("AEIOU"))  # UOIEA
    print(reverseVowels("DesignGUrus"))  # DusUgnGires

if __name__ == "__main__":
    main()


class Solution28:
    def strStr(self, haystack: str, needle: str) -> int:
        if len(needle) == 0:
            return 0
        n = len(haystack)
        m = len(needle)
        ss = " " + haystack
        pp = " " + needle
        jump = [0] * len(pp)
        j = 0
        for i in range(2, m + 1):
            while j > 0 and pp[i] != pp[j + 1]:
                j = jump[j]
            if pp[i] == pp[j + 1]:
                j += 1
            jump[i] = j
        j = 0
        for i in range(1, n + 1):
            while j > 0 and ss[i] != pp[j + 1]:
                j = jump[j]
            if ss[i] == pp[j + 1]:
                j += 1
            if j == m:
                return i - m
        return -1

print(Solution28().strStr("aabaaabaaac", "aabaaac"))

28. 找出字符串中第一个匹配项的下标.py

28. 找出字符串中第一个匹配项的下标.py