import requests
from twilio.rest import Client
import os

# my credentials for https://openweathermap.org/
api_key = os.environ['WEATHER_API']

# my satellite position https://www.latlong.net/
my_lat = 51.507351
my_long = -0.127758

# openweather API endpoint
OMV_Endpoint = "https://api.openweathermap.org/data/2.5/onecall"

# my credentials for Twilio account https://www.twilio.com/docs
account_sid = os.environ['TWILIO_SID']
auth_token = os.environ['TWILIO_TOKEN']
twilio_phone = os.environ['TWILIO_PHONE']

# my personal phone number
my_phone = os.environ['MY_PHONE']

# structuring parameters data
my_data = {
    "lat": my_lat,
    "lon": my_long,
    "appid": api_key,
    "exclude": "current,minutely,daily"
}

# making API request to get weather data for my location
response = requests.get(url=OMV_Endpoint, params=my_data)
response.raise_for_status()
print(response.status_code)
weather_data = response.json()
code_list = []
will_rain = False

# checking weather codes
for i in range(0, 12):
    code = weather_data["hourly"][i]["weather"][0]["id"]
    if code < 700:
        will_rain = True
        print(code)

# sending SMS if the code number is below 700 which means it will rain
if will_rain:
    #print("Bring Umbrella!!!")
    client = Client(account_sid, auth_token)
    message = client.messages \
        .create(
        body="Bring umbrella!!! It will rain in next 12 hours",
        from_=twilio_phone,
        to=my_phone
    )
    print(message.status)


#! python
from pygame.sprite import Sprite
import pygame

class Rectangle(Sprite):
    def __init__(self, colour):
        # Call the parent class (Sprite) constructor
        super(Rectangle, self).__init__()
        self.colour = colour

    def render(self, x, y, width, height):
        self.image = pygame.Surface([width, height])
        self.image.fill(self.colour)

        # Make our top-left corner the passed-in location.
        self.rect = self.image.get_rect()
        self.rect.y = y
        self.rect.x = x


from State import State
from queue import Queue
from time import sleep
import copy
from PriorityQueue import PriorityQueue

from Pac_map_handler import Pac_map_handler

P_CHAR = "P"
Q_CHAR = "Q"
WALL_CHAR = "%"
EMPTY_CHAR = " "
P_FOOD = "1"
Q_FOOD = "2"
BOTH_FOOD = "3"

USE_GOOD_HEURISTIC = False

class A_star:
    def __init__(self, pac_map):
        self.start_state = State(pac_map, None)
        self.explored_states_hash = set()
        self.explored_states_hash_best_depth = dict()
        self.unique_states_hash = set()
        self.num_of_explored_states = 0
        self.num_of_unique_explored_states = 0
        self.goal_state = None
        self.goal_state_is_found = False

        self.frontier_states_queue = PriorityQueue()

    def f(self, state):
        return self.g(state) + self.h(state)

    def g(self, state):
        return state.depth

    def h(self, state):
        if USE_GOOD_HEURISTIC:
            pac_map = state.get_map()
            p_nearest_1_distance = Pac_map_handler.nearest_distance(pac_map, P_CHAR, P_FOOD)
            q_nearest_2_distance = Pac_map_handler.nearest_distance(pac_map, Q_CHAR, Q_FOOD)
            p_nearest_3_distance = Pac_map_handler.nearest_distance(pac_map, P_CHAR, BOTH_FOOD)
            q_nearest_3_distance = Pac_map_handler.nearest_distance(pac_map, Q_CHAR, BOTH_FOOD)
            if p_nearest_1_distance + q_nearest_2_distance == 0:
                return min(p_nearest_3_distance, q_nearest_3_distance)
            else:
                return p_nearest_1_distance + q_nearest_2_distance
        else:
            return Pac_map_handler.count_foods(state.get_map())

    def count_explored_state(self, state):
        self.num_of_explored_states += 1
        if state.get_hash() not in self.unique_states_hash:
            self.unique_states_hash.add(state.get_hash())
            self.num_of_unique_explored_states += 1

    def start(self):
        self.goal_state_is_found = False
        self.frontier_states_queue = PriorityQueue()
        self.frontier_states_queue.push(self.start_state, self.f(self.start_state))
        self.explored_states_hash = set()
        self.explored_states_hash_best_depth = dict()
        self.unique_states_hash = set()
        self.num_of_explored_states = 0
        self.num_of_unique_explored_states = 0

        while not self.frontier_states_queue.empty():
            current_state = self.frontier_states_queue.pop()
            self.count_explored_state(current_state)

            if current_state.get_hash() in self.explored_states_hash:
                continue
            else:
                self.explored_states_hash.add(current_state.get_hash())
                self.explored_states_hash_best_depth[current_state.get_hash()] = current_state.depth

            # Pac_map_handler.print_map(current_state.get_map())
            if self.are_constraints_satisfied(current_state):
                self.goal_state = current_state
                self.goal_state_is_found = True
                return True

            self.do_actions(current_state)
            self.explored_states_hash.add(current_state.get_hash())

        return False

    def print_solution(self, delay=0.2):
        if self.goal_state is None:
            print("No Solution!")
        else:
            current_state = self.goal_state
            states_list = list()
            while current_state is not None:
                states_list.append(current_state)
                current_state = current_state.get_parent()

            for state in reversed(states_list):
                Pac_map_handler.print_map(state.get_map())
                sleep(delay)

            print("Explored States: " + str(self.num_of_explored_states))
            print("Explored Unique States: " + str(self.num_of_unique_explored_states))
            print("Goal Depth: " + str(len(states_list)))

    def are_constraints_satisfied(self, state: State):
        for line in state.get_map():
            if P_FOOD in line or Q_FOOD in line or BOTH_FOOD in line:
                return False
        return True

    def do_actions(self, current_state):
        pac_map = current_state.get_map()
        p_row, p_col = Pac_map_handler.find_in_map(pac_map, P_CHAR)
        q_row, q_col = Pac_map_handler.find_in_map(pac_map, Q_CHAR)
        # P MOVEMENT
        self.move_p(current_state, pac_map, p_row, p_col)
        # Q MOVEMENT
        self.move_q(current_state, pac_map, q_row, q_col)

    def move_p(self, current_state, pac_map, row, col):
        new_map = Pac_map_handler.move_p_up(copy.deepcopy(pac_map), row, col)
        self.add_to_frontier(new_map, current_state)

        new_map = Pac_map_handler.move_p_left(copy.deepcopy(pac_map), row, col)
        self.add_to_frontier(new_map, current_state)

        new_map = Pac_map_handler.move_p_down(copy.deepcopy(pac_map), row, col)
        self.add_to_frontier(new_map, current_state)

        new_map = Pac_map_handler.move_p_right(copy.deepcopy(pac_map), row, col)
        self.add_to_frontier(new_map, current_state)

    def move_q(self, current_state, pac_map, row, col):
        new_map = Pac_map_handler.move_q_up(copy.deepcopy(pac_map), row, col)
        self.add_to_frontier(new_map, current_state)

        new_map = Pac_map_handler.move_q_left(copy.deepcopy(pac_map), row, col)
        self.add_to_frontier(new_map, current_state)

        new_map = Pac_map_handler.move_q_down(copy.deepcopy(pac_map), row, col)
        self.add_to_frontier(new_map, current_state)

        new_map = Pac_map_handler.move_q_right(copy.deepcopy(pac_map), row, col)
        self.add_to_frontier(new_map, current_state)

    def add_to_frontier(self, new_map, current_state):
        new_state = State(new_map, current_state)
        if not new_state.get_hash() in self.explored_states_hash:
            self.frontier_states_queue.push(new_state, self.f(new_state))


import random
import math

import pygame as pg
from pygame import mixer

# def print_hi(name):
#     # Use a breakpoint in the code line below to debug your script.
#     print(f'Hi, {name}')  # Press Ctrl+F8 to toggle the breakpoint.
#
#
# # Press the green button in the gutter to run the script.
# if __name__ == '__main__':
#     print_hi('PyCharm')
#
# # See PyCharm help at https://www.jetbrains.com/help/pycharm/

# Intialize the pg
pg.init()

# create the screen
screen = pg.display.set_mode((800, 600))

# Title and Icon
pg.display.set_caption("monster")
icon = pg.image.load('image/monster.png')
pg.display.set_icon(icon)

# Background
background = pg.image.load('image/space.png')
background = pg.transform.scale(background, (800, 600))
# Background sound
mixer.music.load('sound/background.wav')
# mixer.music.play(1)

# Player
playerImg = pg.image.load('image/player.png')
# set image size
playerImg = pg.transform.scale(playerImg, (60, 60))
playerX = 370
playerY = 480
playerX_change = 0
playerX_speed = 0.5

# enemy
enemyImg = []
enemyX = []
enemyY = []
enemyX_change = []
enemyY_change = []
num_of_enemies = 6

for i in range(num_of_enemies):
    # set image size
    enemyImg.append(pg.transform.scale(pg.image.load('image/monster.png'), (60, 60)))
    enemyX.append(random.randint(0, 735))
    enemyY.append(random.randint(50, 150))
    enemyX_change.append(0.3)
    enemyY_change.append(40)

# bullet

# Ready - You can't see the bullet on the screen
# Fire - The bullet is currently moving
bulletImg = pg.image.load('image/bullet.png')
# set image size
bulletImg = pg.transform.scale(bulletImg, (40, 20))
bulletX = 0
bulletY = 480
bulletX_change = 0
bulletY_change = 0.5
bullet_state = "ready"

# Score
score_value = 0
font = pg.font.Font('freesansbold.ttf', 32)

textX = 10
textY = 10

# Game Over text
over_font = pg.font.Font('freesansbold.ttf', 64)
game_state = "start"

def show_score(x, y):
    score = font.render("Score :" + str(score_value), True, (255, 255, 255))
    screen.blit(score, (x, y))

def game_over_text():
    over_text = font.render("GAME OVER", True, (255, 255, 255))
    screen.blit(over_text, (300, 300))

# built player
def player(x, y):
    screen.blit(playerImg, (x, y))

# built enemy
def enemy(x, y, i):
    screen.blit(enemyImg[i], (x, y))

# built bullet
def fire_bullet(x, y):
    global bullet_state
    bullet_state = "fire"
    screen.blit(bulletImg, (x + 10, y))

# collision detection
def isCollision(enemyX, enemyY, bulletX, bulletY):
    distance = math.sqrt(math.pow(enemyX - bulletX, 2) + math.pow(enemyY - bulletY, 2))
    if distance < 30:
        return True
    else:
        return False

# Game Loop
running = True
while running:
    # set background RGB
    screen.fill((0, 255, 0))
    # Background Image
    screen.blit(background, (0, 0))

    # listen event
    for event in pg.event.get():
        # close screen
        if event.type == pg.QUIT:
            running = False

        # if keystroke is pressed check whether its right or left
        if event.type == pg.KEYDOWN:
            if event.key == pg.K_LEFT:
                playerX_change = -playerX_speed
            if event.key == pg.K_RIGHT:
                playerX_change = playerX_speed
            if event.key == pg.K_SPACE and bullet_state is "ready":
                # Get the current x coordinate of the spaceship
                bullet_Sound = mixer.Sound('sound/laser.wav')
                # bullet_Sound.play()
                bulletX = playerX
                fire_bullet(bulletX, bulletY)

        if event.type == pg.KEYUP:
            if event.key == pg.K_LEFT or event.key == pg.K_RIGHT:
                playerX_change = 0

    if game_state is "gameover":
        game_over_text()
    else:
        # player movement
        playerX += playerX_change
        # setting border of player moving
        if playerX <= 0:
            playerX = 0
        elif playerX >= 736:
            playerX = 736

        for i in range(num_of_enemies):

            # Game Over
            game_over = isCollision(enemyX[i], enemyY[i], playerX, playerY)
            if game_over:
                game_state = "gameover"
                game_over_text()
                for j in range(num_of_enemies):
                    enemyY[i] = 2000
                break

            # enemy movement
            enemyX[i] += enemyX_change[i]
            # setting border of enemy moving
            if enemyX[i] <= 0:
                enemyX_change[i] = -enemyX_change[i]
                enemyY[i] += enemyY_change[i]
            elif enemyX[i] >= 736:
                enemyX_change[i] = -enemyX_change[i]
                enemyY[i] += enemyY_change[i]

            # Collision
            collision = isCollision(enemyX[i], enemyY[i], bulletX, bulletY)
            if collision:
                explosion_Sound = mixer.Sound('sound/explosion.wav')
                # explosion_Sound.play()
                bulletY = 480
                bullet_state = "ready"
                score_value += 1
                # print(score)
                enemyX[i] = random.randint(0, 735)
                enemyY[i] = random.randint(50, 150)

            enemy(enemyX[i], enemyY[i], i)

        # bullet movement
        if bulletY <= 0:
            bulletY = 480
            bullet_state = "ready"

        if bullet_state is "fire":
            fire_bullet(bulletX, bulletY)
            bulletY -= bulletY_change

    player(playerX, playerY)

    show_score(textX, textY)
    # update screen
    pg.display.update()


from datasette.app import Datasette
import pytest

@pytest.mark.asyncio
async def test_plugin_is_installed(tmpdir):
    templates = tmpdir / "templates"
    templates.mkdir()
    pages = tmpdir / "templates" / "pages"
    pages.mkdir()
    (pages / "demo.html").write_text(
        "request.args = {{ request.args._data|safe }}", "utf-8"
    )
    datasette = Datasette([], memory=True, template_dir=str(templates))
    response = await datasette.client.get("/demo?foo=bar")
    assert response.status_code == 200
    assert response.text == "request.args = {'foo': ['bar']}"


# Team Project: Toward Sustainable Cities through simulation
# testing RL

from env_tlstest import TLSEnv

from stable_baselines3 import PPO, A2C

env = TLSEnv(netfile= "data/cross.sumocfg", reward_fn="dwt")

# obs = env.reset()
# env.render()

print(env.observation_space)
print(env.action_space)
print(env.action_space.sample())

# GO_LEFT = 0
# # Hardcoded best agent: always go left!
# n_steps = 20
# for step in range(n_steps):
#   print("Step {}".format(step + 1))
#   obs, reward, done, info = env.step(GO_LEFT)
#   print('obs=', obs, 'reward=', reward, 'done=', done)
#   env.render()
#   if done:
#     print("Goal reached!", "reward=", reward)
#     break

model = A2C('MlpPolicy', env, verbose=1, gamma=0.99999)
model.learn(12000)
# Test the trained agent
obs = env.reset()
n_steps = 1000
for step in range(n_steps):
    action, _ = model.predict(obs, deterministic=True)
    print(f"Step {step+1}")
    print("Action: ", action)
    obs, reward, done, info = env.step(action)
    print('obs=', obs, 'reward=', reward, 'done=', done)
    # env.render(mode='console')
    if done:
    # Note that the VecEnv resets automatically
    # when a done signal is encountered
        print("Goal reached!", "reward=", reward)

env.close()


import visual_novel.getAbsolutePath as getAbsolutePath
import tkinter.messagebox
import os

script_dir = os.path.dirname(__file__)
SAVEDIRECTORY = 'assets/saves/'

class Arbre:
    u"""
    Représente un Arbre Binaire

    Contient des noeuds qui contiennent eux-même
    0, 1 ou 2 autres noeuds : un fils gauche et un fils droit
    L'initialisation de la class Arbre crée un noeud racine.
    Il est possible de modifier, d'ajouter ou d'accéder aux
    autres noeuds en utilisant les méthodes de la class Arbre.

    Attributs:
    ----------
        value : str
            La valeur associée au noeud de l'arbre
        file : str
            Le nom du fichier associé au noeud de l'arbre
        left : Arbre | None
            Le fils gauche du noeud. Peut contenir un autre noeud
            de la class Arbre ou None par défaut
        right : Arbre | None
            Le fils droit du noeud. Peut contenir un autre noeud
            de la class Arbre ou None par défaut

    Méthodes:
    ---------
    getValue()
        Renvoie l'attribut value du noeud actuel de l'instance de Arbre
    getFile()
        Renvoie l'attribut file du noeud actuel de l'instance de Arbre
    getLeft()
        Renvoie le fils gauche du noeud actuel
    getRight()
        Renvoie le fils droti du noeud actuel
    addLeft(value: str, file: str)
        Change le fils gauche du noeud actuel en un nouveau noeud
        ayant comme attributs value et file
    addRight(value: str, file: str)
        Change le fils droit du noeud actuel en un nouveau noeud
        ayant comme attributs value et file
    """
    choices = []

    def __init__(self, value: str, file: str, left=None, right=None) -> None:
        u"""
        Initialise le noeud racine de l'arbre binaire ou un de
        ses noeuds.

        Préconditions:
            value :  str
                correspond à la valeur détenue par le noeud.
            file : str
                est le nom du fichier associé au noeud.
            left : Arbre | None
                est le fils gauche du noeud. Peut contenir
                un sous noeud ou None par défaut.
            right : Arbre | None
                est le fils droit du noeud. Peut contenir
                un sous noeud ou None par défaut.

        Postconditions:
            Initialise une instance de la class Arbre
            en créant un noeud à l'aide des arguments donnés
        """
        self._value = value
        self._left = left
        self._right = right
        self._file = file

    def __str__(self) -> str:
        u"""
        Affiche l'arbre binaire à partir du noeud actuel.

        Postcondition:
            Affiche la valeur et le fichier du noeud actuel de
            l'arbre binaire ainsi que son fils gauche et son fils droit.
            valeur[fichier](fils gauche)(fils droit)
        """
        return f'{self._value}[{self._file}]({self._left}, {self._right})'

    def getValue(self) -> str:
        u"""
        Renvoie la valeur associée au noeud actuel
        """
        return self._value

    def getFile(self) -> str:
        u"""
        Renvoie le nom du fichier associé au noeud actuel
        """
        return self._file

    def getLeft(self, isConstructing = False) -> 'Arbre':
        u"""
        Renvoie le fils gauche du noeud actuel

        Précondition:
            isConstructing : bool
                si on enregistre (False) ou non le choix dans l'arbre.
                Cela est utilisé pour la construction de l'arbre

        Postcondition:
            Renvoie le fis gauche du noeud actuel.
            Cela peut être un autre noeud de la class Arbre
            ou None si le noeud actuel ne possède pas de fils
            gauche.
        """
        if not isConstructing:
            self.choices.append('L')
        return self._left

    def getRight(self, isConstructing = False) -> 'Arbre':
        u"""
        Renvoie le fils droit du noeud actuel

        Précondition:
            isConstructing : bool
                si on enregistre (False) ou non le choix dans l'arbre.
                Cela est utilisé pour la construction de l'arbre

        Postcondition:
            Renvoie le fis droit du noeud actuel.
            Cela peut être un autre noeud de la class Arbre
            ou None si le noeud actuel ne possède pas de fils
            droit.
        """
        if not isConstructing:
            self.choices.append('R')
        return self._right

    def addLeft(self, value: str, file: str) -> None:
        u"""
        Ajoute un fils gauche au noeud actuel

        Cela ajoute un fils gauche à partir du noeud actuel et non
        pas en bas de l'Arbre. Si le noeud actuel possède déjà un fils
        gauche, son contenu et ses enfants seront supprimés et remplacés
        par le nouveau noeud.

        Préconditions:
            value : str
                est la valeur qui sera associée au fils gauche
                du noeud actuel.
            file : str
                est le nom du fichier qui sera associé au fils
                gauche du noeud actuel.

        Postcondition:
            Change le fils gauche du noeud actuel en un
            nouveau sous-noeud à partir des arguments données.
        """
        self._left = Arbre(value, file)

    def addRight(self, value: str, file: str) -> None:
        u"""
        Ajoute un fils droit au noeud actuel

        Cela ajoute un fils droit à partir du noeud actuel et non
        pas en bas de l'Arbre. Si le noeud actuel possède déjà un fils
        droit, son contenu et ses enfants seront supprimés et remplacés
        par le nouveau noeud.

        Préconditions:
            value : str
                est la valeur qui sera associée au fils droit
                du noeud actuel.
            file : str
                est le nom du fichier qui sera associé au fils
                droit du noeud actuel.

        Postcondition:
            Change le fils droit du noeud actuel en un
            nouveau sous-noeud à partir des arguments données.
        """
        self._right = Arbre(value, file)

def writeSave(abr: 'Arbre'):
    u"""
    Écris un fichier de sauvegarde de l'état actuel de
    l'arbre. Ce fichier contient les choix effectués,
    gauche (L) ou droite(R).

    Précondition:
        abr : Arbre
            L'Arbre actuel qu'il faut sauvegarder.

    Postcondition:
        Écris un fichier contenant les choix
    """
    choices = ' '.join(abr.choices)
    print(choices)
    filelocation = getAbsolutePath.getAbsolutePath(
        script_dir, f'{SAVEDIRECTORY}save.txt')
    try:
        with open(filelocation, 'w') as f:
            f.write(choices)
        tkinter.messagebox.showinfo(
            "Sauvegarde réussie",  "La partie a été sauvergardée !")
    except Exception:
        tkinter.messagebox.showerror(
            "Échec de la sauvegarde", "La sauvegarde de la partie a échoué. Veuillez réessayer.")

def loadSave() -> list:
    u"""
    Récupère la dernière sauvegarde si elle existe.
    Renvoie la liste de choix identique à celle qui
    a été entrée. Renvoie une erreur s'il n'y a pas
    de sauvegarde.

    Postcondition:
        Renvoie une liste de choix
    """
    filelocation = getAbsolutePath.getAbsolutePath(script_dir, f'{SAVEDIRECTORY}save.txt')
    try:
        with open(filelocation, 'r') as f:
            line = f.read()
        return line.split(' ')
    except Exception:
        print('Error')

def saveToTree(abr: 'Arbre', save: list) -> 'Arbre':
    u"""
    Convertie récursivement une liste de choix en un arbre à la
    position équivalent à ces choix.

    Préconditions:
        abr : Arbre
            Est l'Arbre principale. Lors de l'appel, il correspond à
            l'arbre complet de l'histoire. Au fils des appels, on
            parcours l'arbre
        save : list
            Est la sauvegarde récupérée. Elle évolue au file des appels

    Postcondition:
        Renvoie un arbre à la position de la sauvegarde
    """
    print(abr)
    print(save)
    print()
    if len(save) == 0:
        print('arbre',abr)
        return abr
    if save[0] == 'L':
        return saveToTree(abr.getLeft(True), save[1:])
    else:
        return saveToTree(abr.getRight(True), save[1:])

if __name__ == "__main__":
    abr = Arbre('Init', 'init.txt')
    abr.addLeft('L1', 'l1.txt')
    abrL = abr.getLeft(True)
    abrL.addRight('R2', '')
    abrLR = abr.getRight(True)
    print(abr.choices)
    print(abr)
    writeSave(abr)
    print(loadSave())
    print(saveToTree(abr, loadSave()))


from fastapi import APIRouter, Response;
from .lib.factory import Factory;

router = APIRouter();

@router.get('/{repo}/{mod}/next')
async def get_Module(response: Response, repo: str, mod: str, key: str, text: bool = False):
    mgr = Factory.getRepository(repo);
    mod = mgr.getModule(mod);

    if mod is not None:
        mod = Factory.fromModule(mod);
        mod.setKey(key);
        mod.increment();

        ret = {
            'Key': mod.getKey(),
            'Text': mod.getText(),
        };

        if not text:
            del ret['Text'];

        return ret;

    response.status_code = 404;
    return [];


from __future__ import annotations
import os
import sys
import torch
import logging
import numpy as np
from typing import Any, Optional, Union, Callable
from dataclasses import dataclass, field, asdict
from datasets import Dataset
from transformers import (
    Wav2Vec2Processor,
    HfArgumentParser,
    TrainingArguments as HFTrainingArguments,
    set_seed,
    Trainer,
    AutoConfig,
    AutoModelForCTC,
    EarlyStoppingCallback
)
from transformers.trainer_utils import get_last_checkpoint, is_main_process
from transformers.trainer_pt_utils import get_parameter_names
from huggingsound.metrics import cer, wer

logger = logging.getLogger(__name__)

@dataclass
class ModelArguments:
    """
    Model arguments

    Parameters:
    ----------
    freeze_feature_extractor: Optional[bool] = True
        Whether to freeze the feature extractor layers of the model.

    attention_dropout: Optional[float] = 0.1
        The dropout ratio for the attention probabilities.

    activation_dropout: Optional[float] = 0.1
        The dropout ratio for activations inside the fully connected layer.

    hidden_dropout: Optional[float] = 0.1
        The dropout probabilitiy for all fully connected layers in the embeddings, encoder, and pooler.

    feat_proj_dropout: Optional[float] = 0.1
        The dropout probabilitiy for all 1D convolutional layers in feature extractor.

    final_dropout: Optional[float] = 0.1
        The dropout probabilitiy for CTC head.

    mask_time_prob: Optional[float] = 0.05
        Propability of each feature vector along the time axis to be chosen as the start of the vector
        span to be masked. Approximately ``mask_time_prob * sequence_length // mask_time_length`` feature
        vectors will be masked along the time axis. This is only relevant if ``apply_spec_augment is True``.

    mask_time_length: Optional[int] = 10
        Length of vector span to mask along the time axis.

    mask_feature_prob: Optional[float] = 0.0
        Propability of each feature vector along the feature axis to be chosen as the start of the vector span to
        be masked. Approximately ``mask_time_prob * hidden_size // mask_time_length`` feature vectors will be
        masked along the time axis. This is only relevant if ``apply_spec_augment is True``."

    mask_feature_length: Optional[int] = 10
        Length of vector span to mask along the feature axis.

    layerdrop: Optional[float] = 0.0
        The probability to randomly drops layers at training time. For reference see https://arxiv.org/abs/1909.11556

    apply_spec_augment: Optional[bool] = True
        Whether to apply *SpecAugment* data augmentation to the outputs of the feature extractor. For reference see <https://arxiv.org/abs/1904.08779>"

    ctc_loss_reduction: Optional[str] = "sum"
        Specifies the reduction to apply to the output of ``torch.nn.CTCLoss``. Can be 'sum' or 'mean'.

    ctc_zero_infinity: Optional[bool] = False
        Whether to zero infinite losses and the associated gradients of ``torch.nn.CTCLoss``. Infinite losses
        mainly occur when the inputs are too short to be aligned to the targets
    """

    freeze_feature_extractor: bool = field(default=True)
    attention_dropout: float = field(default=0.1)
    activation_dropout: float = field(default=0.1)
    hidden_dropout: float = field(default=0.1)
    feat_proj_dropout: float = field(default=0.1)
    final_dropout: float = field(default=0.1)
    mask_time_prob: float = field(default=0.05)
    mask_time_length: int = field(default=10)
    mask_feature_prob: float = field(default=0.0)
    mask_feature_length: int = field(default=10)
    layerdrop: float = field(default=0.0)
    apply_spec_augment: bool = field(default=True)
    ctc_loss_reduction: str = field(default="sum")
    ctc_zero_infinity: bool = field(default=False)

@dataclass
class TrainingArguments:
    """
    Training arguments

    Parameters:
    ----------
    overwrite_output_dir: Optional[bool] = False
        If True, it will overwrite the content of the output directory.
        If False, it will continue training if output directory points to a checkpoint directory.

    ignore_pretrained_weights: Optional[bool] = False
        If True, it will initializar all the model's weight randonly, i.e., it it will not use the pre-trained model weights during training.

    dataloader_num_workers: Optional[int] = 0
        Number of subprocesses to use for data loading (PyTorch only). 0 means that the data will be loaded in the main process.

    learning_rate: Optional[float] = 3e-4
        The learning rate for AdamW optimizer.

    min_learning_rate: Optional[float] = 0.0
        The minimum learning rate for AdamW optimizer. (only used if lr_warmup_steps or lr_decay_steps are set)

    weight_decay: Optional[float] = 0.0
        The weight decay to apply (if not zero) to all layers except all bias and LayerNorm weights in AdamW optimizer.

    adam_beta1: Optional[float] = 0.9
        The beta1 hyperparameter for the AdamW optimizer.

    adam_beta2: Optional[float] = 0.999
        The beta2 hyperparameter for the AdamW optimizer.

    adam_epsilon: Optional[float] = 1e-8
        The epsilon hyperparameter for the AdamW optimizer.

    max_grad_norm: Optional[float] = 1.0
        Maximum gradient norm (for gradient clipping).

    lr_warmup_steps: Optional[int] = 0
        Number of warmup steps for learning rate scheduler at the beginning of training.

    lr_decay_steps: Optional[int] = 0
        Number of decay steps for learning rate scheduler at the end of training.

    eval_steps: Optional[int] = None
        Run an evaluation every X steps.

    group_by_length: Optional[bool] = True
        Whether or not to group together samples of roughly the same length in the training dataset (to minimize padding applied and be more efficient).

    gradient_accumulation_steps: Optional[int] = 1
        Number of updates steps to accumulate before performing a backward/update pass.

    gradient_checkpointing: Optional[bool] = True
        If True, use gradient checkpointing to save memory at the expense of slower backward pass.

    pad_to_multiple_of: Optional[int] = None
        If set will pad the sequence to a multiple of the provided value.
        This is especially useful to enable the use of Tensor Cores on NVIDIA hardware with compute capability >= 7.5 (Volta).

    per_device_train_batch_size: Optional[int] = 8
        The batch size per GPU/TPU core/CPU for training.

    per_device_eval_batch_size: Optional[int] = 8
        The batch size per GPU/TPU core/CPU for evaluation.

    fp16: Optional[bool] = False
        Whether to use 16-bit (mixed) precision training instead of 32-bit training.

    use_8bit_optimizer: Optional[bool] = False
        Whether to use 8-bit optimizer.

    logging_steps: Optional[int] = 100
        Log every X updates steps.

    num_train_epochs: Optional[float] = 3.0
        Total number of training epochs to perform (if not an integer, will perform the decimal part percents of
        the last epoch before stopping training).

    max_steps: Optional[int] = 0
        If set to a positive number, the total number of training steps to perform. Overrides num_train_epochs.

    report_to: Optional[list[str]] = ["none"]
        The list of integrations to report the results and logs to. Supported platforms are "azure_ml",
        "comet_ml", "mlflow", "tensorboard" and "wandb". Use "all" to report to
        all integrations installed, "none" for no integrations.

    save_steps: Optional[int] = 500
        Number of updates steps before two checkpoint saves.

    save_total_limit: Optional[int] = None
        Limit the total amount of checkpoints. Deletes the older checkpoints in the output_dir. Default is unlimited checkpoints

    metric_for_best_model: Optional[str] = "cer"
        The metric to use to compare two different models.

    _n_gpu: Optional[int] = 1
        Numbers of gpus to use for training.

    seed: Optional[int] = None
        Random seed that will be set at the beginning of training. To ensure reproducibility across runs.

    training_step_callbacks: list[Callable[transformers.Trainer, float]] = []
        A list of callbacks that will be called at the end of each training step.
        The trainer, model and the current loss will be passed to those functions: f(trainer: transformers.Trainer, loss: float)

    batch_creation_callbacks: list[Callable[ list[dict[str, list[int]]] ]] = []
        A list of callbacks that will be called at the end of each batch creation.
        The batch will be passed to those functions: f(batch: list[dict[str, list[int]]])

    evaluation_callbacks: list[Callable[dict, list, list]] = []
        A list of callbacks that will be called at the end of each evaluation step.
        The metrics (WER, CER), references and predictions will be passed to those functions: f(metrics: dict, references: list, predictions: list)

    metrics_batch_size: Optional[int] = None
        Batch size to use for evaluation. When this value is specified, the evaluation function will chunk the data into
        batches of the specified size and compute the metrics on each batch.
        After all batches are computed, the function will compute the average metrics over all batches.
        (You will probably need to define this if you have memory issues).

    show_dataset_stats: Optional[bool] = False
        Whether to show dataset stats

    early_stopping_patience: Optional[int] = None
        Use with metric_for_best_model to stop training when the specified metric worsens for early_stopping_patience evaluation calls.

    load_best_model_at_end: Optional[bool] = False
        Whether to load the best model at the end of training.

    """

    overwrite_output_dir: bool = field(default=False)
    ignore_pretrained_weights: bool = field(default=False)
    dataloader_num_workers: int = field(default=0)
    learning_rate: float = field(default=3e-4)
    min_learning_rate: float = field(default=0.0)
    weight_decay: float = field(default=0.0)
    adam_beta1: float = field(default=0.9)
    adam_beta2: float = field(default=0.999)
    adam_epsilon: float = field(default=1e-8)
    max_grad_norm: float = field(default=1.0)
    lr_warmup_steps: int = field(default=0)
    lr_decay_steps: int = field(default=0)
    eval_steps: int = field(default=None)
    group_by_length: bool = field(default=True)
    length_column_name: str = field(default="length")
    gradient_accumulation_steps: int = field(default=1)
    gradient_checkpointing: bool = field(default=True)
    pad_to_multiple_of: int = field(default=None)
    per_device_train_batch_size: int = field(default=8)
    per_device_eval_batch_size: int = field(default=8)
    fp16: bool = field(default=False)
    use_8bit_optimizer: bool = field(default=False)
    logging_steps: int = field(default=100)
    num_train_epochs: float = field(default=3.0)
    max_steps: int = field(default=0)
    report_to: list[str] = field(default_factory=lambda: ["none"])
    save_steps: int = field(default=500)
    save_total_limit: int = field(default=None)
    metric_for_best_model: str = field(default=None)
    _n_gpu: int = field(default=1)
    seed: int = field(default=42)
    training_step_callbacks: list[Callable] = field(default_factory=lambda: [])
    batch_creation_callbacks: list[Callable] = field(default_factory=lambda: [])
    evaluation_callbacks: list[Callable] = field(default_factory=lambda: [])
    metrics_batch_size: int = field(default=None)
    show_dataset_stats: bool = field(default=True)
    early_stopping_patience: int = field(default=None)
    load_best_model_at_end: bool = field(default=False)

class CTCDataCollatorWithPadding:
    """
    Data collator that will dynamically pad the inputs received.

    Parameters:
    ----------
        processor: Wav2Vec2Processor
            The processor used for proccessing the data.

        batch_creation_callbacks: Optional[list[dict[str, Union[list[int], torch.Tensor]]]] = None
            A list of callbacks that will be called at the end of each batch creation.

        pad_to_multiple_of: Optional[int] = None
            If set will pad the sequence to a multiple of the provided value.
            This is especially useful to enable the use of Tensor Cores on NVIDIA hardware with compute capability >= 7.5 (Volta).
    """

    def __init__(self, processor: Wav2Vec2Processor, batch_creation_callbacks: Optional[list[Callable]] = None,
                 pad_to_multiple_of: Optional[int] = None):
        self.processor = processor
        self.batch_creation_callbacks = batch_creation_callbacks
        self.pad_to_multiple_of = pad_to_multiple_of

    def __call__(self, features: list[dict[str, Union[list[int], torch.Tensor]]]) -> dict[str, torch.Tensor]:
        # split inputs and labels since they have to be of different lenghts and need
        # different padding methods

        if self.batch_creation_callbacks is not None:
            for callback in self.batch_creation_callbacks:
                callback(features)

        input_features = [{"input_values": feature["input_values"]} for feature in features]
        labels = [{"input_ids": feature["labels"]} for feature in features]

        batch = self.processor.pad(
            input_features=input_features,
            padding=True,
            pad_to_multiple_of=self.pad_to_multiple_of,
            return_tensors="pt",
        )

        labels_batch = self.processor.pad(
            labels=labels,
            padding=True,
            pad_to_multiple_of=self.pad_to_multiple_of,
            return_tensors="pt",
        )

        # replace padding with -100 to ignore loss correctly
        batch["labels"] = labels_batch["input_ids"].masked_fill(labels_batch.attention_mask.ne(1), -100)

        return batch

class CTCTrainer(Trainer):

    """
    Data collator that will dynamically pad the inputs received.

    Parameters:
    ----------
        min_learning_rate: Optional[float] = None
            The minimum learning rate to use.

        lr_warmup_steps: Optional[int] = None
            The number of steps to use for a warmup.

        lr_decay_steps: Optional[int] = None
            The number of steps to use for a decay.

        training_step_callbacks: list[Callable[transformers.Trainer, float]] = []
            A list of callbacks that will be called at the end of each training step.
            The trainer, model and the current loss will be passed to those functions: f(trainer: transformers.Trainer, loss: float)
    """

    def __init__(self, min_learning_rate=None, lr_warmup_steps=None, lr_decay_steps=None,
                 training_step_callbacks: Optional[list[Callable]] = None, use_8bit_optimizer: Optional[bool] = False, **kwargs):

        super().__init__(**kwargs)
        self.min_learning_rate = min_learning_rate
        self.lr_warmup_steps = lr_warmup_steps
        self.lr_decay_steps = lr_decay_steps
        self.training_step_callbacks = training_step_callbacks
        self.use_8bit_optimizer = use_8bit_optimizer

    def create_optimizer(self):

        decay_parameters = get_parameter_names(self.model, [torch.nn.LayerNorm])
        decay_parameters = [name for name in decay_parameters if "bias" not in name]
        optimizer_grouped_parameters = [
            {
                "params": [p for n, p in self.model.named_parameters() if n in decay_parameters],
                "weight_decay": self.args.weight_decay,
            },
            {
                "params": [p for n, p in self.model.named_parameters() if n not in decay_parameters],
                "weight_decay": 0.0,
            },
        ]

        optimizer_class = torch.optim.AdamW

        if self.use_8bit_optimizer:

            try:
                import bitsandbytes as bnb
            except ImportError:
                raise ImportError("To use 8bit optimizer please install the bitsandbytes from https://github.com/facebookresearch/bitsandbytes")

            optimizer_class = bnb.optim.AdamW

        self.optimizer = optimizer_class(
            params=optimizer_grouped_parameters,
            lr=self.args.learning_rate,
            betas=(self.args.adam_beta1, self.args.adam_beta2),
            eps=self.args.adam_epsilon,
        )

        return self.optimizer

    def create_scheduler(self, num_training_steps: int, optimizer: torch.optim.Optimizer = None):
        """
        Setup the scheduler. This scheduler supports a warmup phase where the learning rate linearly increases
        at the beginning of the training. And a decay phase where the learning rate decreases over time at the end of the training.

        Parameters:
        ----------
            num_training_steps (int): The number of total training steps to do.
        """

        min_lr_ratio = self.min_learning_rate / self.args.learning_rate

        def _lr_lambda(current_step, num_training_steps=num_training_steps, lr_decay_steps=self.lr_decay_steps,
                       lr_warmup_steps=self.lr_warmup_steps, min_lr_ratio=min_lr_ratio):

            if lr_warmup_steps is not None and current_step < lr_warmup_steps: # warmup phase
                return max(
                    min_lr_ratio, float(current_step) / float(max(1, lr_warmup_steps))
                )
            elif lr_decay_steps is not None and current_step >= num_training_steps - lr_decay_steps: # decay phase
                return max(
                    min_lr_ratio, float(num_training_steps - current_step) / float(max(1, lr_decay_steps))
                )
            else: # constant learning rate phase
                return 1

        self.lr_scheduler = torch.optim.lr_scheduler.LambdaLR(self.optimizer, _lr_lambda)

    def training_step(self, model: torch.nn.Module, inputs: dict[str, Union[torch.Tensor, Any]]) -> torch.Tensor:
        """
        Perform a training step on a batch of inputs.

        Parameters:
        ----------
            model (:obj:`nn.Module`):
                The model to train.
            inputs (:obj:`dict[str, Union[torch.Tensor, Any]]`):
                The inputs and targets of the model.

                The dictionary will be unpacked before being fed to the model. Most models expect the targets under the
                argument :obj:`labels`. Check your model's documentation for all accepted arguments.

        Returns:
        ----------
            :obj:`torch.Tensor`: The tensor with training loss on this batch.
        """

        model.train()
        inputs = self._prepare_inputs(inputs)

        if (hasattr(self, 'use_amp') and self.use_amp) or (hasattr(self, 'use_cuda_amp') and self.use_cuda_amp):
            with torch.cuda.amp.autocast():
                loss = self.compute_loss(model, inputs)
        else:
            loss = self.compute_loss(model, inputs)

        if self.args.n_gpu > 1:
            if model.module.config.ctc_loss_reduction == "mean":
                loss = loss.mean()
            elif model.module.config.ctc_loss_reduction == "sum":
                loss = loss.sum() / (inputs["labels"] >= 0).sum()
            else:
                raise ValueError(f"{model.config.ctc_loss_reduction} is not valid. Choose one of ['mean', 'sum']")

        if self.args.gradient_accumulation_steps > 1:
            loss = loss / self.args.gradient_accumulation_steps

        if (hasattr(self, 'use_amp') and self.use_amp) or (hasattr(self, 'use_cuda_amp') and self.use_cuda_amp):
            self.scaler.scale(loss).backward()
        elif self.deepspeed:
            self.deepspeed.backward(loss)
        else:
            loss.backward()

        if self.training_step_callbacks is not None:
            for callback in self.training_step_callbacks:
                callback(self, float(loss.detach()))

        return loss.detach()

def finetune_ctc(model_name_or_path: str, output_dir: str, processor: Wav2Vec2Processor, train_dataset: Dataset,
                 eval_dataset: Optional[Dataset] = None, device: Optional[str] = "cpu",
                 training_args: Optional[TrainingArguments] = None, model_args: Optional[ModelArguments] = None):
    """
    Finetunes the CTC model.

    Parameters:
    ----------

    model_name_or_path : str
        The path to the model or the model identifier from huggingface.co/models.

    output_dir : str
        The output directory where the model checkpoints will be written.

    processor : transformers.Wav2Vec2Processor
        The audio processor object.

    train_dataset : transformers.Dataset
        The training dataset.

    eval_dataset : Optional[transformers.Dataset] = None
        The evaluation dataset.

    device : str = "cpu"
        The device to run the model training on.

    training_args : Optional[TrainingArguments] = None
        The training arguments.

    model_args : Optional[ModelArguments] = None
        The model arguments.

    """

    if training_args is None:
        training_args = TrainingArguments()

    if model_args is None:
        model_args = ModelArguments()

    hf_arg_parser = HfArgumentParser((HFTrainingArguments))
    training_args_dict = asdict(training_args)
    training_args_dict["output_dir"] = output_dir
    training_args_dict["device"] = device
    training_args_dict["no_cuda"] = device == "cpu"
    training_args_dict["do_train"] = True

    if eval_dataset is not None:
        training_args_dict["do_eval"] = True
        training_args_dict["evaluation_strategy"] = "steps"
        training_args_dict["greater_is_better"] = False

    hftraining_args = hf_arg_parser.parse_dict(training_args_dict, allow_extra_keys=True)[0]

    # Set seed before initializing model
    if hftraining_args.seed is not None:
        set_seed(hftraining_args.seed)

    # Detecting last checkpoint.
    last_checkpoint = None
    if os.path.isdir(hftraining_args.output_dir) and not hftraining_args.overwrite_output_dir:
        last_checkpoint = get_last_checkpoint(hftraining_args.output_dir)
        if last_checkpoint is None and len(os.listdir(hftraining_args.output_dir)) > 0:
            raise ValueError(
                f"Output directory ({hftraining_args.output_dir}) already exists and is not empty. "
                "Clear the folder or set TrainingArguments.overwrite_output_dir to True to overcome that."
            )
        elif last_checkpoint is not None:
            logger.info(
                f"Checkpoint detected, resuming training at {last_checkpoint}. To avoid this behavior, change "
                "the model's output directory or set TrainingArguments.overwrite_output_dir to False to train from scratch."
            )

    # Setup logging
    logging.basicConfig(
        format="%(asctime)s - %(levelname)s - %(name)s - %(message)s",
        datefmt="%m/%d/%Y %H:%M:%S",
        handlers=[logging.StreamHandler(sys.stdout)],
    )
    logger.setLevel(logging.INFO if is_main_process(hftraining_args.local_rank) else logging.WARN)

    if training_args.show_dataset_stats:
        logger.info("Getting dataset stats...")

        total_train_size_in_seconds = 0
        for sample in train_dataset:
            total_train_size_in_seconds += len(sample["input_values"]) / processor.feature_extractor.sampling_rate
        logger.info(f"Training dataset size: {len(train_dataset)} samples, {total_train_size_in_seconds/3600} hours")

        if eval_dataset is not None:
            total_eval_size_in_seconds = 0
            for sample in eval_dataset:
                total_eval_size_in_seconds += len(sample["input_values"]) / processor.feature_extractor.sampling_rate
            logger.info(f"Evaluation dataset size: {len(eval_dataset)} samples, {total_eval_size_in_seconds/3600} hours")

    # Setup model

    config = AutoConfig.from_pretrained(model_name_or_path)

    config.update(
        {
            "feat_proj_dropout": model_args.feat_proj_dropout,
            "attention_dropout": model_args.attention_dropout,
            "hidden_dropout": model_args.hidden_dropout,
            "final_dropout": model_args.final_dropout,
            "mask_time_prob": model_args.mask_time_prob,
            "mask_time_length": model_args.mask_time_length,
            "mask_feature_prob": model_args.mask_feature_prob,
            "mask_feature_length": model_args.mask_feature_length,
            "layerdrop": model_args.layerdrop,
            "activation_dropout": model_args.activation_dropout,
            "ctc_loss_reduction": model_args.ctc_loss_reduction,
            "pad_token_id": processor.tokenizer.pad_token_id,
            "vocab_size": len(processor.tokenizer),
        }
    )

    if training_args.ignore_pretrained_weights:
        model = AutoModelForCTC.from_config(config=config)
    else:
        model = AutoModelForCTC.from_pretrained(model_name_or_path, config=config)

    if hftraining_args.gradient_checkpointing:
        model.gradient_checkpointing_enable()

    if model_args.freeze_feature_extractor:
        model.freeze_feature_extractor()

    # Defining metrics
    def _compute_metrics(pred, processor=processor, metrics_batch_size=training_args.metrics_batch_size,
                         evaluation_callbacks=training_args.evaluation_callbacks):

        pred_logits = pred.predictions
        padding_mask = pred_logits[:,:,0] == -100
        pred_ids = np.argmax(pred_logits, axis=-1)
        pred_ids[padding_mask] = processor.tokenizer.pad_token_id

        pred.label_ids[pred.label_ids == -100] = processor.tokenizer.pad_token_id

        pred_str = processor.batch_decode(pred_ids)

        # we do not want to group tokens when computing the metrics
        label_str = processor.batch_decode(pred.label_ids, group_tokens=False)

        metrics = {
            "wer": wer(predictions=pred_str, references=label_str, chunk_size=metrics_batch_size),
            "cer": cer(predictions=pred_str, references=label_str, chunk_size=metrics_batch_size),
        }

        if evaluation_callbacks is not None:
            for callback in evaluation_callbacks:
                callback(metrics, label_str, pred_str)

        return metrics

    # Setup data collator

    data_collator = CTCDataCollatorWithPadding(
        processor=processor,
        batch_creation_callbacks=training_args.batch_creation_callbacks,
        pad_to_multiple_of=training_args.pad_to_multiple_of,
    )

    # Initialize Trainer

    logger.info("Building trainer...")

    callbacks = []
    if training_args.early_stopping_patience is not None and training_args.early_stopping_patience > 0:
        callbacks.append(
            EarlyStoppingCallback(early_stopping_patience=training_args.early_stopping_patience)
        )
        hftraining_args.load_best_model_at_end = True

    trainer = CTCTrainer(
        args=hftraining_args,
        model = model,
        data_collator=data_collator,
        train_dataset=train_dataset,
        eval_dataset=eval_dataset,
        compute_metrics=_compute_metrics if eval_dataset is not None else None,
        min_learning_rate=training_args.min_learning_rate,
        lr_warmup_steps=training_args.lr_warmup_steps,
        lr_decay_steps=training_args.lr_decay_steps,
        training_step_callbacks=training_args.training_step_callbacks,
        use_8bit_optimizer=training_args.use_8bit_optimizer,
        callbacks = callbacks
    )

    # Training

    logger.info("Starting training...")

    if last_checkpoint is not None:
        checkpoint = last_checkpoint
    elif os.path.isdir(model_name_or_path):
        checkpoint = model_name_or_path
    else:
        checkpoint = None

    # Saving processor config to output directory

    if is_main_process(hftraining_args.local_rank):
        processor.save_pretrained(hftraining_args.output_dir)

    train_result = trainer.train(resume_from_checkpoint=checkpoint)
    trainer.save_model()

    metrics = train_result.metrics
    metrics["train_samples"] = len(train_dataset)

    trainer.log_metrics("train", metrics)
    trainer.save_metrics("train", metrics)
    trainer.save_state()


import logging

from lxml import etree
from pathlib import Path

LOGGER = logging.getLogger(__name__)

NRML_SCHEMA = str(Path(__file__).parent / '../schema/openquake/nrml.xsd')

class Validator:
    """
    XML file validator using XSD schema
    """

    def __init__(self, xsd_file: str):
        self.schema = etree.XMLSchema(
            etree.parse(xsd_file)
        )

    def validate(self, xml_filename: str):
        """
        Validate XML file against XSD schema

        :param xml_filename: name of xml file to validate
        :raises AssertionError: on schema validation error
        """

        LOGGER.debug('Validating XML file')

        return self.schema.assert_(
            etree.parse(xml_filename)
        )


"""
Library for QTPy Broker
(C) 2022 Enchanted Engineering
 """

import json
import board
# from nvstore import NVStore
from timeplus import Zulutime, Cron
from simpleq import Queue
from drivers import *

# Configuration/Definition class object for simpler dot notation references
class Definition:

    def __init__(self, obj={}):
        self._keys_ = []        # list of assigned attributes
        self.add(obj)

    def has(self, key=None):
        if key == None:
            return self._keys_.copy()
        return hasattr(self, key)

    def add(self, obj={}):
        if isinstance(obj, list):
            for a in obj:
                self.add(a)
        else:
            for k in obj.keys():
                setattr(self,k,obj[k])
                if not self._keys_.count(k):
                    self._keys_.append(k)

    def remove(self, key=None):
        if key==None:
            for k in self._keys_:
                self.remove(k)
        else:
            if hasattr(self, key):
                delattr(self, key)
                self._keys_.remove(k)

    def resolve(self, key=None, default=None):
        if key==None:
            dx = {}
            for k in self._keys_:
                dx[k] = getattr(self,k)
            return dx
        if not self.has(key):
            self.add(dict([(key, default)]))
        return getattr(self,key)

# singleton class for managing io endpoints...
class IO:

    def __new__(cls, obj=None, verbose=False):
        if not hasattr(cls, 'instance'):
            cls.instance = super(IO, cls).__new__(cls)
        return cls.instance

    def __init__(self, obj=None, verbose=False):
        self.verbose = verbose
        self.interfaces = {}
        self.instances = {}
        if obj:
            self.add([d for i,d in enumerate(obj) if 'driver' in d])
            self.add([x for i,x in enumerate(obj) if 'interface' in x])

    def add(self,obj):
        if isinstance(obj, list):
            for o in obj:
                self.add(o)
        else:
            if 'driver' in obj:
                driver = obj['driver']
                try:
                    if self.verbose: print(f"Adding driver: {obj['name']}")
                    if driver=='OneWire':
                        self.interfaces[obj['name']] = OneWireDriver(obj,obj.get('debug',self.verbose))
                        self.instances[obj['name']] = obj['name']
                        print(f"Onewire... {obj['name']}")
                        print(self.interfaces)
                        print(self.instances)
                    elif driver=='Analog':
                        self.interfaces[obj['name']] = AnalogDriver(obj,obj.get('debug',self.verbose))
                    elif driver=='Digital':
                        self.interfaces[obj['name']] = DigitalDriver(obj,obj.get('debug',self.verbose))
                    elif driver=='PWM':
                        self.interfaces[obj['name']] = PWMDriver(obj,obj.get('debug',self.verbose))
                    else:
                        print(f"WARN: Unknown driver type: {obj['name']} --> {obj['driver']}")
                except Exception as ex:
                    print(f"ERROR[{type(ex).__name__}]: IO.add Failed to load driver: {driver}", ex.args)
                    raise ex
            elif 'interface' in obj:
                try:
                    aliases = [str(x) for x in (set([obj.get('id'),obj.get('name'),obj.get('sn'),obj.get('addr')] +
                        obj.get('aliases',[])) - {None})]   # aliases defined for each io object for cross references
                    if self.verbose: print(f"Adding instance[{obj['interface']}]: {aliases}")
                    interface = self.interfaces.get(obj['interface'],None)
                    if not interface:
                        print(f"WARN: Ignoring instance {self.identity(obj)}, interface {obj['interface']} NOT DEFINED")
                    else:
                        interface.createInstance(obj, aliases)
                        for a in aliases:
                            exists = self.instances.get(a)
                            if exists:
                                print(f"WARN: Interface '{obj['interface']}' alias '{a}' exists; redefining alias")
                            else:
                                if self.verbose: print(f"Creating instance alias '{a}' for interface '{obj['interface']}'")
                            self.instances[a] = obj['interface']
                except Exception as ex:
                    print(f"ERROR[{type(ex).__name__}]: IO.add Failed to load instance", ex.args)
                    raise ex
            else:
                print("WARN: I/O definition lacks driver/interface property", obj)

    def handle(self, msg):
        instance = self.instances.get(msg['id'])
        interface = self.interfaces.get(instance)
        try:
            #if self.verbose: print(f"IO.handle: id->{msg['id']}, instance->{instance}, interface->{interface}")
            return interface.handler(msg)
        except Exception as ex:
            print(f"ERROR[{type(ex).__name__}]: broker[IO.handle]: {instance}, {interface}")
            return None

    def identity(self, cfg):
        return str(cfg.get('id',cfg.get('name',cfg.get('sn',cfg.get('addr','UNKNOWN')))))

    def poll(self):
        results = []
        for interface in self.interfaces.values():
            result = interface.poll()
            if result: results.append(result)
        return results

# singleton class holding all global shared broker Data ...
class Glob:

    def __new__(cls):
        if not hasattr(cls, 'instance'):
            cls.instance = super(Glob, cls).__new__(cls)
        return cls.instance

    def __init__(self):
        # shared data
        self.utc = Zulutime()       # universal time object
        self.errors = Definition()  # Error logging object
        self.cfg = Definition()     # dot object to hold configuration parameters
        self.io = IO()              # management of io endpoints
        self.cron = Cron(self.utc)  # management of cronjobs
        self.msgs = Queue()         # incoming message queue
        self.rtn = Queue()          # return message queue
        #self.actions = Queue()      # action message queue
        self.events = Queue()       # cronjob events

    # report error...
    def error(self,e=None):
        if e==None:
            ex = {}
            for k in self.errors.has():
                ex[k] = self.errors.resolve(k,None)
            return ex
        self.errors.add(dict([(e, self.errors.resolve(e,0)+1)]))


import os
import time

from Settings import Settings
from BrightnessManager import BrightnessManager

class PowerSaver:
    def __init__(self, args=None):
        self.setup(args)

    def setup(self, args=None):
        '''Set up arguments to be used, and initialize Battery and Brightness mangager.'''

        arguments = {
            "verbose": False,
            "manual": False,
            "fade": .25,
            "time": 2,
            "profile": None
        }

        if args is not None:
            for arg in args.keys():
                if arg in arguments:
                    arguments[arg] = args[arg]

        self.arguments = arguments

        self.level = None

        self.brightness_manager = BrightnessManager()

        self.brightness = self.brightness_manager.get_brightness()

        #self.charging = self.battery.is_charging()
        #self.percent = self.battery.percent()

        self.level = None
        self.min_percent = None
        self.max_percent = None

        if self.arguments["profile"] is None:
            cur_dir = os.path.abspath(os.path.dirname(__file__))
            #if self.arguments["verbose"]:
            #    print("Default settings loaded", flush=True)
            self.settings = Settings(os.path.join(cur_dir, "settings.json"))

        else:
            self.settings = Settings(arguments["profile"])

    def poll(self):
        '''Poll the battery and brightness. If the battery level defined in settings
        has changed, update the screen brightness.'''

        poll_time = self.arguments["time"]

        while True:
            time.sleep(poll_time)
            update = False

            brightness = self.brightness_manager.get_brightness()
            print (brightness)

            brightness_level = 50
            self.brightness_manager.set_brightness(brightness_level)
            if brightness_level <= 50:
                self.brightness_manager.set_brightness(75)

            else:
                self.brightness_manager.set_brightness(25)

            brightness = self.brightness_manager.get_brightness()
            print ("New brightness",brightness)

if __name__ == "__main__":

    import argparse

    parser = argparse.ArgumentParser()

    parser.add_argument(
        "-v",
        "--verbose",
        help="Display messages in the terminal each time the battery is polled.\n"
        "Default: Off",
        action="store_true"
    )

    parser.add_argument(
        "-m",
        "--manual",
        help="Keep the program open if the brightness is manually changed.\n"
        "Default: Off",
        action="store_true"
    )

    parser.add_argument(
        "-f",
        "--fade",
        help="The speed to fade the brightness in or out.\n"
        "Higher is slower. Default: .25",
        type=float,
        default=.25
    )

    parser.add_argument(
        "-t",
        "--time",
        help="The time to sleep between each poll on the battery. (in seconds)\n"
        "Default: 2",
        type=float,
        default=2
        )

    parser.add_argument(
        "-p",
        "--profile",
        help="The json file to use for battery levels and percentages.",
        type=str
    )

    args = parser.parse_args()

    arguments = {
        "verbose": args.verbose,
        "manual": args.manual,
        "fade": args.fade,
        "time": args.time,
        "profile": None if not args.profile else args.profile,
    }

    powersaver = PowerSaver(arguments)
    powersaver.poll()


from scipy import spatial as _spatial
import numpy as _np

from . import util
from . import grid_filters

def from_random(size,N_seeds,grid=None,seed=None):
    """
    Random seeding in space.

    Parameters
    ----------
    size : numpy.ndarray of shape (3)
        Physical size of the seeding domain.
    N_seeds : int
        Number of seeds.
    grid : numpy.ndarray of shape (3), optional.
        If given, ensures that all seeds initiate one grain if using a
        standard Voronoi tessellation.
    seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
        A seed to initialize the BitGenerator. Defaults to None.
        If None, then fresh, unpredictable entropy will be pulled from the OS.

    """
    rng = _np.random.default_rng(seed)
    if grid is None:
        coords = rng.random((N_seeds,3)) * size
    else:
        grid_coords = grid_filters.cell_coord0(grid,size).reshape(-1,3,order='F')
        coords = grid_coords[rng.choice(_np.prod(grid),N_seeds, replace=False)] \
               + _np.broadcast_to(size/grid,(N_seeds,3))*(rng.random((N_seeds,3))*.5-.25)           # wobble without leaving grid

    return coords

def from_Poisson_disc(size,N_seeds,N_candidates,distance,periodic=True,seed=None):
    """
    Seeding in space according to a Poisson disc distribution.

    Parameters
    ----------
    size : numpy.ndarray of shape (3)
        Physical size of the seeding domain.
    N_seeds : int
        Number of seeds.
    N_candidates : int
        Number of candidates to consider for finding best candidate.
    distance : float
        Minimum acceptable distance to other seeds.
    periodic : boolean, optional
        Calculate minimum distance for periodically repeated grid.
    seed : {None, int, array_like[ints], SeedSequence, BitGenerator, Generator}, optional
        A seed to initialize the BitGenerator. Defaults to None.
        If None, then fresh, unpredictable entropy will be pulled from the OS.

    """
    rng = _np.random.default_rng(seed)
    coords = _np.empty((N_seeds,3))
    coords[0] = rng.random(3) * size

    i = 1
    progress = util._ProgressBar(N_seeds+1,'',50)
    while i < N_seeds:
        candidates = rng.random((N_candidates,3))*_np.broadcast_to(size,(N_candidates,3))
        tree = _spatial.cKDTree(coords[:i],boxsize=size) if periodic else \
               _spatial.cKDTree(coords[:i])
        distances, dev_null = tree.query(candidates)
        best = distances.argmax()
        if distances[best] > distance:                                                              # require minimum separation
            coords[i] = candidates[best]                                                            # maximum separation to existing point cloud
            i += 1
            progress.update(i)

    return coords

def from_geom(geom,selection=None,invert=False,average=False,periodic=True):
    """
    Create seed from existing geometry description.

    Parameters
    ----------
    geom : damask.Geom
        Geometry, from which the material IDs are used as seeds.
    selection : iterable of integers, optional
        Material IDs to consider.
    invert : boolean, false
        Do not consider the material IDs given in selection. Defaults to False.
    average : boolean, optional
        Seed corresponds to center of gravity of material ID cloud.
    periodic : boolean, optional
        Center of gravity with periodic boundaries.

    """
    material = geom.material.reshape((-1,1),order='F')
    mask = _np.full(geom.grid.prod(),True,dtype=bool) if selection is None else \
           _np.isin(material,selection,invert=invert).flatten()
    coords = grid_filters.cell_coord0(geom.grid,geom.size).reshape(-1,3,order='F')

    if not average:
        return (coords[mask],material[mask])
    else:
        materials = _np.unique(material[mask])
        coords_ = _np.zeros((materials.size,3),dtype=float)
        for i,mat in enumerate(materials):
            pc = (2*_np.pi*coords[material[:,0]==mat,:]-geom.origin)/geom.size
            coords_[i] = geom.origin + geom.size / 2 / _np.pi * (_np.pi +
                         _np.arctan2(-_np.average(_np.sin(pc),axis=0),
                                     -_np.average(_np.cos(pc),axis=0))) \
                         if periodic else \
                         _np.average(coords[material[:,0]==mat,:],axis=0)
        return (coords_,materials)


from dash import Dash, html, dcc, Input, Output
import dash_bootstrap_components as dbc
import altair as alt
import pandas as pd

# disable Altair limits
qwl_df = pd.read_csv("data/bei_vita_qwl_assessment.csv")

#Dash app
app = Dash(
    __name__,
    external_stylesheets=[dbc.themes.BOOTSTRAP, "https://codepen.io/chriddyp/pen/bWLwgP.css"]
)
server = app.server

app.layout = dbc.Container(
    [
        dbc.Row(
            [
                dbc.Col(
                    [
                        html.Br(),
                        html.H3("Bei Vita"),
                        html.P(
                            dcc.Markdown(
                                """
                                Visualization to represent how scores for quality of
                                work life are distributed
                                """
                            )
                        )
                    ],
                    width=3
                ),
                dbc.Col(
                    [
                        html.H2("Quality of Work Life"),
                        html.H3("Client Name: HDBC Bank")
                    ],
                    width=6
                ),
                dbc.Col(
                    [
                    ],
                    width=3
                )
            ],
            align="center"
        ),
        html.Br(),

        dbc.Row(
            [
                dbc.Col(
                    [
                        html.Div(
                            [
                                html.H6("Country of Residence"),
                                dcc.Dropdown(
                                    id = 'my_checklist_1',
                                    options = [{'label' : y , 'value' : y,'disabled':False}
                                    for y in qwl_df['Country of Residence '].unique()],
                                    value = 'HK & Macau'),

                                html.H6("Role Classification"),
                                dcc.Dropdown(
                                    id = 'my_checklist_2',
                                    options = [{'label' : x , 'value' : x,'disabled':False}
                                    for x in qwl_df['Role Classification'].unique()],
                                    value = 'Entry (Associate)'),

                                html.Iframe(
                                    id="histogram",
                                    style={"border-width": "0", "width": "100%", "height": "370px"}
                                )
                            ]
                        )
                    ],
                    width=12
                )
            ],
        ),

        dbc.Row(
            [
                dbc.Col(
                    [
                        html.Iframe(
                            id='horizontal_barplot',
                            style={'border-width': '0', 'width': '100%', 'height': '500px'})
                        ],
                    width=6
                ),
                dbc.Col(
                    [
                        html.Div(
                            [
                            html.Iframe(
                                id='Country',
                                style={'border-width': '0', 'width': '100%', 'height': '575px'})
                            ]
                        ),
                    ],
                )
            ],
        )
    ]
)

@app.callback(
    Output('histogram', 'srcDoc'),
    Output("horizontal_barplot", "srcDoc"),
    Output('Country', 'srcDoc'),
    Input('my_checklist_1', 'value'),
    Input('my_checklist_2', 'value')
)

def vertical_barplot(my_checklist_1,my_checklist_2):
    plot_data = qwl_df[(qwl_df["Country of Residence "].isin([my_checklist_1])) &
                        (qwl_df["Role Classification"].isin([my_checklist_2]))]

    #histogram
    histogram = alt.Chart(plot_data, ).mark_bar(
        color = "lightblue").encode(
        alt.X("Total score", bin = True),
        alt.Y("count():Q",
              title="# of Employees", axis = alt.Axis(values = list(range(1,17,1)))
    )).properties(width=750, height=250, title= {'text': ['How healthy are the employees feeling overall?'],'subtitle': 'At country and designation level'}).interactive()

    #horizontal barchart
    col_name = '17. I experience MEANINGFULNESS at work ... (e.g. inspired, trusted, respected, purpose, seen and heard, acknowledged, fulfilled, growth, contribution to something greater, etc.) '

    plot_data = plot_data[col_name].value_counts().to_frame().reset_index()
    plot_data = plot_data.rename(columns={col_name:'Count', 'index':'Response'})

    chart = alt.Chart(plot_data).mark_bar().encode(
        x='Count:Q',
        y='Response:O',
        color = alt.Color('Response', legend=None)
    ).properties(
        width=300,
        height=350, title = {'text': ['How frequently do employees find meaningfulness at work?'],'subtitle': 'At country and designation level'}
    )

    #vertical boxplot
    # NEW Data wrangling for vertical bar graph
    plot_data_2 = qwl_df[(qwl_df["Country of Residence "].isin([my_checklist_1]))]

    workshop_topics = ['Stress Optimization',
                        'Mindset Coaching',
                        'Sleep Strategies',
                        'Social Wellbeing',
                        'Leadership and Teamwork',
                        'Physical Health & Fitness',
                        'Nutrition & Gut Health']

    temp = plot_data_2.iloc[:,55:62]
    temp = temp.set_axis(workshop_topics, axis=1)
    temp['Country'] = plot_data_2.iloc[:,4]
    temp = temp.set_index('Country')

    vg_df = temp.melt(var_name = "Workshop_Topic", value_name = "Preference", ignore_index = False)
    vg_df = vg_df.reset_index(level=0)

    #data = vg_df[(vg_df['Country'].isin([my_checklist_1]))]
    vertical_boxplot = alt.Chart(vg_df).mark_boxplot().encode(
        x = 'Workshop_Topic',
        y = 'Preference',
        color = alt.Color('Workshop_Topic', legend=None)
    ).properties(
        width=300,
        height=350,title = {'text': ["Workshop Preference (lower is more important)"],'subtitle': 'At country level'}
    )

    return histogram.to_html(), chart.to_html(), vertical_boxplot.to_html()

if __name__ == "__main__":
    app.run_server(debug=False)


import mediapipe as mp
import cv2

mp_drawing = mp.solutions.drawing_utils
mp_hands = mp.solutions.hands
hands = mp_hands.Hands(static_image_mode = False,max_num_hands = 1,min_detection_confidence = 0.7)

def detections(img):
    #img = cv2.flip(img, 1)
    imgRGB = cv2.cvtColor(img, cv2.COLOR_BGR2RGB)
    results = hands.process(imgRGB)
    master = []
    if results.multi_hand_landmarks:
        for hmark in results.multi_hand_landmarks:
                #for id, lm in enumerate(hmark.landmark):
                    #print(id, lm)
            master[:] = hmark.landmark[:]
            mp_drawing.draw_landmarks(img, hmark, mp_hands.HAND_CONNECTIONS)

    return img, master


print(range(10))

# zwykła funkcja
def my_range(num):
    idx = 0
    result = []
    while idx < num:
        result.append(idx)
        idx += 1

    return result

# res = my_range(999999)
# print(res)

# generator
def my_range2(num):
    idx = 0
    result = []
    while idx < num:
        yield idx
        idx += 1

# zwykła funkcja
# for item in my_range(999999999999999999999999999):
#     print(item)

# generator
# for item in my_range2(999999999999999999999999):
#     print(item)


from selenium.webdriver.common.by import By
from base_page_object import BasePage
from nose.tools import assert_equal, assert_true
from conf import new_request_conf as request
import datetime

class PortfolioPage(BasePage):
    locator_dictionary = {
        "portfolio_header": (By.XPATH, "//div[@class='title']/span[.='Project REC portfolio']"),
        "portfolio_mass_header": (By.XPATH, "//div[@class='title']/span[.='Project MASS portfolio']"),
        "last_project_title": (By.XPATH, "//span[.='Recrutment_archive']"),
        "filter_button": (By.XPATH, "//a[@class='ant-dropdown-trigger']"),
        "settings_button": (By.XPATH, "//i[@class='anticon anticon-settings']"),
        "request_title": (By.XPATH, "//span[.='Recrutment_reject']"),
        "mass_request_title": (By.XPATH, "//span[.='Mass_request']"),
        "mass_inwork_title": (By.XPATH, "//span[.='Mass_inwork']"),
        "mass_frozen_title": (By.XPATH, "//span[.='Mass_freeze']"),
        "mass_complete_title": (By.XPATH, "//span[.='Mass_complete']"),
        "mass_cancelled_title": (By.XPATH, "//span[.='Mass_annulate']"),
        "mass_archived_title": (By.XPATH, "//span[.='Mass_archive']"),
        "inwork_title": (By.XPATH, "//span[.='Recrutment1']"),
        "frozen_title": (By.XPATH, "//span[.='Recrutment_freeze']"),
        "complete_title": (By.XPATH, "//span[.='Recrutment_complete']"),
        "cancelled_title": (By.XPATH, "//span[.='Recrutment_annulate']"),
        "archived_title": (By.XPATH, "//span[.='Recrutment_archive']"),
        "go_to_project_button": (By.XPATH, "//a[@class='sidebar-link']/i[@class='anticon anticon-briefcase']"),
        "user_field": (By.XPATH, "//div[@class='antd-select-container user-filter']//input"),
        "second_resp_project": (By.XPATH, "//span[.='Position2']"),
        "second_resp_mass_project": (By.XPATH, "//span[.='Mass_Second_User']")
        }

    def __init__(self, context):
        BasePage.__init__(
            self,
            context.browser)

    def validate_project_list(self, type):
        if type == "request":
            assert_true(self.request_title)
        elif type == "inwork":
            assert_true(self.inwork_title)
            assert_true(self.find_element(By.XPATH, "//span[.='10']"))
            assert_true(self.find_element(By.XPATH, "//span[.='25.04.2025']"))
        elif type == "frozen":
            assert_true(self.frozen_title)
            assert_true(self.find_element(By.XPATH, "//span[.='10']"))
            assert_true(self.find_element(By.XPATH, "//span[.='22.02.2022']"))
        elif type == "complete":
            assert_true(self.complete_title)
            assert_true(self.find_element(By.XPATH, "//span[.='2']"))
            assert_true(self.find_element(By.XPATH, "//span[.='22.02.2022']"))
        elif type == "cancelled":
            assert_true(self.cancelled_title)
            assert_true(self.find_element(By.XPATH, "//span[.='10']"))
            assert_true(self.find_element(By.XPATH, "//span[.='22.02.2022']"))
        elif type == "archived":
            assert_true(self.archived_title)
            assert_true(self.find_element(By.XPATH, "//span[.='1']"))
            assert_true(self.find_element(By.XPATH, "//span[.='22.02.2022']"))
        elif type == "mass request":
            assert_true(self.mass_request_title)
            assert_true(self.find_element(By.XPATH, "//span[.='10']"))
        elif type == "mass inwork":
            assert_true(self.mass_inwork_title)
            assert_true(self.find_element(By.XPATH, "//span[.='25']"))
            assert_true(self.find_element(By.XPATH, "//span[.='22.02.2022']"))
        elif type == "mass frozen":
            assert_true(self.mass_frozen_title)
            assert_true(self.find_element(By.XPATH, "//span[.='35']"))
        elif type == "mass complete":
            assert_true(self.mass_complete_title)
            assert_true(self.find_element(By.XPATH, "//span[.='1']"))
        elif type == "mass cancelled":
            assert_true(self.mass_cancelled_title)
            assert_true(self.find_element(By.XPATH, "//span[.='65']"))
        elif type == "mass archived":
            assert_true(self.mass_archived_title)
            assert_true(self.find_element(By.XPATH, "//span[.='45']"))
            assert_true(self.find_element(By.XPATH, "//span[.='25.10.2025']"))

    class FilterPage(BasePage):
        locator_dictionary = {
            "filter_header": (By.XPATH, "//span[.=Filter]"),
            "all_field": (By.XPATH, "//a[.='All']"),
            "request_field": (By.XPATH, "//a[.='Request']"),
            "inprogress_field": (By.XPATH, "//a[.='In progress']"),
            "frozen_field": (By.XPATH, "//a[.='Frozen']"),
            "completed_field": (By.XPATH, "//a[.='Completed']"),
            "cancelled_field": (By.XPATH, "//a[.='Canceled']"),
            "archive_field": (By.XPATH, "//a[.='Archive']"),
        }

        def __init__(self, context):
            BasePage.__init__(
                self,
                context.browser)

    class NotWorksheetPage(BasePage):
        locator_dictionary = {
            "not_worksheet_header": (By.XPATH, "//span[.='Project SearchWorksheet']"),
            "ok_button": (By.XPATH, "//button[@aria-label='Close']")
        }

        def __init__(self, context):
            BasePage.__init__(
                self,
                context.browser)

    class PortfolioSettingsPage(BasePage):
        locator_dictionary = {
            "settings_header": (By.XPATH, "//span[.='Projects Portfolio REC settings']"),
            "ok_button": (By.XPATH, "//button[@aria-label='Close']")
        }

        def __init__(self, context):
            BasePage.__init__(
                self,
                context.browser)


"""
반복문을 이용한 세그먼트 트리
"""
from sys import stdin
from math import ceil, log2

INF = 100001

def init():
    for i in range(N):
        tree[N + i] = (arr[i], arr[i])

    for i in range(N - 1, 0, -1):
        l, r = tree[i << 1], tree[i << 1 | 1]
        tree[i] = (min(l[0], r[0]), max(l[1], r[1]))

def update(a, b):
    tree[N + a] = (arr[b], arr[b])
    tree[N + b] = (arr[a], arr[a])

    i = N + a
    while i > 1:
        tree[i >> 1] = (min(tree[i][0], tree[i + 1][0]),
                        max(tree[i][1], tree[i + 1][1]))
        i >>= 1

    i = N + b
    while i > 1:
        tree[i >> 1] = (min(tree[i][0], tree[i + 1][0]),
                        max(tree[i][1], tree[i + 1][1]))
        i >>= 1

def query(left, right):
    left += N
    right += N
    res = [INF, -INF]

    while left < right:
        if left & 1:
            res[0] = min(tree[left][0], res[0])
            res[1] = max(tree[left][1], res[1])
            left += 1
        if right & 1:
            right -= 1
            res[0] = min(tree[right][0], res[0])
            res[1] = max(tree[right][1], res[1])
        left >>= 1
        right >>= 1

    return res

if __name__ == "__main__":
    input = lambda: stdin.readline().rstrip()

    T = int(input())
    for _ in range(T):
        N, K = map(int, input().split())
        arr = list(i for i in range(N))
        tree = list((0, 0) for _ in range(1 << (int(ceil(log2(N))) + 1)))
        init()

        for _ in range(K):
            Q, A, B = map(int, input().split())

            if Q == 0:
                update(A, B)
                arr[A], arr[B] = arr[B], arr[A]
            else:
                res = query(A, B + 1)
                print(["NO", "YES"][res[0] == arr[A] and res[1] == arr[B]])


num = int(input())
positives = []
negatives = []

for integers in range(num):
    num = int(input())
    if num >= 0:
        positives.append(num)
    elif num < 0:
        negatives.append(num)
print(positives)
print(negatives)
print(f'Count of positives: {len(positives)}')
print(f'Sum of negatives: {sum(negatives)}')


__author__ = 'ZJsnowman'
# -*- coding:utf-8 -*-
import numpy as np

class Solution:
    def removeElement(self, nums, val):
        """
        :type nums: List[int]
        :type val: int
        :rtype: int
        """
        i = 0
        for value in nums:
            if value != val:
                nums[i] = value
                i += 1
        return i

if __name__ == '__main__':
    s = Solution()
    nums = [3, 2, 2, 3]
    nums2 = [0, 1, 2, 2, 3, 0, 4, 2]
    print(s.removeElement(nums, 3))
    print(s.removeElement(nums2, 2))


import matplotlib.pyplot as plt
from mpl_toolkits.mplot3d import Axes3D
import MProblem as MP
from platypus import NSGAII, Problem, Real,SMPSO
import pandas as pd
from sklearn.preprocessing import LabelEncoder
from keras.models import *
from keras.layers import *
from keras.utils.vis_utils import plot_model
from keras.callbacks import EarlyStopping
from keras.utils import to_categorical
from keras.optimizers import SGD
import matplotlib.pyplot as plt
import os
import numpy as np
import cv2
import progressbar
import sys
from platypus import NSGAII, Problem, Real
from sklearn.model_selection import train_test_split
import csv
from sklearn.metrics import classification_report, precision_recall_fscore_support, accuracy_score
import copy
from random import *
from random import shuffle
from platypus import *
from keras.datasets import cifar10
import keras
from keras.datasets import fashion_mnist
from keras.datasets import mnist
import os
import numpy as np
from scipy.misc import imread,imresize
from sklearn.model_selection import train_test_split
from glob import glob

# Retorna quantidade de imagens em diretorio
def getNumSamples(src):
    sum = 0
    for cl in os.listdir(src):
        class_dir = os.path.join(src, cl)
        files = os.listdir(class_dir)
        l = len(files)
        sum += l

    return sum, len(os.listdir(src))

# Carrega base de dados e converte em array numpy
def array_from_dir(data_dir, nb_samples, nb_classes, width, height):
    images = np.zeros((nb_samples, width, height, 1))
    y = np.zeros((nb_samples, nb_classes))

    bar = progressbar.ProgressBar(max_value=len(os.listdir(data_dir)))

    cont = 0
    cl_index = 0
    for cl in os.listdir(data_dir):
        class_dir = os.path.join(data_dir, cl)
        files = os.listdir(class_dir)
        shuffle(files)
        files_per_class = 0
        for file in files:
            files_per_class += 1

            # lê em escala de cinza
            img = cv2.imread(os.path.join(class_dir, file), flags=0)

            # muda escala
            img = cv2.resize(img, (width, height))

            # deixa entre 0 e 1
            img = np.array(img) / 255.0

            # coloca no array
            images[cont, :, :, 0] = img

            # guarda a classe
            y[cont] = to_categorical(cl_index, nb_classes)

            cont += 1
        cl_index += 1
        bar.update(cl_index)

    # retorna array com imagens em classes
    return images, y

# divide base aleatoriamente em treinamento, teste e validação
def split_dataset_random(b_x, b_y, p_train, p_val):
    total_samples = b_x.shape[0]
    train_size = int(total_samples * p_train)
    valid_size = int(total_samples * p_val)
    test_size = total_samples - train_size - valid_size

    print()
    print('train set:', train_size, ' images')
    print('validation set:', valid_size, ' images')
    print('test set:', test_size, ' images')

    x_tr = np.zeros((train_size, b_x[0].shape[0], b_x[0].shape[1], b_x[0].shape[2]))
    y_tr = np.zeros((train_size, b_y[0].shape[0]))

    x_val = np.zeros((valid_size, b_x[0].shape[0], b_x[0].shape[1], b_x[0].shape[2]))
    y_val = np.zeros((valid_size, b_y[0].shape[0]))

    x_te = np.zeros((test_size, b_x[0].shape[0], b_x[0].shape[1], b_x[0].shape[2]))
    y_te = np.zeros((test_size, b_y[0].shape[0]))

    from random import shuffle
    index = list(range(total_samples))
    shuffle(index)

    for i in range(total_samples):
        if i < train_size:
            x_tr[i] = b_x[index[i]]
            y_tr[i] = b_y[index[i]]
        elif i < (train_size + valid_size):
            x_val[i - train_size] = b_x[index[i]]
            y_val[i - train_size] = b_y[index[i]]
        else:
            x_te[i - train_size - valid_size] = b_x[index[i]]
            y_te[i - train_size - valid_size] = b_y[index[i]]

    return x_tr, y_tr, x_te, y_te, x_val, y_val

print("Carregando Base")

#Base Gestos

# indica pasta da base de dados, uma pasta com imagens para cada classe
pasta_base = 'DB/Gestures/'

# tamanho do batch de treinamento
batch_size = 200

nb_db_samples, num_classes = getNumSamples(pasta_base)

print('Base tem ', nb_db_samples, ' imagens e ', num_classes, ' classes')

# tamanho da imagem
options_im_size = [16, 32, 48, 64]
im_sz=random.randint(0,3)
img_width, img_height = options_im_size[im_sz], options_im_size[im_sz]
print('Rescaling database to', img_width, 'x', img_height, ' pixels')
base_x, base_y = array_from_dir(data_dir=pasta_base, nb_samples=nb_db_samples,
                                        nb_classes=num_classes, width=img_width, height=img_height)

X_train, X_test, y_train, y_test = train_test_split(base_x,base_y,test_size=0.2,random_state=0)
input_shape=X_train.shape[1:]
print("Criando o modelo")
model = Sequential()
model.add(Conv2D(filters=5, kernel_size=4,padding="same", input_shape=input_shape))
model.add(Conv2D(filters=5, kernel_size=4, padding="same"))
model.add(MaxPooling2D())
model.add(Conv2D(filters=5, kernel_size=4, padding="same"))
model.add(Flatten())
model.add(Dense(units=5))

print("Compilando")
learning_rate = 0.1
epochs=50
decay_rate = learning_rate / epochs
momentum = 0.8
sgd = SGD(lr=learning_rate, momentum=momentum, decay=decay_rate, nesterov=False)
model.compile(loss='binary_crossentropy', optimizer=sgd, metrics=['accuracy'])#,'precision','recall', 'f1'])

print("Iniciando treinamento")
earlyStopping = EarlyStopping(monitor='val_acc', min_delta=0.001, patience=10, verbose=1, mode='auto')
history=model.fit(X_train,y_train,batch_size=200,
                        epochs=epochs,
                        callbacks=[earlyStopping],
                        validation_split=0.33,
                        shuffle=True,
                        verbose=2)

train_acc = history.history['acc'][-1]
val_acc = history.history['val_acc'][-1]
print("acuracia",val_acc)


from tkinter import *
import math

root = Tk()
# Set the Window Title
root.title("Calculator")

# Create input field, assign it to root and give it some shape/size
textinput = Entry(root, width=60, borderwidth=10)
# Move the input field to row 0, column 0 and tell it that there will be 3 columns. Padding to space it out a bit.
textinput.grid(row=0, column=0, columnspan=4, padx=10, pady=10)

def button_add(num):
    current_input = textinput.get()  # Get current textbox value
    textinput.delete(0, END)  # Clear the textbox
    textinput.insert(0, str(current_input) + str(num))  # Concatonate the values into the textbox

# Clear the textbox
def button_clear():
    textinput.delete(0, END)

def button_addition():
    first_num = textinput.get()
    global num_get
    global op
    op = "add"
    num_get = int(first_num)
    textinput.delete(0, END)  # Clear the textbox

def button_subtract():
    first_num = textinput.get()
    global num_get
    global op
    op = "sub"
    num_get = int(first_num)
    textinput.delete(0, END)  # Clear the textbox

def button_multiply():
    first_num = textinput.get()
    global num_get
    global op
    op = "mult"
    num_get = int(first_num)
    textinput.delete(0, END)  # Clear the textbox

def button_divide():
    first_num = textinput.get()
    global num_get
    global op
    op = "div"
    num_get = int(first_num)
    textinput.delete(0, END)  # Clear the textbox

# Can't multiply floats. Fix this.
def button_total():
    second_num = textinput.get()
    textinput.delete(0, END)  # Clear the textbox

    if op == "add":
        textinput.insert(0, num_get + int(second_num))
    elif op == "sub":
        textinput.insert(0, num_get - int(second_num))
    elif op == "mult":
        textinput.insert(0, num_get * int(second_num))
    elif op == "div":
        div_ans = num_get / int(second_num)
        if div_ans == int(div_ans):
            textinput.insert(0, math.floor(num_get / int(second_num)))
        else:
            textinput.insert(0, round(num_get / int(second_num), 2))

# Number buttons. Assign to Root. Text Value, Size/Shape, Function("lambda:" allows the function to have "()"),
# Background Colour
button_1 = Button(root, text="1", padx=40, pady=20, borderwidth=5, command=lambda: button_add(1), bg="#d1d9e3")
button_2 = Button(root, text="2", padx=40, pady=20, borderwidth=5, command=lambda: button_add(2), bg="#d1d9e3")
button_3 = Button(root, text="3", padx=40, pady=20, borderwidth=5, command=lambda: button_add(3), bg="#d1d9e3")
button_4 = Button(root, text="4", padx=40, pady=20, borderwidth=5, command=lambda: button_add(4), bg="#d1d9e3")
button_5 = Button(root, text="5", padx=40, pady=20, borderwidth=5, command=lambda: button_add(5), bg="#d1d9e3")
button_6 = Button(root, text="6", padx=40, pady=20, borderwidth=5, command=lambda: button_add(6), bg="#d1d9e3")
button_7 = Button(root, text="7", padx=40, pady=20, borderwidth=5, command=lambda: button_add(7), bg="#d1d9e3")
button_8 = Button(root, text="8", padx=40, pady=20, borderwidth=5, command=lambda: button_add(8), bg="#d1d9e3")
button_9 = Button(root, text="9", padx=40, pady=20, borderwidth=5, command=lambda: button_add(9), bg="#d1d9e3")
button_0 = Button(root, text="0", padx=40, pady=20, borderwidth=5, command=lambda: button_add(0), bg="#d1d9e3")
# Operator buttons.
button_plus = Button(root, text="+", padx=37, pady=20, borderwidth=5, command=button_addition, bg="#e3dad1")
button_minus = Button(root, text="-", padx=39, pady=20, borderwidth=5, command=button_subtract, bg="#e3dad1")
button_multi = Button(root, text="*", padx=39, pady=20, borderwidth=5, command=button_multiply, bg="#e3dad1")
button_divi = Button(root, text="/", padx=39, pady=20, borderwidth=5, command=button_divide, bg="#e3dad1")
# Functional buttons.
button_equals = Button(root, text="=", padx=39, pady=20, borderwidth=5, command=button_total, bg="#e3dad1")
button_clear = Button(root, text="C", padx=39, pady=20, borderwidth=5, command=button_clear, bg="#e3dad1")

# Display number buttons.
# 1-3 Bottom Row
button_1.grid(row=3, column=0)
button_2.grid(row=3, column=1)
button_3.grid(row=3, column=2)
# 4-6 Middle Row
button_4.grid(row=2, column=0)
button_5.grid(row=2, column=1)
button_6.grid(row=2, column=2)
# 7-9 Top Row
button_7.grid(row=1, column=0)
button_8.grid(row=1, column=1)
button_9.grid(row=1, column=2)
# Bottom Bottom Row
button_0.grid(row=4, column=1)
button_equals.grid(row=4, column=0)
button_clear.grid(row=4, column=2)
# Symbols
button_plus.grid(row=1, column=3)  # Top Row
button_minus.grid(row=2, column=3)  # Mid Row
button_multi.grid(row=3, column=3)  # Bot Row
button_divi.grid(row=4, column=3)  # Bot Bot

# root.mainloop() is the function that opens the application window and keeps it updated.
root.mainloop()