#!/usr/bin/env python3
# author: drcor

import requests
import json
import os
import simplekml
from datetime import datetime
import math
import argparse
import yaml

URL = "https://precoscombustiveis.dgeg.gov.pt/api/PrecoComb/PesquisarPostos?idsTiposComb={}&idMarca=&idTipoPosto=&idDistrito=&idsMunicipios=&qtdPorPagina=5000&pagina=1"
TYPES_OF_FUEL = {
    "95": 3201,
    "98": 3405,
    "diesel": 2101
}

class FuelStation(object):
	# Fuel station constructor
	def __init__(self, name:str, district:str, municipality:str, town:str, address:str, latitude:float, longitude:float, price:float, brand:str):
		self.name = name
		self.district = district
		self.municipality = municipality
		self.town = town
		self.address = address
		self.latitude = latitude
		self.longitude = longitude
		self.price = price
		self.brand = brand

class CheckFuelPrices:
    def __init__(self, configPath:str, urlFormat:str, databasePath:str):
        # parse default configurations from the config file
        with open(configPath, 'r') as configfile:
            configOptions = yaml.safe_load(configfile)
        # import default configurations
        self.latitude = configOptions['latitude']
        self.longitude = configOptions['longitude']
        self.fuelType = self.convertFuelNameToRef(configOptions['fuel'])
        self.createKml = configOptions['create_kml']
        self.searchRadiusInKm = configOptions['search_radius']

        self.url = urlFormat.format(self.fuelType)
        self.databaseFile = os.path.join(databasePath, "fuel_prices_{}.json".format(self.fuelType))

        if self.isTimeToUpdateDatabase():
            self.updateDatabase()
            self.lastDatabaseUpdate = datetime.now()
        else:
            self.lastDatabaseUpdate = datetime.fromtimestamp(os.path.getmtime(self.databaseFile))

    def setFuelType(self, fuelName:str):
        self.fuelType = self.convertFuelNameToRef(fuelName)

    def setLatitude(self, latitude:float):
        if latitude and -90.0 <= latitude <= 90.0:
            self.latitude = latitude

    def setLongitude(self, longitude:float):
        if longitude and -180.0 <= longitude <= 180.0:
            self.longitude = longitude

    def isDatabaseAvailable(self) -> bool:
        return os.path.isfile(self.databaseFile)

    def isTimeToUpdateDatabase(self) -> bool:
        if self.isDatabaseAvailable():
            last_update = datetime.fromtimestamp(os.path.getmtime(self.databaseFile)) # Get time of last update
            # return True if database was not updated this week or if database is empty
            return last_update.isocalendar()[1] is not datetime.now().isocalendar()[1] or os.stat(self.databaseFile).st_size == 0
        else:
            return True

    def updateDatabase(self):
        # create database file if not exists
        if not self.isDatabaseAvailable():
            open(self.databaseFile, 'a').close()

        # Get database from API
        response = requests.get(self.url)

        if response.status_code == 200:
            try:
                json_response = json.loads(response.content)["resultado"]
                # Save in a file
                with open(self.databaseFile, "w") as file:
                    file.writelines(json.dumps(json_response))
            except Exception as e:
                print(e)
                exit(1)
        else:
            print("⚠ failed to retrieve online data!")
            exit(1)

    def isStationNear(self, latitude:float, longitude:float) -> bool:
        arcLength = self.calculateEarthArcFromRadius(self.searchRadiusInKm)
        latitudeDistance = abs(latitude - self.latitude)
        longitudeDistance = abs(longitude - self.longitude)
        # return True if the distance between the two locations is smaller or equal to the radius
        return math.sqrt(latitudeDistance**2 + longitudeDistance**2) <= arcLength

    # converts the name of the fuel to it's reference in database
    def convertFuelNameToRef(self, fuelName:str) -> int:
        if fuelName in TYPES_OF_FUEL.keys():
            return TYPES_OF_FUEL[fuelName]
        else:
            return self.fuelType

    # Calculate the arc of earth equivalent to the radius of search
    def calculateEarthArcFromRadius(self, radius:float) -> float:
        earthRadius = 6371 # km
        return (radius * 180) / (math.pi * earthRadius)

    def searchDatabase(self):
        self.nearFuelStations = []
        stationsDatabase = None
        # read database
        with open(self.databaseFile, "r") as file:
            stationsDatabase = json.load(file)
        # create list of objects
        for station in stationsDatabase:
            if self.isStationNear(station['Latitude'], station['Longitude']):
                priceInFloat = float(station['Preco'].split()[0].replace(',', '.'))
                self.nearFuelStations.append(FuelStation(station['Nome'],
                                                    station['Distrito'],
                                                    station['Municipio'],
                                                    station['Localidade'],
                                                    station['Morada'],
                                                    station['Latitude'],
                                                    station['Longitude'],
                                                    priceInFloat,
                                                    station['Marca']))
        if len(self.nearFuelStations) > 1:
            # sort by price
            self.nearFuelStations = sorted(self.nearFuelStations, key=lambda fuelStation: fuelStation.price)

    def showResults(self):
        print(f"Data from: {self.lastDatabaseUpdate.strftime('%d/%m/%Y')}")

        if self.nearFuelStations == []:
            print("\n!Não existem bombas de combustível nesse raio!")
            exit()

        # Show the fuel stations list on monitor
        row_format ="{:>2} | {:<16} {:<40} {:<9} {:<15} {:<25}"
        print(row_format.format("Nº", "Marca", "Nome", "Preco", "Municipio", "Localizacao"))
        print("-" * len(row_format.format("", "", "", "", "", "")))
        for i, station in enumerate(self.nearFuelStations, start=1):
            print(row_format.format(
                i,
                station.brand,
                station.name,
                str(station.price) + " €",
                station.municipality,
                "{}, {}".format(station.latitude, station.longitude)
            ))

        if self.createKml:
            self.saveToKMLFile()

    def saveToKMLFile(self):
        kml = simplekml.Kml()
        for i, station in enumerate(self.nearFuelStations):
            kml.newpoint(name=f'{i} - {station.price}', description=f"{station.brand} - {station.name}", coords=[(station.longitude, station.latitude)])

        kml.save("fuelstations{}_[{}_{}]x{}_{}.kml".format(datetime.now().strftime("%Y%m%d"), self.latitude, self.longitude, self.searchRadiusInKm, self.fuelType))

# execute the Main class code
if __name__ == "__main__":
    CONFIG_PATH = os.path.expanduser('~')+"/.config/check-fuel-prices.yaml"
    DATA_PATH = os.path.expanduser('~')

    # create cli arguments
    parser = argparse.ArgumentParser()
    parser.add_argument("-r", "--radius", type=float, help="Radius of search in kilometers")
    parser.add_argument("-f", "--fuel", choices=TYPES_OF_FUEL.keys(), help="Type of fuel, default is 95")
    parser.add_argument("-k", "--kml", action="store_true", help="Save fuel stations in a KML file")
    parser.add_argument("latitude", type=float, help="Latitude location to search", nargs="?")
    parser.add_argument("longitude", type=float, help="Longitude location to search", nargs="?")

    # parse the arguments
    try:
        args = parser.parse_args()
    except argparse.ArgumentError:
        print("Error: Failed to parse the arguments")
        exit(1)

    # create class
    checkFuelPrices = CheckFuelPrices(CONFIG_PATH, URL, DATA_PATH)

    # update kml configuration
    checkFuelPrices.createKml = args.kml

    # update radius
    if args.radius and args.radius > 0:
        checkFuelPrices.searchRadiusInKm = args.radius

    # update fuel
    checkFuelPrices.setFuelType(args.fuel)

    # update latitude and longitude
    checkFuelPrices.setLatitude(args.latitude)
    checkFuelPrices.setLongitude(args.longitude)

    checkFuelPrices.searchDatabase()
    checkFuelPrices.showResults()


from typing import List

class Solution:
    def jobScheduling(
        self, startTime: List[int], endTime: List[int], profit: List[int]
    ) -> int:
        n = len(startTime)
        indices = sorted(range(n), key=lambda x: startTime[x])
        max_start = startTime[indices[-1]]

        dp = [0] * n
        for i in range(n - 1, -1, -1):
            idx = indices[i]
            if i == n - 1:
                # 最后一个只能选自己
                dp[i] = profit[idx]
                continue
            if endTime[idx] > max_start:
                # 结束时间超过最大开始时间
                # 如果选的话就只能选自己
                dp[i] = max(dp[i + 1], profit[idx])
                continue

            # 找到第一个开始时间大于等于当前结束时间的job
            end = endTime[idx]
            left, right = i, n - 1
            while left < right:
                mid = (left + right) >> 1
                time = startTime[indices[mid]]
                if end <= time:
                    right = mid
                else:
                    left = mid + 1
            dp[i] = max(dp[i + 1], profit[idx] + dp[left])

        return dp[0]


import pygame
pygame.init()

(width, height) = (800, 600)
screen = pygame.display.set_mode((width, height))
pygame.display.flip()
while True:
	pass

pygame.display.set_caption('Tutorial 1')

background_colour = (255,255,255)
screen.fill(background_colour)

background_colour = (255,255,255)
(width, height) = (300, 200)

screen = pygame.display.set_mode((width, height))
pygame.display.set_caption('Tutorial 1')
screen.fill(background_colour)

pygame.display.flip()

running = True
while running:
	pygame.event.get()
	for event in pygame.event.get():
		if event.type == pygame.QUIT:
			running = False


import cv2 as cv
import numpy as np

W, H = 1500, 1000

img: np.ndarray = cv.imread("img.png")
width = (img.shape[1] - W) // 2
height = (img.shape[0] - H) // 2
new = img[height:H + height, width:W + width]
print(new.shape)

cv.imshow("img", new)
cv.imwrite("img_.png", new)
cv.waitKey()


# encoding: utf-8

import contextlib
from colorama import Fore, Style
import time

def output_wrapper(fn):
    def shim(*args, **kwargs):
        name = fn.__name__
        try:
            print("{} starting".format(name) + Style.RESET_ALL)
            fn(*args, **kwargs)
            print(Fore.GREEN + "{} completed".format(name) + Fore.RESET)
        except NotImplementedError as e:
            print(Fore.YELLOW + "{} not implemented: {}".format(name, e) + Style.RESET_ALL)
        except Exception as e:
            print(Fore.RED + "{} failed ({}): {}".format(name, type(e).__name__, e) + Style.RESET_ALL)

    shim.__name__ = fn.__name__
    return shim

class Test(object):
    def __init__(self):
        self.all_tests = []

    def __call__(self, fn):
        self.all_tests.append(output_wrapper(fn))

test = Test()

def file_exists(client, path):
    return must_run(client, "[ -e {} ]".format(path)) == 0

def must_run(client, command):
    chan = client.get_transport().open_session()
    chan.exec_command(command)
    ret = chan.recv_exit_status()
    chan.close()
    return ret


import sys
import boto3

#Image
import skimage
from skimage.viewer import ImageViewer

# GUI
import PySimpleGUI as sg
import os.path

def alerte(s):
	layout = [[sg.Text(s)], [sg.Button("OK")]]

	window = sg.Window("Alerte", layout)

	while True:
		event, values = window.read()
		if event == "OK" or event == sg.WIN_CLOSED:
			break

	window.close()
	exit()

s3 = boto3.client('s3')
sqs = boto3.resource('sqs')
Rqueue = sqs.get_queue_by_name(QueueName='outbox')

try:
	file_list = os.listdir(os.getcwd())
except:
	file_list = []
fnames = [
	f
	for f in file_list
	if os.path.isfile(os.path.join(os.getcwd(), f))
	and f.lower().endswith((".png", ".gif"))
]

# First the window layout in 2 columns
file_list_column = [
	[
		sg.Text("Dossier:"),
		sg.In(size=(25, 1), enable_events=True, key="-FOLDER-", default_text=os.getcwd()),
		sg.FolderBrowse(),
	],
	[
		sg.Listbox(
			values=fnames, enable_events=True, size=(40, 20), key="-FILE LIST-"
		)
	],
]

# For now will only show the name of the file that was chosen
image_viewer_column = [
	[sg.Text("Choisir une image à flouter dans la liste à gauche:")],
	[sg.Text(size=(40, 1), key="-TOUT-")],
	[sg.Image(key="-IMAGE-")],
	[sg.Text("Valeur de sigma:"),
		sg.Slider(
			(0.1, 10),
			5,
			0.001,
			orientation="h",
			size=(40, 15),
			key="-SIGMA SLIDER-",
		),
	],
	[sg.Button("Envoyer", key="send")]
]

# ----- Full layout -----
layout = [
	[
		sg.Column(file_list_column),
		sg.VSeperator(),
		sg.Column(image_viewer_column),
	]
]

main = sg.Window("Sélectionner une image (png ou GIF)", layout).Finalize()

main.FindElement('send').Update(disabled=True)

# Run the Event Loop
filename = ''
sigma = None
newFile = False
while True:
	for message in Rqueue.receive_messages(MessageAttributeNames=['All']):
		if not message.body:
			message.delete()
			pass
		rFileName = message.message_attributes.get('Key').get('StringValue')
		print('Téléchargement de ' + rFileName)
		s3.download_file('mybucket975846589', rFileName, rFileName)
		newFile = True
		message.delete()

	event, values = main.read()
	sigma  = values["-SIGMA SLIDER-"]
	if event == "Exit" or event == sg.WIN_CLOSED:
		exit()
	if event == "send":

		if not filename:
			alerte("Aucun fichier sélectionné.")

		if not sigma:
			alerte("Valeur de sigma introuvable.")

		h,t = os.path.split(filename)
		image = skimage.io.imread(fname=filename)
		layout = [[sg.Text("Image en cours d'envoi...")]]

		r = True
		window = sg.Window("Alerte", layout, margins=(100, 50)).Finalize()
		while r:
			r = s3.upload_file(
				filename, 'mybucket975846589', t,
				ExtraArgs={'Metadata': {'mykey': 'myvalue'}}
				)

			queue = sqs.create_queue(QueueName='inbox', Attributes={'DelaySeconds': '0'})
			response = queue.send_message(MessageBody="Sending picture to process: "+ t, MessageAttributes={
						'Key': {
							'StringValue': t,
							'DataType': 'String'
							},
						'Sigma': {
							'StringValue': str(sigma),
							'DataType': 'String'
							}
						})
			r = False
		window.close()

		layout = [[sg.Text("Image envoyée....")], [sg.Button("OK")]]
		window = sg.Window("Alerte", layout)

		while True:
			event, values = window.read()
			if event == "OK" or event == sg.WIN_CLOSED:
				break
		window.close()

	# Folder name was filled in, make a list of files in the folder
	if event == "-FOLDER-" or newFile:
		newFile = False
		folder = values["-FOLDER-"]
		try:
			# Get list of files in folder
			file_list = os.listdir(folder)
		except:
			file_list = []

		fnames = [
			f
			for f in file_list
			if os.path.isfile(os.path.join(folder, f))
			and f.lower().endswith((".png", ".gif"))
		]
		main["-FILE LIST-"].update(fnames)
	elif event == "-FILE LIST-":  # A file was chosen from the listbox
		try:
			filename = os.path.join(
				values["-FOLDER-"], values["-FILE LIST-"][0]
			)
			main["-TOUT-"].update(filename)
			main["-IMAGE-"].update(filename=filename)
			main.FindElement('send').Update(disabled=False)

		except:
			pass

#main.close()


# coding=utf-8
from __future__ import unicode_literals

import tg
import paypalrestsdk
import datetime
import math
from tgext.ecommerce.lib.utils import apply_percentage_discount, get_percentage_discount

def configure_paypal(mode, client_id, client_secret):
    paypalrestsdk.configure({
        "mode": mode,
        "client_id": client_id,
        "client_secret": client_secret})

def pay(cart, redirection_url, cancel_url):
    payment = paypalrestsdk.Payment({
        "intent": "sale",
        "payer": {
            "payment_method": "paypal"
        },
        "redirect_urls": {
            "return_url": redirection_url,
            "cancel_url": cancel_url
        },
        "transactions": [{"item_list": {"items": [{"name": "Order %s" % str(cart._id),
                                                   "price": cart.order_due,
                                                   "sku": str(cart._id),
                                                   "currency": "EUR",
                                                   "quantity": 1}]},
                          "amount": {
                              "total": cart.order_due,
                              "currency": "EUR",
                          }}]
    })

    if payment.create():
        cart.order_info.payment = {'backend': 'paypal',
                                   'id': payment.id,
                                   'date': datetime.datetime.utcnow()}

        for link in payment.links:
            if link.rel == "approval_url":
                return link.href
    else:
        print(payment.error)
        return cancel_url

def confirm(cart, redirection, data):
    payerId = data['PayerID']
    return tg.url(redirection, qualified=True, params={'payer_id': payerId})

def execute(cart, data):
    paymentId = cart.order_info.payment['id']
    payment = paypalrestsdk.Payment.find(paymentId)
    result = payment.execute(data)
    payer_info = dict()
    if result:
        payer_info['first_name'] = payment.payer.payer_info.first_name
        payer_info['last_name'] = payment.payer.payer_info.last_name
        payer_info['email'] = payment.payer.payer_info.email

    return dict(result=result, payer_info=payer_info)


"""Exchange Order Book"""

from decimal import Decimal
from typing import Dict, Iterable, List, Optional, Sequence, Tuple

from .abstract_types import PluginFactory
from .constants import ALL_PLUGINS
from .fill import Fill
from .order import Side, Style
from .order_book import OrderBook

class ExchangeOrderBook:
    """An order book for an exchange.

    This maintains the order book for each ticker.
    """

    def __init__(
            self,
            tickers: Iterable[str],
            plugins: Sequence[PluginFactory] = ALL_PLUGINS
    ) -> None:
        """Initialise the exchange order book.

        Args:
            tickers (Iterable[str]): The tickers for which order books are kept.
            plugins (Sequence[PluginFactory], Optional): The plugins. Defaults
                to `ALL_PLUGINS`.
        """
        self.books: Dict[str, OrderBook] = {
            ticker: OrderBook(plugins)
            for ticker in tickers
        }

    def add_order(
            self,
            ticker: str,
            side: Side,
            price: Decimal,
            size: int,
            style: Style
    ) -> Tuple[Optional[int], List[Fill], List[int]]:
        """Add an order for a ticker.

        Args:
            ticker (str): The ticker.
            side (Side): Buy or sell.
            price (Decimal): The price at which the order should be executed.
            size (int): The size of the order.
            style (Style): The order style.

        Returns:
            Tuple[Optional[int], List[Fill], List[int]]: The id of the order (if
            an order could be created), any fills that were generated, and a
            list of cancelled order ids.
        """
        order_book = self.books[ticker]
        return order_book.add_order(side, price, size, style)

    def amend_order(self, ticker: str, order_id: int, size: int) -> None:
        """Amend aa order.

        Args:
            ticker (str): The ticker.
            order_id (int): The id of the order.
            size (int): The new size.
        """
        order_book = self.books[ticker]
        order_book.amend_order(order_id, size)

    def cancel_order(self, ticker: str, order_id: int) -> None:
        """Cancel an order.

        Args:
            ticker (str): The ticker.
            order_id (int): The order id.
        """
        order_book = self.books[ticker]
        order_book.cancel_order(order_id)


# import libs
import logging
import argparse
import pandas as pd
import numpy as np # these are two libs for calculation

# set the logger
logging.basicConfig(
                    # filename = "logfile",
                    # filemode = "w+",
                    format='%(name)s %(levelname)s %(message)s',
                    datefmt = "%H:%M:%S",
                    level=logging.INFO)
logger = logging.getLogger("hill-climbing")

def greedy_search(edges_df):
    """
    edges_df: the dataframe containing the information about edges, pd.DataFrame.
    return: influential set.
    """
    # get all the sets relationships
    groups = edges_df.groupby(edges_df.columns[1]).groups
    groups = {i: set(edges_df.iloc[groups[i], 0]) for i in groups.keys()}
    # the target set should be influenced
    target = set(edges_df.iloc[:, 0])
    # init the influential set and the current influenced set.
    influ_set, current = list(), set()
    while current != target and influ_set != list(groups.keys()):
        size, tmp = len(current), None
        for key in groups.keys():
            if key not in influ_set and size < len(current.union(groups[key])):
                size, tmp = len(current.union(groups[key])), key
        if tmp:
            influ_set.append(tmp)
            current = current.union(groups[tmp])

    return influ_set

def args_parser():
    """
    return: args containing programs arguments.
    """
    parser = argparse.ArgumentParser(description='Hill-Climbing')

    # get edgelists
    parser.add_argument("--edges", type = str, default = "./Employee_Movie_Choices.txt",
                        help= "path for edgelists file")

    # set if using debug mod
    parser.add_argument("-v", "--verbose", action= "store_true", dest= "verbose",
                        help= "enable debug info output")

    args = parser.parse_args()
    return args

def main():
    # get program arguments
    args = args_parser()

    # set the logger
    logger.setLevel(logging.DEBUG)
    if not args.verbose:
        logger.setLevel(logging.INFO)
    logger.debug("--------DEBUG enviroment start---------")

    # check the input file format
    try:
        edges_df = pd.read_table(args.edges, sep = "\t")
        logger.debug(edges_df)
        if len(edges_df.columns) != 2 or np.sum(edges_df.isnull().values):
            raise ValueError
    except:
        logger.warning("""The format of edgelists file is illegal. Plz change to 'int\tint' where two non-zero integer are separated by blankspace in each line
                          indicating there should an edge from first int to second int.
                       """)
        return

    # find the influential set
    influ_set = greedy_search(edges_df)

    logger.info("-------------Influence Set--------------")
    logger.info(" \t ".join([str(i) for i in influ_set]) + "\n")

if __name__ == "__main__":
    main()


from typing import List, Tuple

def parse(path):
    def process(e):
        return list(e.strip())
    return list(map(process, open(path).readlines()))

closure = {'{': '}', '[': ']', '(': ')', '<': '>'}

def solve(line: List[str]) -> Tuple[List[str], str]:
    lifo = []
    for char in line:
        if char in closure.values():
            last_char = lifo.pop()
            if closure[last_char] != char:
                return lifo + [last_char], char
        else:
            lifo.append(char)
    return lifo, ''

def q1(path):
    data = parse(path)
    score = {')': 3, ']': 57, '}': 1197, '>': 25137}

    def line_score(solution):
        last_char = solution[-1]
        if not last_char:
            return 0
        else:
            return score[last_char]

    return sum(map(line_score, map(solve, data)))

def q2(path):
    score = {')': 1, ']': 2, '}': 3, '>': 4}
    data = parse(path)

    def line_score(solved_line):
        res = 0
        for char in reversed(solved_line):
            res = res * 5 + score[closure[char]]
        return res

    scores = sorted(line_score(line) for (line, char) in map(solve, data) if not char)
    return scores[len(scores) // 2]

if __name__ == '__main__':
    assert q1("test.txt") == 26397
    print(q1("data.txt"))
    assert q2("test.txt") == 288957
    print(q2("data.txt"))


# Given an array of non - negative integers nums, you are initially positioned at the first index of the array.
#
# Each element in the array represents your maximum jump length at that position. Your goal is to reach the
# last index in the minimum number of jumps. You can assume that you can always reach the last index.
#
# Example 1:
# Input: nums = [2, 3, 1, 1, 4]
# Output: 2
# Explanation: The minimum number of jumps to reach the last index is 2. Jump 1 step from index 0 to 1, then
# 3 steps to the last index.
#
# Example 2:
# Input: nums = [2, 3, 0, 1, 4]
# Output: 2
#
# Constraints:
# 1 <= nums.length <= 1000
# 0 <= nums[i] <= 105
from collections import defaultdict, deque

# dp solution
def jump(nums):
    dp = [0] * len(nums)

    for i in range(1, len(nums)):
        mindpj = 9999
        for j in range(i):
            if nums[j] + j >= i:
                mindpj = min(mindpj, dp[j])
        dp[i] = mindpj + 1
    print(dp)
    return dp[-1]

# using graph
def jump1(nums):
    if len(nums) == 1:
        return 0

    n = len(nums)
    g = defaultdict(list)  # graph
    for i in range(n):  # nodes
        g[i] = []

    for i in range(n):  # edges
        for j in range(i + 1, min(i + nums[i] + 1, n)):
            g[i].append(j)
    print(g)
    # bfs shortest path -  start = 0,  end = n
    pathlen = 0
    q = deque([0])
    while q:
        pathlen += 1
        for _ in range(len(q)):
            u = q.popleft()
            for v in g[u]:
                if v == n - 1:
                    return pathlen
                if v not in q:
                    q.append(v)
    return pathlen

# class Solution:
#     def jump(self, n: List[int]) -> int:
#         currEnd = currFarthest = jump = 0
#         l = len(n)
#         for i in range(l - 1):
#             currFarthest = max(currFarthest, i + n[i])
#             if i == currEnd:
#                 jump += 1
#                 currEnd = currFarthest
#
#         return jump

print(jump([2, 3, 1, 1, 4]))
# dp        0  1  1  2  2

print(jump([2, 3, 0, 1, 4]))
# dp        0  1  1  2  2

print(jump1([2, 3, 1, 1, 4]))
print(jump1([4, 3, 1, 1, 4]))
print(jump1([1]))


import argparse
import copy
import yaml
import os

import pandas as pd
import numpy as np
from matplotlib import cm
import matplotlib.pyplot as plt
from tqdm import tqdm

def parse_args():
    parser = argparse.ArgumentParser(description='This script takes ' +
                                                 'path to input folder, with cohort files '+
                                                 'and finds intervals for all parameters.' +
                                                 '\n' + 'If output folder does not exist, script will create it.')
    parser.add_argument('-i', '--input_folder', type=str,
                        help='full path to input folder with points data')

    parser.add_argument('-o', '--output_path', type=str, help='full path to output .tsv file')
    parser.add_argument('-c', '--config', type=str, help='path to config file')

    return parser.parse_args()

def find_interval(input_filename,
                  arg1_name: str,
                  arg2_name: str,
                  threshold=0.95):

    res_df = pd.read_csv(input_filename, sep='\t')

    max_value = res_df['R2'].max()
    if max_value < threshold: # bad fitting
        return None

    opt_row = res_df.iloc[np.argmax(res_df['R2'])]
    res_df_above_threshold = res_df[res_df['R2'] > threshold]

    res_dict = {}
    arg2name = {'arg1': arg1_name,
                'arg2': arg2_name,
                'opt_scale': 'opt_scale'}

    for arg_name in ['arg1', 'arg2', 'opt_scale']:
        # min
        cur_key = f'{arg2name[arg_name]}_min'
        cur_value = res_df_above_threshold[arg_name].min()
        res_dict[cur_key] = cur_value

        # max
        cur_key = f'{arg2name[arg_name]}_max'
        cur_value = res_df_above_threshold[arg_name].max()
        res_dict[cur_key] = cur_value

        # optimal
        cur_key = f'{arg2name[arg_name]}_optimal'
        cur_value = float(opt_row[arg_name])
        res_dict[cur_key] = cur_value

    # R2 in optimal point
    cur_key = f'R2 optimal'
    cur_value = opt_row['R2']
    res_dict[cur_key] = cur_value

    return res_dict

if __name__ == '__main__':

    args = parse_args()
    config_path = args.config
    with open(config_path, 'r') as config_file:
        config_data = yaml.load(config_file, Loader=yaml.FullLoader)

    res_dict = dict()

    for file_name in tqdm(sorted(os.listdir(args.input_folder))):
        cohort_name = file_name.split('.')[0]

        full_input_file_name = os.path.join(args.input_folder, file_name)

        cur_dict = find_interval(full_input_file_name,
                                 config_data['arg1'],
                                 config_data['arg2'],
                                 config_data['threshold'])
        if cur_dict is not None:
            res_dict[cohort_name] = cur_dict
        else:
            res_dict[cohort_name] = None

    final_df = pd.DataFrame.from_dict(res_dict)
    final_df.to_csv(args.output_path, sep='\t')
    final_df.to_excel(args.output_path.replace('.tsv', '.xlsx'))


# First wallet address: txch1nchyk8kax2awmuh0ckleuslsm9wvwydpe0jvwvzx62aae6xqnuzs0hzeea
# First wallet secret key (m/12381/8444/2/0): <PrivateKey 5acf5ef55caff570b74bb1335c93f6646d8c2004a4fabdb5122398a2df41cfdb>

from blspy import (PrivateKey, AugSchemeMPL, G1Element, G2Element)
from chia.util.bech32m import decode_puzzle_hash, encode_puzzle_hash
from chia.wallet.puzzles.p2_delegated_puzzle_or_hidden_puzzle import (
    DEFAULT_HIDDEN_PUZZLE_HASH,
    calculate_synthetic_secret_key,
    puzzle_for_public_key_and_hidden_puzzle_hash
)

sk: PrivateKey = PrivateKey.from_bytes(bytes.fromhex("5acf5ef55caff570b74bb1335c93f6646d8c2004a4fabdb5122398a2df41cfdb"))
pk: G1Element = sk.get_g1()

puzzle = puzzle_for_public_key_and_hidden_puzzle_hash(
    pk, DEFAULT_HIDDEN_PUZZLE_HASH
)

puzz_hash = puzzle.get_tree_hash()
address = encode_puzzle_hash(puzz_hash, prefix="txch")
assert address == "txch1nchyk8kax2awmuh0ckleuslsm9wvwydpe0jvwvzx62aae6xqnuzs0hzeea"

print(f'pk:\t\t{pk}')
print(f'puzz_hash:\t{puzz_hash}')
print(f'address:\t{address}')


#!/usr/bin/python
# -*- coding: utf-8 -*-

import re
import os
import time
import json
import argparse
import subprocess

from numpy import median, sqrt
from libLocalization import deriveLocation

def which(program):
    '''
    check if a certain program exists
    '''
    def is_executable(fp):
        return os.path.isfile(fp) and os.access(fp, os.X_OK)
    fp, fn = os.path.split(program)
    if fp:
        if is_executable(program):
            return program
    else:
        for path in os.environ["PATH"].split(os.pathsep):
            path = path.strip('"')
            exec_file = os.path.join(path, program)
            if is_executable(exec_file):
                return exec_file
    return None

class Measurement(object):
    def __init__(self, interface, ofp=None, cali=(1.0, 0.0)):
        self.outf = None
        self.interface = interface
        # default file path for config for iw ftm_request
        self.config_fp = '/tmp/config_entry'
        if ofp:
            try:
                self.outf = open(ofp, 'w')
                self.outf.write(
                    'MAC,caliDist(cm),rawRTT(psec),rawRTTVar,rawDist(cm),' +
                    'rawDistVar,rssi(dBm),time(sec)\n'
                )
                self.outf.write(
                    "ff:ff:ff:ff:ff:ff,nan,nan,nan,nan,nan,nan,{0:.6f}\n"
                    .format(time.time())
                )
            except Exception as e:
                print(str(e))
        self.regex = (
            r"Target: (([0-9a-f]{2}:*){6}), " +
            r"status: ([0-9]), rtt: ([0-9\-]+) \(±([0-9\-]+)\) psec, " +
            r"distance: ([0-9\-]+) \(±([0-9\-]+)\) cm, rssi: ([0-9\-]+) dBm"
        )
        self.cali = cali
        if not self.check_iw_validity():
            exit(127)  # command not found

    def check_iw_validity(self):
        '''
        check if iw exists and support FTM commands
        '''
        iwPath = which('iw')
        if iwPath is None:
            print('Err: iw command not found!')
            return False
        p = subprocess.Popen(
            "iw --help | grep FTM",
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            shell=True
        )
        out, err = p.communicate()
        if err:
            print('Err: {0}'.format(err))
            return False
        if 'FTM' not in out:
            print('Err: iw command does not support FTM')
            return False
        return True

    def prepare_config_file(self, targets):
        if not isinstance(targets, dict):
            return False
        with open(self.config_fp, 'w') as of:
            for bssid in targets:
                of.write(
                    "{0} bw={1} cf={2} retries={3} asap spb={4}\n"
                    .format(
                        bssid,
                        targets[bssid]['bw'],
                        targets[bssid]['cf'],
                        targets[bssid]['retries'],
                        targets[bssid]['spb'],
                    )
                )
        return True

    def get_distance_once(self, verbose=False):
        p = subprocess.Popen(
            "iw wlp58s0 measurement ftm_request " +
            "{0}".format(self.config_fp),
            stdout=subprocess.PIPE,
            stderr=subprocess.PIPE,
            shell=True
        )
        out, err = p.communicate()
        if err:
            print(err)
            exit(13)
        matches = re.finditer(self.regex, out)
        if not matches:
            return []
        result = []
        mytime = time.time()
        for match in matches:
            mac = match.group(1)
            status = int(match.group(3))
            rtt = int(match.group(4))
            rtt_var = int(match.group(5))
            raw_distance = int(match.group(6))
            raw_distance_var = int(match.group(7))
            rssi = int(match.group(8))
            if status is not 0 or raw_distance < -1000 or raw_distance > 10000:
                continue
            distance = self.cali[0] * raw_distance + self.cali[1]
            result.append(
                (mac, distance, rtt, rtt_var,
                 raw_distance, raw_distance_var, rssi)
            )
            if verbose:
                print(
                    '*** {0} - {1}dBm - {2} (±{3:.2f}cm)'
                    .format(mac, rssi, raw_distance, sqrt(raw_distance_var))
                )
            if self.outf is not None:
                self.outf.write(
                    "{0},{1:.2f},{2},{3},{4},{5},{6},{7:.6f}\n"
                    .format(
                        mac, distance, rtt, rtt_var,
                        raw_distance, raw_distance_var,
                        rssi, mytime
                    )
                )
        return result

    def get_distance_median(self, rounds=1, verbose=False):
        '''
        use median instead of mean for less bias with small number of rounds
        '''
        result = {}
        median_result = {}
        if rounds < 1:
            rounds = 1
        for i in range(rounds):
            # no guarantee that all rounds are successful
            for each in self.get_distance_once(verbose=verbose):
                if each[0] not in result:
                    result[each[0]] = []
                result[each[0]].append(each[1:])
        for mac in result:
            median_result[mac] = (
                median([x[0] for x in result[mac]]),
                median(
                    [sqrt(x[4]) * self.cali[0] for x in result[mac]]
                )
            )
        return median_result

    def __enter__(self):
        return self

    def __exit__(self, exc_type, exc_value, traceback):
        # properly close the file when destroying the object
        if self.outf is not None:
            self.outf.write(
                "ff:ff:ff:ff:ff:ff,nan,nan,nan,nan,nan,nan,{0:.6f}\n"
                .format(time.time())
            )
            self.outf.close()

def wrapper(args):
    if os.path.isfile(args['json']):
        args['config_entry'] = json.load(open(args['json'], 'r'))
        print('Successfully loaded {0}!'.format(args['json']))
    else:  # default config
        args['config_entry'] = {
            '34:f6:4b:5e:69:1f': {
                'bw': 20,
                'cf': 2462,
                'spb': 255,
                'retries': 3
            }
        }
    counter = 1
    if args['plot']:
        try:
            import matplotlib.pyplot as plt
            from libLocalization import plotLocation
            handler = None
            fig = plt.figure()
            plt.ion()
            plt.xlim([-200, 500])
            plt.ylim([-10, 1000])
        except Exception:
            args['plot'] = False
            print('Cannot plot because lacking matplotlib!')
    with Measurement(
        args['interface'],
        ofp=args['outfp'], cali=args['cali']
    ) as m:
        while 1:
            print('Round {0}'.format(counter))
            try:
                m.prepare_config_file(args['config_entry'])
                # only print out results
                results = m.get_distance_median(
                    rounds=args['rounds'], verbose=args['verbose']
                )
                for mac in results:
                    print(
                        '* {0} is {1:.4f}cm (±{2:.2f}) away.'
                        .format(mac, results[mac][0], results[mac][1])
                    )
                # calculate location info
                if args['locs']:
                    loc = deriveLocation(args, results)
                    print(
                        '* Derived location: ({0:.3f}, {1:.3f})'
                        .format(loc[0], loc[1])
                    )
                    if args['plot']:
                        try:
                            if handler is not None:
                                handler.remove()
                            handler = plotLocation(loc)
                            if handler is None:
                                plt.close(fig)
                        except KeyboardInterrupt:
                            plt.close(fig)
                            break
                        except Exception:
                            raise
            except KeyboardInterrupt:
                break
            except Exception as e:
                err = str(e)
                print(err)
                if 'Busy' in err:
                    break
                time.sleep(10)
            counter += 1

def main():
    p = argparse.ArgumentParser(description='iw measurement tool')
    p.add_argument(
        '--cali',
        nargs=2,
        # default=(0.9376, 558.0551),  # indoor
        default=(0.8927, 553.3157),  # outdoor
        type=float,
        help="calibrate calibration params (pre-defined outdoor by default)"
    )
    p.add_argument(
        '--outfp', '-f',
        default=None,
        help="if set, will write raw fetched data to file"
    )
    p.add_argument(
        '--rounds',
        default=1,
        type=int,
        help="how many rounds to run one command; default is 1"
    )
    p.add_argument(
        '--interface', '-i',
        default='wlp58s0',
        help="set the wireless interface"
    )
    p.add_argument(
        '--json', '-j',
        default='config_entry.default',
        help="load a config json file"
    )
    p.add_argument(
        '--verbose', '-v',
        default=False,
        action="store_true",
        help="if set, show detailed messages"
    )
    p.add_argument(
        '--indoor',
        default=False,
        action="store_true",
        help=(
            "if set, use default indoor calibration params " +
            "(will be ignored if `cali` is being used)"
        )
    )
    p.add_argument(
        '--locs',
        default=False,
        action="store_true",
        help="if set, derive location and store it to file"
    )
    p.add_argument(
        '--plot',
        default=False,
        action="store_true",
        help="if set, will plot the derived location in realtime"
    )
    try:
        args = vars(p.parse_args())
    except Exception as e:
        print(str(e))
        sys.exit()
    if args['indoor'] and args['cali'] == (0.8927, 553.3157):
        args['cali'] = (0.9376, 558.0551)
    args['time_of_exec'] = int(time.time())
    # TODO: add option to change loc bounds, currently force y_min = 0
    args['loc_bounds'] = {'y_min': 0}
    # rename file path by adding time of exec
    if args['outfp']:
        fp, ext = os.path.splitext(args['outfp'])
        args['outfp'] = "{0}_{1}{2}".format(fp, args['time_of_exec'], ext)
    wrapper(args)

if __name__ == '__main__':
    main()


# To add a new cell, type '# %%'
# To add a new markdown cell, type '# %% [markdown]'
# %%
from IPython import get_ipython

# %%
#get_ipython().run_line_magic('load_ext', 'autoreload')
# get_ipython().run_line_magic('autoreload', '2')

# %%
import numpy as np
from vae.arch import VAE
import matplotlib
import tkinter
matplotlib.use('TkAgg')
import matplotlib.pyplot as plt
import os
from IPython import display
from ipywidgets import interact, interactive, fixed, interact_manual, FloatSlider
import ipywidgets as widgets
from tensorflow.keras.utils import plot_model

np.set_printoptions(precision=4, suppress = True)

# %%
vae = VAE()
vae.set_weights('./vae/weights.h5')

# %%
DIR_NAME = './data/rollout/'
file = os.listdir(DIR_NAME)[200]
print(file)
obs_data = np.load(DIR_NAME + file)['obs']
print(obs_data.shape)

# %%
plt.figure(10)
plot_model(vae.encoder, to_file='./vae/encoder.png', show_shapes=True)
plot_model(vae.decoder, to_file='./vae/decoder.png', show_shapes=True)

# %%
### output from one episode

for idx in range(0,300):
    plt.gca().cla()

    obs = obs_data[idx]
    z_decoded = vae.full_model.predict(np.array([obs]))[0]

    plt.subplot(121)
    plt.imshow( obs)
    plt.subplot(122)
    plt.imshow( z_decoded)

    plt.show()
    display.clear_output(wait=True)
    display.display(plt.gcf())

# %%
### output from the full_model
DIR_NAME = './data/rollout/'
file = os.listdir(DIR_NAME)[179]
obs_data = np.load(DIR_NAME + file)['obs']

obs = obs_data[50]
reconstruction = vae.full_model.predict(np.array([obs]))[0]

ax1 = plt.subplot(121)
plt.imshow( obs)
ax1.axis('off')
ax1.text(0.5,-0.1, "INPUT", size=12, ha="center",
         transform=ax1.transAxes)

ax2 = plt.subplot(122)
plt.imshow( reconstruction)
ax2.axis('off')
ax2.text(0.5,-0.1, "OUTPUT", size=12, ha="center",
         transform=ax2.transAxes);

# %%
mus, log_vars, _  = vae.encoder.predict(np.array([obs]))
mu = mus[0]
log_var = log_vars[0]
print("mu = " + str(mu))
print("log_var = " + str(log_var))

encoded_z = vae.encoder.predict(np.array([obs]))[0]
print("z = " + str(encoded_z))

# %%
plt.plot(mu);
plt.plot(log_var);
print('informative dimensions:')
hot_zs = np.where(abs(log_var) > 0.5)[0]
hot_zs

# %%
file1 = os.listdir(DIR_NAME)[100]
obs_data1 = np.load(DIR_NAME + file)['obs']
file2 = os.listdir(DIR_NAME)[140]
obs_data2 = np.load(DIR_NAME + file)['obs']

# %%
vae.encoder.predict(np.array([obs_data1[20]]))

# %%
top_left = vae.encoder.predict(np.array([obs_data1[20]]))[2][0]
top_right = vae.encoder.predict(np.array([obs_data1[60]]))[2][0]
bottom_left = vae.encoder.predict(np.array([obs_data2[80]]))[2][0]
sample_z = vae.encoder.predict(np.array([obs_data[60]]))[2][0]

fig, axes = plt.subplots(nrows=5, ncols=5, figsize=(32,32), sharex=True, sharey=True)
plt.subplots_adjust(hspace = 0.4)

for x in range(5):
    for y in range(5):

        z = sample_z.copy()

#         z = top_left + (top_right - top_left) * x/8 + (bottom_left - top_left) * y/8
        z[7] = (x-2)
        z[10] = (y-2)

        decoded_obs = vae.decoder.predict(np.array([z]))[0]

        axes[x,y].set_axis_off()

        axes[x,y].imshow(decoded_obs)

        axes[x,y].text(0.5,-0.1, 'z[7] ' + str(np.round(z[7],2)), size=20, ha="center",
                       transform=axes[x,y].transAxes)

        axes[x,y].text(0.5,-0.2, 'z[10] = ' + str(np.round(z[10],2)), size=20, ha="center",
                       transform=axes[x,y].transAxes)

plt.show()

# %%
def play_with_z(z0 = sample_z[0]
                ,z2 = sample_z[2]
                ,z4 = sample_z[4]
                ,z5 = sample_z[5]
                ,z6 = sample_z[6]
                ,z7 = sample_z[7]
                ,z10 = sample_z[10]
                ,z15 = sample_z[15]
                ,z24= sample_z[24]
                ,z25= sample_z[25]
                ,z27= sample_z[27]
                ):
    z = sample_z.copy()
    z[0] = z0
    z[2] = z2
    z[4] = z4
    z[5] = z5
    z[6] = z6
    z[7] = z7
    z[10] = z10
    z[15] = z15
    z[24] = z24
    z[25] = z25
    z[27] = z27

    decoded_obs = vae.decoder.predict(np.array([z]))[0]
    plt.gca().cla()
    plt.imshow( decoded_obs)

# %%
interact(play_with_z
        , z0=(-3.0,3.0,0.1)
        , z2=(-3.0,3.0,0.1)
        , z4=(-3.0,3.0,0.1)
        , z5=(-3.0,3.0,0.1)
        , z6=(-3.0,3.0,0.1)
        , z7=(-3.0,3.0,0.1)
        , z10=(-3.0,3.0,0.1)
        , z15=(-3.0,3.0,0.1)
        , z24=(-3.0,3.0,0.1)
        , z25=(-3.0,3.0,0.1)
        , z27=(-3.0,3.0,0.1)
        )

# %%


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Fri Jan 20 16:33:56 2023

@author: floriancurvaia
"""
import numpy as np
from skimage.io import imread
import time

#import os
from abbott.conversions import to_numpy
#import napari

start_time_0=time.time()

image=imread("/Users/floriancurvaia/Desktop/Uni/ETH/Labos/Pelkmans/C07_px+1929_py-0176-1.tif")
print("Reading image --- %s seconds ---\n" % (time.time() - start_time_0))
#image1=np.swapaxes(image,0,1)

#start_time_1=time.time()

#image2=to_numpy("/Users/floriancurvaia/Desktop/Uni/ETH/Labos/Pelkmans/C07_px+1929_py-0176-1.tif")
#print("Reading image --- %s seconds ---\n" % (time.time() - start_time_1))

#for i in image1:
#    print(i.shape)

class embryo:
    """
    A class to handle embryos as 4-Dimensional np arrays.
    """
    def __init__(self, image, channels_labels):

        self.labs=dict(zip(list(channels_labels), list(range(len(channels_labels))))) #Storing the labels with their index in a dictionnary

        self.array=np.swapaxes(image,0,1) #Putting the different channels as the first dimension, so each embryo can be entirely accessed for a given channel using dimension 2, 3 and 4

    def get_channel(self, chan_name):
        """

        Parameters
        ----------
        chan_name : str
            the name of the chanel for which the image of the embryo should be returned.

        Returns
        -------
        3D np array
            3-D array corresponding image of the embryo for the desired channel.

        """
        index= self.labs[chan_name]
        return self.array[index]

def appendSpherical_np(xyz): # from https://stackoverflow.com/questions/4116658/faster-numpy-cartesian-to-spherical-coordinate-conversion
    ptsnew = np.hstack((xyz, np.zeros(xyz.shape)))
    xy = xyz[:,0]**2 + xyz[:,1]**2
    ptsnew[:,3] = np.sqrt(xy + xyz[:,2]**2)
    ptsnew[:,4] = np.arctan2(np.sqrt(xy), xyz[:,2]) # for elevation angle defined from Z-axis down
    #ptsnew[:,4] = np.arctan2(xyz[:,2], np.sqrt(xy)) # for elevation angle defined from XY-plane up
    ptsnew[:,5] = np.arctan2(xyz[:,1], xyz[:,0])
    return ptsnew

chans=["B-cat", "pERM", "pMyosin", "DAPI", "pERK", "pSmad2/3", "pSmad1/5", "p56"]
start_time_2=time.time()
emb1=embryo(image, chans)
print("Creating embryo object --- %s seconds ---\n" % (time.time() - start_time_2))
del image
#del image1

#viewer = napari.Viewer()
#new_layer = viewer.add_image(emb1.get_channel("B-cat"))
#new_layer1 = viewer.add_image(np.swapaxes(emb1.get_channel("B-cat"), 0, 2))
#napari.run()
print("Whole script --- %s seconds ---\n" % (time.time() - start_time_0))


# -*- coding: utf-8 -*-
from __future__ import unicode_literals

from django.conf import settings
from django.db import migrations, models

class Migration(migrations.Migration):
    dependencies = [
        migrations.swappable_dependency(settings.AUTH_USER_MODEL),
    ]

    operations = [
        migrations.CreateModel(
            name='PitInstance',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('created_on', models.DateTimeField()),
                ('valid', models.BooleanField(default=True)),
            ],
        ),
        migrations.CreateModel(
            name='PITLevel',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('name_short', models.CharField(max_length=3)),
                ('name_long', models.CharField(max_length=16)),
                ('ordering', models.IntegerField(default=0)),
            ],
        ),
        migrations.CreateModel(
            name='Projectionist',
            fields=[
                ('id', models.AutoField(verbose_name='ID', serialize=False, auto_created=True, primary_key=True)),
                ('license_number', models.CharField(max_length=10, null=True, blank=True)),
                ('license_expiry', models.DateField(null=True, blank=True)),
                ('user', models.OneToOneField(to=settings.AUTH_USER_MODEL, on_delete=models.CASCADE)),
            ],
        ),
        migrations.AddField(
            model_name='pitinstance',
            name='pit_level',
            field=models.ForeignKey(related_name='pitinstances', to='projection.PITLevel', on_delete=models.CASCADE),
        ),
        migrations.AddField(
            model_name='pitinstance',
            name='projectionist',
            field=models.ForeignKey(related_name='pitinstances', to='projection.Projectionist', on_delete=models.CASCADE),
        ),
    ]


import time
import os
from threading import Thread, current_thread
from multiprocessing import Process, current_process

COUNT = 200000000
SLEEP = 5

"""
https://www.geeksforgeeks.org/multiprocessing-python-set-1/
https://jenkov.com/tutorials/java-concurrency/concurrency-vs-parallelism.html
https://www.geeksforgeeks.org/difference-between-multithreading-vs-multiprocessing-in-python/
"""

def io_bound(sec):
    pid = os.getpid()
    threadName = current_thread().name
    processName = current_process().name

    print(f"{pid} * {processName} * {threadName} \
        ---> Start sleeping...")
    time.sleep(sec)
    print(f"{pid} * {processName} * {threadName} \
        ---> Finished sleeping...")

def cpu_bound(n):
    pid = os.getpid()
    threadName = current_thread().name
    processName = current_process().name

    print(f"{pid} * {processName} * {threadName} \
        ---> Start counting...")

    while n > 0:
        n -= 1

    print(f"{pid} * {processName} * {threadName} \
        ---> Finished counting...")

if __name__ == "__main__":
    start = time.time()

    # YOUR CODE SNIPPET HERE
    # Code snippet for Part 1
    # io_bound(SLEEP)
    # io_bound(SLEEP)

    # Code snippet for Part 2
    # t1 = Thread(target=io_bound, args=(SLEEP,))
    # t2 = Thread(target=io_bound, args=(SLEEP,))
    # t1.start()
    # t2.start()
    # t1.join()
    # t2.join()

    # Code snippet for Part 3
    # cpu_bound(COUNT)
    # cpu_bound(COUNT)

    # Code snippet for Part 4
    # t1 = Thread(target=cpu_bound, args=(COUNT,))
    # t2 = Thread(target=cpu_bound, args=(COUNT,))
    # t1.start()
    # t2.start()
    # t1.join()
    # t2.join()

    # Code snippet for Part 5
    p1 = Process(target=cpu_bound, args=(COUNT,))
    p2 = Process(target=cpu_bound, args=(COUNT,))
    p1.start()
    p2.start()
    p1.join()
    p2.join()

    # Code snippet for Part 6
    # p1 = Process(target=io_bound, args=(SLEEP,))
    # p2 = Process(target=io_bound, args=(SLEEP,))
    # p1.start()
    # p2.start()
    # p1.join()
    # p2.join()

    end = time.time()
    print('Time taken in seconds -', end - start)


"""

"""

import numpy as np
import tensorflow as tf
from tensorflow import keras
from keras.optimizers import Adam
from buffer import ReplayBuffer
from networks import ActorNetwork, CriticNetwork

class Agent:
    def __init__(self, input_dims, alpha=0.001, beta=0.002, env=None,
                 gamma=0.99, n_actions=2, max_size=1000000, tau=0.005,
                 fc1=400, fc2=300, batch_size=65, noise=0.1) -> None:
        """
        params:
        - alpha: lr for the actor
        - beta: lr for the critic, higher as policy approximation is more sensitive than the value one.
        - env: to add noice
        - gamma: discount
        - n_actions: action dimensions.
        - max_size: of replay buffer
        - tau: soft update rule from paper.
        - fc1
        """
        #
        self.gamma=gamma
        self.tau=tau
        #
        self.memory=ReplayBuffer(max_size, input_dims, n_actions)
        self.batch_size = batch_size
        self.n_actions=n_actions
        self.noise = noise
        self.max_action = env.action_space.high[0]
        self.min_action = env.action_space.low[0]
        #
        self.actor = ActorNetwork(n_actions=n_actions, name="actor")
        self.critic = CriticNetwork(name="critic")
        self.target_actor = ActorNetwork(n_actions=n_actions, name="target_actor")
        self.target_critic = CriticNetwork(name="target_critic")

        # Compile networks
        self.actor.compile(optimizer=Adam(learning_rate=alpha))
        self.critic.compile(optimizer=Adam(learning_rate=beta))
        # Arent actually going to do gradient decent on these networks, only soft updates.
        # Have to compile them anyways. TF2 stuff.
        self.target_actor.compile(optimizer=Adam(learning_rate=alpha))
        self.target_critic.compile(optimizer=Adam(learning_rate=beta))

        # Do the first initial hard copy of the networks
        self.update_network_parameters(tau=1)

    def update_network_parameters(self, tau=None):
        """
        Implementing hardcopy as well as soft copy from paper.
        """
        # Actor
        if tau is None:
            tau=self.tau
        weights = []
        targets = self.target_actor.weights
        for i, weight in enumerate(self.actor.weights):
            weights.append(weight*tau + targets[i]*(1-tau))
        self.target_actor.set_weights(weights)
        # Critic
        weights = []
        targets = self.target_critic.weights
        for i, weight in enumerate(self.critic.weights):
            weights.append(weight*tau + targets[i]*(1-tau))
        self.target_critic.set_weights(weights)

    def remember(self, state, action, reward, new_state, done):
        # Just a clean transition function
        self.memory.store_transition(state, action, reward, new_state, done)

    def save_models(self):
        print("...... saving models ......")
        self.actor.save_weights(self.actor.checkpoint_file)
        self.critic.save_weights(self.critic.checkpoint_file)
        self.target_actor.save_weights(self.target_actor.checkpoint_file)
        self.target_critic.save_weights(self.target_critic.checkpoint_file)

    def load_models(self):
        print("...... loadning models .......")
        self.actor.load_weights(self.actor.checkpoint_file)
        self.critic.load_weights(self.critic.checkpoint_file)
        self.target_actor.load_weights(self.target_actor.checkpoint_file)
        self.target_critic.load_weights(self.target_critic.checkpoint_file)

    def choose_action(self, observation, evaluate=False):
        """
        - Observation of current state of env.
        - Evaluate => Training vs Testing of agent. Add noise in training.
        """
        #state = tf.convert_to_tensor([observation], dtype=tf.float32) # Add extra dim as "batch dim"
        try:
            states = np.reshape(observation[0],(3,1))
        except ValueError:
            states = np.reshape(observation,(3,1))
        actions = self.actor(states)

        if not evaluate: # add normal noise
            # prolem, could add something to get outside of bound of environment
            actions += tf.random.normal(shape=[self.n_actions],
                                         mean=0.0, stddev=self.noise)
            # Clip it, to avoid going outside env.
            actions = tf.clip_by_value(actions, self.min_action, self.max_action)

            return actions[0] # return zeroth element of tensor => a numpy array

    def learn(self):
        """ The bread and butter
        Dilemma: what if we haven't filled a batch size of replay buffer yet?
            1: Wait until we fill up memory
            2: Do batch size number of random actions -> Then learn
        """
        if self.memory.mem_cntr < self.batch_size:
            return

        state, action, reward, new_state, done = \
              self.memory.sample_buffer(self.batch_size)
        # Convert to tensors
        states = tf.convert_to_tensor(state, dtype=tf.float32)
        states_ = tf.convert_to_tensor(new_state, dtype=tf.float32)
        actions = tf.convert_to_tensor(action, dtype=tf.float32)
        rewards = tf.convert_to_tensor(reward, dtype=tf.float32)

        # 1: Critic loss, using the target critic
        with tf.GradientTape() as tape:
            """
            Gradient tape: stick in update rule into gradient decent.
                - tf is made for deep learning, but DRL requires a bit more involved loss.
            """
            target_actions = self.target_actor(states_) # of the next state, what should we do?
            critic_value_ = tf.squeeze(self.target_critic(
                states_, target_actions), 1) # Critic value of new state
            # The actual state and action agent took during episode.
            critic_value = tf.squeeze(self.critic(states, actions), 1)
            # The (1-done) will be 0 if the episode is over, as there are no resulting state.
            target = rewards + self.gamma*critic_value_*(1-done)
            critic_loss = keras.losses.MSE(target, critic_value)
        # Calculate and apply gradients
        critic_network_gradient = tape.gradient(critic_loss, self.critic.trainable_variables)
        self.critic.optimizer.apply_gradients(zip(critic_network_gradient, self.critic.trainable_variables))

        # 2: actor loss, using target actor
        # Essentially same approach, using context manager tape.
        with tf.GradientTape() as tape:
            # Actions according to current actor, not based on what it had in the memory.
            new_policy_actions = self.actor(states)
            # Loss using gradient -ascent-.
            # In Policy Gradient methods (PG) we want to maximize score over time => Ascent.
            actor_loss = -self.critic(states, new_policy_actions)
            actor_loss = tf.math.reduce_mean(actor_loss)

        # Calculate and apply gradients.
        actor_networ_gradient = tape.gradient(actor_loss,
                                              self.actor.trainable_variables)
        self.actor.optimizer.apply_gradients(zip(
            actor_networ_gradient, self.actor.trainable_variables
        ))

        # Soft update for target.
        self.update_network_parameters()


#!/usr/bin/env python3

from os import name
import socket
import struct
import argparse

protocols_dictionary = {
    0: ['!6s6sH'],  # Ethernet Protocol
    1: ['!BBH'],  # ICMP Packets
    6: ['!2H2L2B3H'],  # TCP protocol
    8: ['!2B3H2BH4s4s'],  # Exterior Gateway Protocol (EGP)
    17: ['!HHHH']  # UDP Protocol
}

def get_eth_address(address_byte):
    source_addr = "%x:%x:%x:%x:%x:%x" % struct.unpack(
        "BBBBBB", address_byte[:6])
    destination_addr = "%x:%x:%x:%x:%x:%x" % struct.unpack(
        "BBBBBB", address_byte[6:12])

    return source_addr, destination_addr

def get_header_upacked(protocol_nunber, buffer_to_unpack):
    packet_unpacked = struct.unpack(
        protocols_dictionary[protocol_nunber][0], buffer_to_unpack)
    return packet_unpacked

def save_to_file(user_file_name, output):
    with open(user_file_name, 'a+') as f:
        f.write(output)

def main(user_options):

    if user_options.filter is not None and len(user_options.filter) > 0:
        filtered = True
    else:
        filtered = False

    if user_options.save is not None:
        save_output = user_options.save
    else:
        save_output = False

    with socket.socket(socket.AF_PACKET, socket.SOCK_RAW, socket.ntohs(0x0003)) as socket_object:

        while True:
            result_to_print = ''
            packet = socket_object.recvfrom(30000)
            packet = packet[0]
            eth_length = 14
            eth_header = packet[:eth_length]
            eth = get_header_upacked(0, eth_header)
            eth_protocol = socket.ntohs(eth[2])
            source_mac, destination_mac = get_eth_address(packet[:12])

            result_to_print = f'''
            Destination MAC2: {destination_mac}
            Source MAC2: {source_mac}
            Protocol: {str(eth_protocol)}'''

            # The Exterior Gateway Protocol (EGP) is a routing protocol for the Internet
            if eth_protocol == 8:
                ip_header = packet[eth_length:20 + eth_length]
                ip_header_unpacked = get_header_upacked(
                    eth_protocol, ip_header)
                ip_version_len = ip_header_unpacked[0]
                ip_version = ip_version_len >> 4
                ip_header_len = (ip_version_len & 0xF) * 4

                ip_ttl = ip_header_unpacked[5]
                protocol = ip_header_unpacked[6]
                source_addr = socket.inet_ntoa(ip_header_unpacked[8])
                destination_addr = socket.inet_ntoa(ip_header_unpacked[9])
                result_to_print += f'''
                    -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
                    Version : {str(ip_version)} IP Header Length : {str(ip_header_len)}
                    TTL : {str(ip_ttl)} Protocol : {str(protocol)}
                    Source Address : {str(source_addr)}
                    Destination Address : {str(destination_addr)}
                '''

                # TCP protocol
                if protocol == 6:
                    if (filtered and 't' not in user_options.filter):
                        continue
                    tcp = ip_header_len + eth_length
                    tcp_header = packet[tcp: tcp + 20]
                    tcp_header_unpacked = get_header_upacked(
                        protocol, tcp_header)

                    source_port = tcp_header_unpacked[0]
                    dest_port = tcp_header_unpacked[1]
                    sequence = tcp_header_unpacked[2]
                    acknowledgement = tcp_header_unpacked[3]
                    tcp_header_length = (tcp_header_unpacked[4] >> 4) * 4
                    reserved = tcp_header_unpacked[4] & 0xF

                    header_size = eth_length + ip_header_len + tcp_header_length * 4
                    data_size = len(packet) - header_size

                    data = packet[header_size:]

                    result_to_print += f'''
                        Protocol number: 6 TCP
                        Source Port : {str(source_port)} Dest Port : {str(dest_port)}
                        Sequence Number: {str(sequence)} Acknowledgement: {str(acknowledgement)}
                        CP header length: {str(tcp_header_length)}
                        Reserverd: {reserved}
                        Data: {data}
                        -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
                    '''
                    print(result_to_print)

                    if save_output:
                        save_to_file('log.txt', result_to_print)

                # ICMP Packets
                # The Internet Control Message Protocol (ICMP) is a supporting protocol in the Internet protocol suite.
                elif protocol == 1:
                    if (filtered and 'i' not in user_options.filter):
                        continue
                    icmp = ip_header_len + eth_length
                    icmp_header_length = 4
                    icmp_header = packet[icmp:icmp + 4]
                    icmp_header = get_header_upacked(protocol, icmp_header)
                    icmp_type = icmp_header[0]
                    code = icmp_header[1]
                    checksum = icmp_header[2]

                    header_size = eth_length + ip_header_len + icmp_header_length
                    data_size = len(packet) - header_size

                    data = packet[header_size:]

                    result_to_print += f'''
                        Protocol number: 1 The Internet Control Message Protocol (ICMP)
                        Type : {str(icmp_type)}
                        Code : {str(code)}
                        Checksum : {str(checksum)}
                        Data: {data}
                        -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
                    '''
                    print(result_to_print)
                    if save_output:
                        save_to_file('log.txt', result_to_print)

                # UDP packets
                elif protocol == 17:
                    if (filtered and 'u' not in user_options.filter):
                        continue
                    udp = ip_header_len + eth_length
                    udp_header_length = 8
                    udp_header = packet[udp:udp + 8]
                    udp_header = get_header_upacked(protocol, udp_header)
                    source_port = udp_header[0]
                    dest_port = udp_header[1]
                    length = udp_header[2]
                    checksum = udp_header[3]

                    header_size = eth_length + ip_header_len + udp_header_length
                    data_size = len(packet) - header_size

                    data = packet[header_size:]

                    result_to_print += f'''
                        Protocol number: 17 UDP Packets
                        Source Port : {str(source_port)}
                        Dest Port : {str(dest_port)}
                        Length : {str(length)}
                        Checksum : {str(checksum)}
                        Data size: {data_size}
                        Data: {data}
                        -=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=-=
                        '''
                    print(result_to_print)
                    if save_output:
                        save_to_file('log.txt', result_to_print)

                # some other IP packet like IGMP
                else:
                    if filtered:
                        continue
                    # print('Protocol other than TCP/UDP/ICMP')
                    result_to_print += 'Protocol other than TCP/UDP/ICMP'
                    print(result_to_print)
                    if save_output:
                        save_to_file('log.txt', result_to_print)

if __name__ == '__main__':
    parser = argparse.ArgumentParser()
    parser.add_argument(
        '--filter', nargs='*', choices=['t', 'u', 'i'], help='''Filter by protocols (T)CP, (U)DP, (I)CMP. \n
        \n e.g. sniffer.py --filter t u''')
    parser.add_argument('-s', '--save', action='store_true',
                        help='Automatically save the output as log.txt')
    args = parser.parse_args()

    try:
        main(args)
    except KeyboardInterrupt:
        print('Script interrupted by the user')
        print('Bye')


import numpy as np
from scipy.special import comb
from skimage import measure
import torch

def compute_ari(table):
    """
    Compute ari, given the index table
    :param table: (r, s)
    :return:
    """

    # (r,)
    a = table.sum(axis=1)
    # (s,)
    b = table.sum(axis=0)
    n = a.sum()

    comb_a = comb(a, 2).sum()
    comb_b = comb(b, 2).sum()
    comb_n = comb(n, 2)
    comb_table = comb(table, 2).sum()

    if (comb_b == comb_a == comb_n == comb_table):
        # the perfect case
        ari = 1.0
    else:
        ari = (
            (comb_table - comb_a * comb_b / comb_n) /
            (0.5 * (comb_a + comb_b) - (comb_a * comb_b) / comb_n)
        )

    return ari

def compute_mask_ari(mask0, mask1):
    """
    Given two sets of masks, compute ari
    :param mask0: ground truth mask, (N0, H, W)
    :param mask1: predicted mask, (N1, H, W)
    :return:
    """

    # will first need to compute a table of shape (N0, N1)
    # (N0, 1, H, W)
    mask0 = mask0[:, None].byte()
    # (1, N1, H, W)
    mask1 = mask1[None, :].byte()
    # (N0, N1, H, W)
    agree = mask0 & mask1
    # (N0, N1)
    table = agree.sum(dim=-1).sum(dim=-1)

    return compute_ari(table.numpy())

def _segmentation_cover(pred, gt):
    regionsGT = []
    regionsPred = []
    total_gt = 0

    cntR = 0
    sumR = 0
    cntP = 0
    sumP = 0

    propsGT = measure.regionprops(gt)
    for prop in propsGT:
        regionsGT.append(prop.area)
    regionsGT = np.array(regionsGT).reshape(-1, 1)
    total_gt = total_gt + np.max(gt)

    best_matchesGT = np.zeros((1, total_gt))

    matches = _match_segmentation(pred, gt)

    matchesPred = np.max(matches, axis=1).reshape(-1, 1)
    matchesGT = np.max(matches, axis=0).reshape(1, -1)

    propsPred = measure.regionprops(pred)
    for prop in propsPred:
        regionsPred.append(prop.area)
    regionsPred = np.array(regionsPred).reshape(-1, 1)

    for r in range(regionsPred.shape[0]):
        cntP += regionsPred[r] * matchesPred[r]
        sumP += regionsPred[r]

    for r in range(regionsGT.shape[0]):
        cntR += regionsGT[r] * matchesGT[:, r]
        sumR += regionsGT[r]

    best_matchesGT = np.maximum(best_matchesGT, matchesGT)

    R = cntR / (sumR + (sumR == 0))
    P = cntP / (sumP + (sumP == 0))

    return R[0], P[0]
def iou_binary(mask_A, mask_B):
    assert mask_A.shape == mask_B.shape
    assert mask_A.dtype == torch.bool
    assert mask_B.dtype == torch.bool
    intersection = (mask_A * mask_B).sum((1, 2, 3))
    union = (mask_A + mask_B).sum((1, 2, 3))
    # Return -100 if union is zero, else return IOU
    return torch.where(union == 0, torch.tensor(-100.0).cuda(),
                       intersection.float() / union.float())

def average_segcover(segA, segB, ignore_background=False):
    """
    Covering of segA by segB
    segA.shape = [batch size, 1, img_dim1, img_dim2]
    segB.shape = [batch size, 1, img_dim1, img_dim2]
    scale: If true, take weighted mean over IOU values proportional to the
           the number of pixels of the mask being covered.
    Assumes labels in segA and segB are non-negative integers.
    Negative labels will be ignored.
    """

    assert segA.shape == segB.shape, f"{segA.shape} - {segB.shape}"
    assert segA.shape[1] == 1 and segB.shape[1] == 1
    bsz = segA.shape[0]
    nonignore = (segA >= 0)

    mean_scores = torch.tensor(bsz*[0.0]).cuda()
    N = torch.tensor(bsz*[0]).cuda()
    scaled_scores = torch.tensor(bsz*[0.0]).cuda()
    scaling_sum = torch.tensor(bsz*[0]).cuda()

    # Find unique label indices to iterate over
    if ignore_background:
        iter_segA = torch.unique(segA[segA > 0]).tolist()
    else:
        iter_segA = torch.unique(segA[segA >= 0]).tolist()
    iter_segB = torch.unique(segB[segB >= 0]).tolist()
    # Loop over segA
    for i in iter_segA:
        binaryA = segA == i
        if not binaryA.any():
            continue
        max_iou = torch.tensor(bsz*[0.0]).cuda()
        # Loop over segB to find max IOU
        for j in iter_segB:
            # Do not penalise pixels that are in ignore regions
            binaryB = (segB == j) * nonignore
            if not binaryB.any():
                continue
            iou = iou_binary(binaryA, binaryB)
            max_iou = torch.where(iou > max_iou, iou, max_iou)
        # Accumulate scores
        mean_scores += max_iou
        N = torch.where(binaryA.sum((1, 2, 3)) > 0, N+1, N)
        scaled_scores += binaryA.sum((1, 2, 3)).float() * max_iou
        scaling_sum += binaryA.sum((1, 2, 3))

    # Compute coverage
    mean_sc = mean_scores / torch.max(N, torch.tensor(1)).float()
    scaled_sc = scaled_scores / torch.max(scaling_sum, torch.tensor(1)).float()

    # Sanity check
    assert (mean_sc >= 0).all() and (mean_sc <= 1).all(), mean_sc
    assert (scaled_sc >= 0).all() and (scaled_sc <= 1).all(), scaled_sc
    assert (mean_scores[N == 0] == 0).all()
    assert (mean_scores[nonignore.sum((1, 2, 3)) == 0] == 0).all()
    assert (scaled_scores[N == 0] == 0).all()
    assert (scaled_scores[nonignore.sum((1, 2, 3)) == 0] == 0).all()

    # Return mean over batch dimension
    return mean_sc.mean(0), scaled_sc.mean(0)

def _match_segmentation(pred, gt):
    total_gt = np.max(gt)
    cnt = 0
    matches = np.zeros((total_gt, np.max(pred)))

    num1 = np.max(gt) + 1
    num2 = np.max(pred) + 1
    confcounts = np.zeros((num1, num2))

    # joint histogram
    sumim = 1 + gt + pred * num1

    hs, _ = np.histogram(sumim.flatten(), bins=np.linspace(1, num1*num2+1, num=num1*num2+1))
    hs = hs.reshape(confcounts.shape[1], confcounts.shape[0]).T

    confcounts = confcounts + hs
    accuracies = np.zeros((num1, num2))

    for j in range(0, num1):
        for i in range(0, num2):
            gtj = np.sum(confcounts[j, :])
            resj = np.sum(confcounts[:, i])
            gtjresj = confcounts[j, i]
            if gtj + resj - gtjresj:
                value = gtjresj / (gtj + resj - gtjresj)
                accuracies[j, i] = value
    matches[cnt:cnt + np.max(gt), :] = accuracies[1:, 1:]

    return matches.T


from operator import mod
from attr import fields
from rest_framework import serializers
from CITRApp import models
from CITRApp.validators import *

class UserSerializer(serializers.ModelSerializer):

    class Meta:
        model = models.User
        fields = '__all__'

    def validate(self, data):
        if not cpf_valido(data['cpf']):
            raise serializers.ValidationError({'CPF':'O número é inválido'})

        if not celular_valido(data['fone']):
            raise serializers.ValidationError({'Celular':'O número precisa seguir este modelo: XX XXXXX-XXXX'})

        if not cep_valido(data['cep']):
            raise serializers.ValidationError({'CEP':'O formato do CEP é inválido (XXXXX-XXX)'})

        return data

class VacancySerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Vacancy
        fields = '__all__'

class CandidacySerializer(serializers.ModelSerializer):
    class Meta:
        model = models.Candidacies
        fields = '__all__'


import os
import librosa
import glob
import soundfile as sf

# Set the path to the directory containing the audio files and text files
dir_path = os.getcwd()

# Find all the audio files in the directory
audio_files = [f for f in os.listdir(dir_path) if f.endswith(".wav")]

# Create the output directory if it doesn't exist
out_dir = "./out"
if not os.path.exists(out_dir):
    os.mkdir(out_dir)

for audio_file in audio_files:
    # Set the path to the corresponding text file
    text_file = os.path.splitext(audio_file)[0] + ".lab"
    text_file_path = os.path.join(dir_path, text_file)

    # Load the audio file
    audio, sr = librosa.load(os.path.join(dir_path, audio_file), sr=None)

    # Read the text file and create a list of segment start and end times
    segment_times = []
    with open(text_file_path, 'r') as f:
        lines = f.readlines()
        prev_end = 0
        pau_count = 0
        segment_count = 0
        for line in lines:
            start, end, label = line.strip().split()
            start = float(start) / 10000000
            end = float(end) / 10000000
            if label == 'pau':
                pau_count += 1
                if pau_count % 3 == 1:
                    segment_times.append((prev_end, start))
                    prev_end = start
                    segment_count += 1

    # Segment the audio file based on the segment start and end times
    for i, (start, end) in enumerate(segment_times):
        segment_audio = audio[int(start*sr):int(end*sr)]
        segment_file = f"{os.path.splitext(audio_file)[0]}_{i+1}.wav"
        segment_file_path = os.path.join(out_dir, segment_file)
        sf.write(segment_file_path, segment_audio, sr, 'PCM_24')

        # Create a new text file for the segment
        segment_text_file = f"{os.path.splitext(text_file)[0]}_{i+1}.txt"
        segment_text_file_path = os.path.join(out_dir, segment_text_file)
        with open(segment_text_file_path, 'w') as f:
            for line in lines:
                line_start, line_end, label = line.strip().split()
                line_start, line_end = float(line_start), float(line_end)
                line_start /= 10000000
                line_end /= 10000000
                if line_end <= start:
                    continue
                if line_start >= end:
                    break
                line_start = max(line_start, start) - start
                line_end = min(line_end, end) - start
                f.write(f"{line_start:.4f} {line_end:.4f} {label}\n")


import sqlite3

db = sqlite3.connect('sqltest.db')
ptr = db.cursor()
QUERY="INSERT INTO test (ID,Nombre,DNI) VALUES (NULL, ?, ?);"

print("Ingrese nombre")
a = raw_input()
print("Ingrese DNI")
b = raw_input()

ptr.execute(QUERY,(str(a), b))
print(QUERY,(str(a), b))

db.commit()
db.close()


"""

three-pronged-choice.py
-----------------------

Author: Michael Dickens <mdickens93@gmail.com>
Created: 2020-09-04

"""

import numpy as np
from scipy import optimize

def utility_of_consumption(eta: float, c: float) -> float:
    if eta == 1:
        return np.log(c)
    else:
        return (c**(1 - eta) + 1) / (1 - eta)

def final_utility(delta_f, r, eta, budget):
    if eta == 1:
        return (delta_f * np.log(budget * delta_f) + r - delta_f) / delta_f**2
    else:
        return eta*(budget / eta)**(1 - eta) / (1 - eta) / (r*eta - r + delta_f)**eta

def optimize_three_pronged_choice_fix_me(p, delta_f, r, eta, budget_0):
    # At attempt at dynamic programming. Calculate final spending and work
    # backward

    # TODO: this will always spend $0 on XRR, because that means the previous
    # period had the lowest possible discount rate
    def optimize_final_budget(budget_f):
        undiscounted_utility = final_utility(delta_f, r, eta, budget_f)
        discount_rate = delta_f
        budget = budget_f

        while discount_rate < delta_0:
            accum_spending = delta_0 / discount_rate - 1
            prev_accum_spending = final_accum_spending - xrr
            prev_discount_rate = delta_0 / (1 + prev_accum_spending)
            utility_fn = lambda consumption, xrr: (
                utility_of_consumption(eta, consumption)
                + (1 - prev_discount_rate) * undiscounted_utility
            )

            initial_guess = [budget * 0.1, budget * 0.1]
            opt = optimize.minimize(utility_fn, initial_guess, constraints=TODO)

def optimize_single_period(p, delta_f, r, eta, budget):
    '''
    See notebook (date 9/4) for explanation

    p: initial probability of extinction
    delta_f: final probability of extinction (different letter used to make it more visually distinct)
    r: total interest rate between initial and final choice
    eta: elasticity of marginal utility of consumption
    budget: total budget, normalized such that 1 unit of spending halves x-risk
    '''
    def utility_fn(input_vector):
        consumption = input_vector[0] * budget
        xrr = input_vector[1] * budget
        discount_rate = p / (1 + xrr)
        undiscounted_final_utility = final_utility(
            delta_f, r, eta, np.exp(r) * (budget - consumption - xrr)
        )
        return utility_of_consumption(eta, consumption) + (1 - discount_rate) * undiscounted_final_utility

    initial_guess = [0.1, 0.1]
    spending_sum_constraint = optimize.LinearConstraint(
        [1, 1],
        lb=[0],
        ub=[1],
    )
    bounds_constraint = optimize.LinearConstraint(
        np.identity(2),  # identity matrix
        lb=[0, 0],
        ub=[1, 1],
    )

    # opt = optimize.minimize(
    #     lambda x: -utility_fn(x), initial_guess,
    #     # constraints=[spending_sum_constraint, bounds_constraint]
    #     constraints=[spending_sum_constraint]
    # )

    # shitty maximize
    x = initial_guess
    prev_max = utility_fn(x)
    improving = True
    step_size = [0.00001, 0.0001]
    while improving:
        improving = False
        for i in range(2):
            if x[i] - step_size[i] < 0:
                continue
            x[i] -= step_size[i]
            if utility_fn(x) > prev_max:
                improving = True
                prev_max = utility_fn(x)
            else:
                x[i] += step_size[i]

            if x[i] + step_size[i] > 1:
                continue
            x[i] += step_size[i]
            if utility_fn(x) > prev_max:
                improving = True
                prev_max = utility_fn(x)
            else:
                x[i] -= step_size[i]

    print("{} -> {} or {}".format(x, prev_max, utility_fn(x)))

def optimize_single_period_no_present_consumption(p, delta_f, r, eta, budget, magic_risk_vanish):
    '''
    No choice about how much to consume now.

    magic_risk_vanish: If True, x-risk magically vanishes and drops to its
      lowest rate. If False, x-risk permanently stays at whatever level you set
      it to (bounded below by delta_f).
    '''
    def utility_fn(xrr_prop):
        if xrr_prop < 0:
            return -1e99
        xrr = xrr_prop * budget
        discount_rate = p / (1 + xrr)
        if not magic_risk_vanish and discount_rate >= delta_f:
            final_discount = discount_rate
        else:
            final_discount = delta_f
        undiscounted_final_utility = final_utility(
            final_discount, r, eta, np.exp(r) * (budget - xrr)
        )
        return (1 - discount_rate) * undiscounted_final_utility

    opt = optimize.minimize_scalar(lambda x: -utility_fn(x))
    print(opt)

def optimize_n_periods(num_periods, r, eta, pure_discount, epsilon, beta, years_per_period=100):
    def utility_fn(xs):
        c = [xs[2*i] for i in range(num_periods)]
        s = [xs[2*i + 1] for i in range(num_periods)]

        # scale by investment return
        for i in range(1, num_periods):
            c[i] *= (1 + r)**(i * years_per_period)
            s[i] *= (1 + r)**(i * years_per_period)

        # utility_floor = -utility_of_consumption(eta, 0.01)
        utility_floor = 0

        # Note: This doesn't really make sense because higher consumption at
        # time t decreases the probability of there being consumption at time
        # t. First one should really be t-1 instead, but then the two-period
        # model is too sparse
        initial_x_risk = 0.001
        x_risk = [
            min(1, initial_x_risk * sum(c[0:(i+1)])**epsilon * sum(s[0:(i+1)])**beta)
            for i in range(num_periods)
        ]

        return sum([
            np.product([
                ((1 - pure_discount) * (1 - x_risk[j]))**years_per_period
                for j in range(i+1)
            ])
            * (utility_of_consumption(eta, c[i]) + utility_floor)
            for i in range(num_periods)
        ])

    bounds_constraint = optimize.LinearConstraint(
        np.identity(2 * num_periods),  # identity matrix
        lb=[0.0, 0] * num_periods,
        ub=[1] * (2 * num_periods),
    )

    sum_constraint = optimize.LinearConstraint(
        np.array([1] * (2 * num_periods)),
        lb=0,
        ub=1,
    )

    opt = optimize.minimize(
        lambda xs: -utility_fn(xs),
        x0=np.array([1.0 / (2 * num_periods)] * (2 * num_periods)),
        constraints=[bounds_constraint, sum_constraint],
    )
    print(opt)

optimize_n_periods(2, r=0.05, eta=1.5, pure_discount=0.01, epsilon=0.5, beta=0.7)
print("\n")
optimize_n_periods(2, r=0.05, eta=1.5, pure_discount=0.00001, epsilon=0.5, beta=0.7)

# Some observations:
# 1. present consumption always goes close to 0 (hence why I wrote a new function to ignore it)
# 2. if magic_risk_vanish=False and budget is too small to get x-risk down to delta_f, it's best to spend almost all money on x-risk reduction because it continues to provide linear returns