# https://py.checkio.org/en/mission/even-last/
"""
Slicing basics
mylist = [1,2,3,4,5,6,7,8,9,10]
for i in mylist[::2]:
    print i,
# prints 1 3 5 7 9

for i in mylist[1::2]:
    print i,
# prints 2 4 6 8 10
"""
def checkio(array: list[int]) -> int:
    sum = 0
    product = 0

    if(len(array)<1):
        return 0
    else:
        for i in range(0,len(array),2):
                print(i)
                sum = sum + array[i]

        print("sum - ", sum)
        product =  sum * array[-1]
        print("product - ", product)
        return product

print("Example:")
print(checkio([0, 1, 2, 3, 4, 5]))

# # These "asserts" are used for self-checking
assert checkio([0, 1, 2, 3, 4, 5]) == 30
assert checkio([1, 3, 5]) == 30
assert checkio([6]) == 36
assert checkio([]) == 0

print("The mission is done! Click 'Check Solution' to earn rewards!")


import numpy as np
import cv2
from PIL import ImageGrab
import pyautogui
import pytesseract
import time
from pyfirmata import Arduino,util
import serial
result = 0;
result2 = result - 1;
x = 500
y = 2000
w = 100
h = 11007
cords = 0
thingy = True;
DeathsInGame = 0;
board = Arduino('COM3');

pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
def test_Pytesseract():
    pytesseract.pytesseract.tesseract_cmd = r"C:\Program Files\Tesseract-OCR\tesseract.exe"
    screenshot = pyautogui.screenshot();
    screenshot = np.array(screenshot);
    text = pytesseract.image_to_string(screenshot)
    cv2.imshow("img", screenshot)
    print(text);
    cv2.waitKey(0);

def screen_Capture():
    while True:
        screenshot = pyautogui.screenshot();
        screenshot = np.array(screenshot);
        text = pytesseract.image_to_string(screenshot)
        cv2.imshow('Computer Vision', screenshot)
        if cv2.waitKey(1) == ord('q'):
            break
    cv2.destroyAllWindows()
    print('Done');

# pyautogui.displayMousePosition()
def deezNuts():
    while(True):
        X = 1683;
        Y = 38;
        image = ImageGrab.grab(bbox=(1683,38,100,100))
        img_np = np.array(image)
        frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)

def Trial_2():
    while True:
        img = ImageGrab.grab(bbox=(0, 200, 1920, 1200))  # x, y, w, h #                     #
        img_np = np.array(img)
        frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
        cv2.imshow("frame", frame)
        if cv2.waitKey(1) & 0Xff == ord('q'):
            break
    cv2.destroyAllWindows()
def Trial_That_Works():
    time.sleep(2);
    print("ooooo");
    while True:
        screenshot = pyautogui.screenshot('screenshot.png', region = (1665,0, 100, 25));
        img_np = np.array(screenshot)
        frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
        img = cv2.imread('screenshot.png');
        text = pytesseract.image_to_string(img)
        #cv2.imshow("frame", frame)
        try:
            ConversionToSomethingReadable = text.split('/');
            DeathsInGame = int(ConversionToSomethingReadable[1]);
            result = DeathsInGame
            result2 = result - 1
            YourAssIsGettingTazed();
        except IndexError:
            continue;
    print('Done');

def YourAssIsGettingTazed():
    #time.sleep(5)
    if (result == result2 + 1):
        # LEDpin = board.get_pin('d:13:p')
        board.digital[12].write(1);

        time.sleep(5)
        board.digital[12].write(0);
        print("Tazed");

def Take_ScreenShot():
    time.sleep(5);
    screenshot = pyautogui.screenshot('Screenshot.jpg', region = (850,1000, 100, 50));
    img_np = np.array(screenshot)
    frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
    img = cv2.imread(frame);
    text = pytesseract.image_to_string(img)
    print(text);
'''
Trial_That_Works()
img = cv2.imread('Screenshot.jpg');
#picture = cv2.cvtColor(img, cv2.COLOR_BGR2GRAY)
text = pytesseract.image_to_string(img)
print(text);
'''
#Trial_That_Works()
#YourAssIsGettingTazed()
#cv2.destroyAllWindows()
#print('done');

# references to helpful code
'''
img = ImageGrab.grab(bbox=None)  # x, y, w, h
img_np = np.array(img) <--- use this for the *mat* error
frame = cv2.cvtColor(img_np, cv2.COLOR_BGR2GRAY)
'''
def Take_ScreenShotV2():
    #board.digital[13].write(1);
    time.sleep(5);
    while True:
        try:
            screenshot = pyautogui.screenshot('Screenshot.jpg', region=(850, 1000, 100, 50));
            img_np = np.array(screenshot)
            img = cv2.imread('Screenshot.jpg');
            text = pytesseract.image_to_string(img)
            SomeBullshit = text.split("/")
            Health = SomeBullshit[0];
            print("done");
            if Health == "0":
                YourAssIsGettingTazed()
        except IndexError:
            continue
#Take_ScreenShotV2();
#board.digital[13].write(0);

#YourAssIsGettingTazed();

'''
while True:
    Take_ScreenShotV2()
    img = cv2.imread('Screenshot.jpg');
    text = pytesseract.image_to_string(img)
    SomeBullshit = text.split("/")
    Health = int(SomeBullshit[0]);
    if Health == 0:
        YourAssIsGettingTazed()
print(Done);
'''


import numpy as np
import pandas as pd
from urllib.parse import urlencode
import pkg_resources
data_path = pkg_resources.resource_filename('phase', 'data/')

def lookup(Z):
    elems = ['H', 'He', 'Li', 'Be', 'B', 'C', 'N', 'O', 'F', 'Ne', 'Na', 'Mg',
             'Al', 'Si', 'P', 'S', 'Cl', 'Ar', 'K', 'Ca', 'Sc', 'Ti', 'V',
             'Cr', 'Mn', 'Fe', 'Co', 'Ni', 'Cu', 'Zn', 'Ga', 'Ge', 'As', 'Se',
             'Br', 'Kr', 'Rb', 'Sr', 'Y', 'Zr', 'Nb', 'Mo', 'Tc', 'Ru', 'Rh',
             'Pd', 'Ag', 'Cd', 'In', 'Sn', 'Sb', 'Te', 'I', 'Xe', 'Cs', 'Ba',
             'La', 'Ce', 'Pr', 'Nd', 'Pm', 'Sm', 'Eu', 'Gd', 'Tb', 'Dy', 'Ho',
             'Er', 'Tm', 'Yb', 'Lu', 'Hf', 'Ta', 'W', 'Re', 'Os', 'Ir', 'Pt',
             'Au', 'Hg', 'Tl', 'Pb', 'Bi', 'Po', 'At', 'Rn', 'Fr', 'Ra', 'Ac',
             'Th', 'Pa', 'U']

    return elems[Z-1]

def get_NIST_data(mat, lower=0, upper=100):
    '''
    Scrapes mass attenuation data for an element or material
    from the NIST X-ray Form Factor, Attenuation and Scattering
    Tables (FFAST)

    https://physics.nist.gov/PhysRefData/FFast/html/form.html

    Parameters
    __________
    mat : str or int
        Atomic number (Z) if int, material name if str
    lower : float or int
        Lower bound on energy range
    upper : float or int
        Upper bound on energy range (Note, FFAST only goes to 433 keV)

    Returns
    _______
    data : pd.DataFrame
        FFAST data for 'mat'
    '''

    baseurl = 'https://physics.nist.gov/cgi-bin/ffast/ffast.pl?'

    # Parses 'mat' input and sets Z and Formula paramters accordingly
    Z, Formula = (str(mat), '') if type(mat) == int else ('', str(mat))

    params = {'Z': Z,
              'Formula': Formula,
              'gtype': '4',  # Indicates mass attenuation tables
              'range': 'S',
              'lower': str(lower),
              'upper': str(upper),
              'density': '',
              'frames': 'no',
              'htmltable': '1'}

    # Returns a list of html tables as a pandas dataframe.
    # For these pages, there is only one html table, so we return the
    # first one and save as ndarray with ".values"
    data = pd.read_html(baseurl + urlencode(params), header=0)[0]
    data.columns = fix_header(data.columns)
    data = fix_E_column(data)

    return data

def fix_header(cols):
    new_cols = []
    for col in cols:
        if col == 'E keV':
            new_cols.append('E')
        if col == 'f1\xa0e atom-1':
            new_cols.append('f1')
        if col == 'f2\xa0e atom-1':
            new_cols.append('f2')
        if col == '[]Photoelectriccm2\xa0g-1':
            new_cols.append('Ph')
        if col == '[/]  Coh+inccm2\xa0g-1':
            new_cols.append('Sc')
        if col == '[]Totalcm2\xa0g-1':
            new_cols.append('Tot')
        if col == '[]K\xa0cm2\xa0g-1':
            new_cols.append('K')
        if col == 'nm':
            new_cols.append('lam')
    return new_cols

def fix_E_column(data):
    # f1 values are mistakenly concatenated with E for some elements

    try:
        # creates a mask of faulty rows
        cond = [len(val.split()) == 2 for val in data.E]
    except AttributeError:  # returns attribute error if there is no problem
        return data

    # Creates "correct" copy of E, f1 for problem rows, zeros otherwise
    nrows, ncols = data.shape
    fixed = np.zeros((nrows, 2))
    fixed[cond] = [val.split() for val in data[cond].E]

    # Copy values over from right to left up until f1
    for i in range(1, ncols-1):
        data.iloc[:, -i] = np.where(cond,
                                    data.iloc[:, -i-1], data.iloc[:, -i])
    # Copy f1 values from fixed to f1 column
    data.iloc[:, -ncols +
              1] = np.where(cond, fixed[:, 1], data.iloc[:, -ncols+1])

    # Set E values to correct values from fixed
    data.iloc[:, -ncols] = np.where(cond,
                                    fixed[:, 0], data.iloc[:, -ncols])

    # E column has mixed dtype, fix that here
    data.iloc[:, -ncols] = data.iloc[:, -ncols].astype(np.float64)

    return data

def update_all():
    Z = range(1, 93)

    for i in Z:
        print('Updating {}, Z = {}'.format(lookup(i), i))
        get_NIST_data(
            i, lower=0, upper=500).to_pickle('data/' + lookup(i) + '.pkl')

    print('Updating H2O')
    get_NIST_data('H2O', lower=0, upper=500).to_pickle('data/H2O.pkl')

def load_ffast(elem):
    '''
    Parameters
    __________
    elem : str or int
        Z or element symbol

    Returns
    _______
    data : pd.DataFrame
        ffast data for elem

    '''
    elems = [lookup(z) for z in range(1, 93)] + ['H2O']
    if type(elem) == int:
        elem = lookup(elem)
    if elem not in elems:
        print('{} is not in the database'.format(elem))
        return
    else:
        data = pd.read_pickle(data_path + '{}.pkl'.format(elem))
        return data


from flask import Flask, abort, Response, request
from socket import *

app = Flask(__name__)

@app.route('/')
def initialize():
    return "You should visit /fibonacci with several parameters to obtain the IP address"

@app.route('/register', methods=["PUT"], endpoint="register")
def register():
    data = request.json
    hostname = data.get("hostname")
    ip = data.get("ip")
    as_ip = data.get("as_ip")
    as_port = data.get("as_port")

    if not all((hostname, ip, as_ip, as_port)):
        abort(400, "Missing Parameters!")

    dns_Message = f"TYPE=A\nNAME={hostname}\nVALUE={ip}\nTTL=10"
    address = (as_ip, int(as_port))

    fibonacciSocket = socket(AF_INET, SOCK_DGRAM)
    fibonacciSocket.sendto(dns_Message.encode(), address)

    response, addr = fibonacciSocket.recvfrom(2048)
    print(response.decode())

    return Response("Registration Finished!", status=201)

@app.route('/fibonacci', methods=["GET"], endpoint="fibonacci")
def fibonacci():
    num = request.args.get("number")

    if not num:
        abort(400, "Missing Parameters")
    elif not num.isdigit():
        abort(400, "Wrong Parameter Type")

    num = int(num)

    def fib(n):
        a, b = 1, 1
        for i in range(n - 1):
            a, b = b, a + b
        return a

    return str(fib(num))

if __name__ == '__main__':
    app.run(host='0.0.0.0', port=9090, debug=True)


import core.wireless as s
import disnake
import binascii
import aiofiles
from disnake.ext import commands
from io import BytesIO
from datetime import datetime
from core.pixelpeek import protocol

class image(commands.Cog):
    def __init__(self, syscord):
        self.syscord = syscord

# {-- Photo Management Commands --}
    @commands.slash_command(description = "Send a picture of Switch screen")
    @commands.is_owner()
    async def peek(self, ctx: disnake.ApplicationCommandInteraction):
        await protocol(self, ctx)

    @commands.slash_command(description = "Save screenshot to PC")
    @commands.is_owner()
    async def screenshot(self, ctx: disnake.ApplicationCommandInteraction):
        connection = s.connection(self.syscord)
        await connection.connect()
        await connection.switch("pixelPeek")
        screen = binascii.unhexlify((await connection._r.readline())[:-1])

        # Get time and date
        timestamp = datetime.now().strftime("%d-%m-%Y %H-%M-%S")

        # Create a file and save to album
        async with aiofiles.open(f"album/{timestamp}.jpg", "wb+") as f:
            await f.write(screen)

        # Send as embed
        embed = disnake.Embed(title = f"Screenshot of {ctx.author.name}'s Switch", color = ctx.author.color)
        embed.set_image(url = "attachment://screen.jpg")

        # Footer timestamp
        index = timestamp.find(" ")
        textstamp = timestamp[:index] + "\nTime: " + timestamp[index:]
        embed.set_footer(text = f"Date: {textstamp}")

        await ctx.send(file = disnake.File(BytesIO(screen), filename = "screen.jpg"), embed = embed)

def setup(syscord):
    syscord.add_cog(image(syscord))


"""Translate english to chinese via a dict."""
import copy
from typing import List, Union

# from word_tr import word_tr
from .json_de2zh import json_de2zh

# fmt: off
def de2zh(
        text: Union[str, List[List[str]]],
) -> List[str]:
    # fmt: on
    """Translate english to chinese via a dict.

    Args
        text: to translate, list of list of str

    Returns
        res: list of str
    """
    res = copy.deepcopy(text)
    if isinstance(text, str):
        res = [text.split()]

    # if res and isinstance(res[0], str):
        # res = [line.lower().split() for line in res]

    res = ["".join([json_de2zh(word) for word in line]) for line in res]

    return res


import os
import re
import time
import openai
import tiktoken
import google.generativeai as palm
import google.api_core.exceptions
from typing import Set, Tuple
from prompt import StreamPrompt
from colorama import Fore, Style
from argparse import Namespace

class Model(object):
    api_interval = 0.00 # seconds
    cost_per_1000tokens = 0.02
    gpt_models = {"text-davinci-003", "gpt-3.5-turbo-instruct"}
    palm_models = {"models/text-bison-001"}

    def __init__(self, config: Namespace):
        self._config = config
        if self._config.model in Model.gpt_models:
            self._tokenizer = tiktoken.encoding_for_model(self._config.model)
            self._original_max_tokens = self._config.max_tokens
            self._original_temperature = self._config.temperature
            openai.api_key = os.getenv("OPENAI_API_KEY")
        else:
            palm.configure(api_key=os.getenv("GOOGLE_API_KEY"))

    def retry_with_exponential_backoff(
        func,
        initial_delay: float = 0.5,
        exponential_base: float = 2,
        max_retries: int = 20,
        errors: tuple = (
            openai.error.RateLimitError, openai.error.APIError,
            google.api_core.exceptions.ResourceExhausted, google.api_core.exceptions.ServiceUnavailable, google.api_core.exceptions.GoogleAPIError,
        ),
    ):
        """Retry a function with exponential backoff."""

        def wrapper(*args, **kwargs):
            # Initialize variables
            num_retries = 0
            delay = initial_delay
            # Loop until a successful response or max_retries is hit or an exception is raised
            while True:
                try:
                    return func(*args, **kwargs)
                # Retry on specific errors
                except errors as e:
                    # Increment retries
                    num_retries += 1
                    # Check if max retries has been reached
                    if num_retries > max_retries:
                        raise Exception(
                            Fore.RED + f"Maximum number of retries ({max_retries}) exceeded." + Style.RESET_ALL
                        )
                    # Increment the delay
                    delay *= exponential_base
                    # Sleep for the delay
                    print(Fore.YELLOW + f"Error encountered. Retry ({num_retries}) after {delay} seconds..." + Style.RESET_ALL)
                    time.sleep(delay)
                # Raise exceptions for any errors not specified
                except Exception as e:
                    raise e

        return wrapper

    @retry_with_exponential_backoff
    def complete(self, prompt: str, label_set: Set[str] = set(), temperature: float = None) -> Tuple[str, str]:
        time.sleep(Model.api_interval)
        if self._config.model in Model.gpt_models:
            return self.gpt_complete(prompt, label_set, temperature)
        elif self._config.model in Model.palm_models:
            return self.palm_complete(prompt, label_set, temperature)
        else:
            raise Exception(Fore.RED + f"Model {self._config.model} not supported." + Style.RESET_ALL)

    def gpt_complete(self, prompt: str, label_set: Set[str] = set(), temperature: float = None) -> Tuple[str, str]:
        params = vars(self._config)
        if label_set:
            max_tokens = 0
            for label in label_set:
                tokens = label
                if '(' == tokens[0]:
                    tokens = tokens[1:] # remove parentheses
                    if prompt[-1] != '(':
                        prompt += " ("
                token_ids = self._tokenizer.encode(tokens)
                max_tokens = max(max_tokens, len(token_ids))
            if max_tokens > 0:
                # params["logit_bias"] = logit_bias
                if prompt[-1] != '(':
                    max_tokens += 1 # +1 for whitespace
                params["max_tokens"] = max_tokens
        else:
            params["max_tokens"] = self._original_max_tokens

        if temperature is not None:
            params["temperature"] = temperature
        else:
            params["temperature"] = self._original_temperature
        print(Fore.GREEN + f" (Predicting with temperature: {params['temperature']}, max_tokens: {params['max_tokens']}) " + Style.RESET_ALL, end='')
        return prompt, openai.Completion.create(prompt=prompt, **params)["choices"][0]["text"]

    def palm_complete(self, prompt: str, label_set: Set[str] = set(), temperature: float = None) -> Tuple[str, str]:
        params = {
            "model": self._config.model,
            "temperature": self._config.temperature if (temperature is None) else temperature,
            "candidate_count": 1,
            "top_p": self._config.top_p,
            "max_output_tokens": self._config.max_tokens,
        }
        response = palm.generate_text(
            **params,
            prompt=prompt,
            safety_settings=[  # set all safety settings to 4 (no restrictions)
                {"category": "HARM_CATEGORY_DEROGATORY", "threshold": 4},
                {"category": "HARM_CATEGORY_TOXICITY", "threshold": 4},
                {"category": "HARM_CATEGORY_VIOLENCE", "threshold": 4},
                {"category": "HARM_CATEGORY_SEXUAL", "threshold": 4},
                {"category": "HARM_CATEGORY_MEDICAL", "threshold": 4},
                {"category": "HARM_CATEGORY_DANGEROUS", "threshold": 4}
            ]
        )
        print(Fore.GREEN + f" (Predicting with temperature: {params['temperature']}, max_tokens: {params['max_output_tokens']}) " + Style.RESET_ALL)
        if response.result is None:
            print(Fore.RED + f"Failed to generated new instance." + Style.RESET_ALL)
            raise ValueError("Failed to generated new instance.")
        return prompt, response.result

    def set_api_key(self, key: str) -> None:
        openai.api_key = key

    def count_tokens(self, text: str) -> int:
        return len(self._tokenizer.encode(text))

# for unit testing
if __name__ == "__main__":
    # model
    config = Namespace(
        model="models/text-bison-001",
        max_tokens=1024,
        temperature=0.0,
        top_p=1.0,
    )
    model_api = Model(config)

    # tasks
    from task import TaskGenerator

    task_gen = TaskGenerator(
        task_input_path="./bbh/BIG-Bench-Hard/bbh/",
        task_desc_path="./bbh/bbh_task_description.json",
        batch_size=1
    )
    task_names = ["boolean_expressions", "causal_judgement", "date_understanding", "formal_fallacies", "sports_understanding"]

    # prompt
    for task_name in task_names:
        task = task_gen.get_task(task_name)
        task_inputs = task.get_new_inputs()
        stream_prompt = StreamPrompt(
            task_desc=task.task_desc,
            inputs=task_inputs,
            num_demos=3,
            shots=[]
        )

        pred_prompt = stream_prompt.gen_prediction()
        print(f"Generating prediction from label set: {task.label_set} ->")
        pred_prompt, res_text = model_api.complete(pred_prompt, task.label_set)
        full_text = pred_prompt + res_text
        print(f"full text: {full_text}")


users = set()

# Create a set with the two users sporia123 and clarko919
users = {"sporia123","clarko919"}
print("Current users: {}\n".format(users))

# Add harrise1 to the set
users.add("harrise1")
print("Added user to the set: {}\n".format(users))

# Add clarko919 to the set again
users.add("clarko919")
print("After adding user again: {}\n".format(users))

# Check for login status and remove clarko919 from the set (log them out)
find_user = input("Enter a name: ")
if find_user in users:
    print("Logged in.\n")
else:
    print("Not logged in.\n")
selection = input("Enter user to log out\n->")
users.remove("clarko919")
print("User logged out.\nCurrent users logged in: {}\n".format(users))


#!/usr/bin/env python
# -*- coding: utf-8 -*-
import RPi.GPIO as GPIO
import time
import random

def main():
    lowhz=400
    highhz=1000

    # 使用する出力ピン(GPIO)
    pwm_pin = 18

    # GPIOピンの定義
    GPIO.setmode(GPIO.BCM)        # GPIO番号で指定
    GPIO.setup(pwm_pin, GPIO.OUT)
    pwm = GPIO.PWM(pwm_pin, lowhz)
    freq = lowhz
    pwm.start(50)

    for i in range(5000):
        if random.randrange(0,2) == 1:
            if freq == lowhz:
                pwm.ChangeFrequency(highhz)
                freq = highhz
            else:
                pwm.ChangeFrequency(lowhz)
                freq = lowhz
        time.sleep(0.02)

    pwm.stop()
    # GPIOピンの設定解除
    GPIO.cleanup()

if __name__ == "__main__":
    main()


#################################################################################
#
# pokemon.py
#
# A simple command line Python app to get information on your favourite Pokemons!
#
# Requirement: Please install the requests package by running
#   pip install requests
#
#################################################################################

import requests

# This function returns the Pokemon's information as a dictionary.
# Information is retrieved from the https://pokeapi.co/api/v2/pokemon/ endpoint.
def get_pokemon(name : str) -> dict:

  # Get Pokemon information.
  pokemon_url = "https://pokeapi.co/api/v2/pokemon/" + name
  pokemon_req = requests.get(pokemon_url)

  # Raise an exception if fetching data failed.
  if pokemon_req.status_code != 200:
    raise Exception("Request failed with status code: " + str(pokemon_req.status_code))

  # Retrieve available data from this request.
  pokemon = pokemon_req.json()
  output = {
    "name": pokemon["name"],
    "height": pokemon["height"],
    "types": [t["type"]["name"] for t in pokemon["types"]]
  }

  return {**output, **get_species(pokemon["species"]["name"], fetch_pokemons=False)}

# This function returns a Pokemon species' information as a dictionary.
# If the optional argument fetch_pokemons is true, the output dictionary will include
# a list of Pokemon varieties under this species group.
# Information is retrieved from the https://pokeapi.co/api/v2/pokemon-species/ endpoint.
def get_species(name : str, fetch_pokemons : bool = True) -> dict:

  # Get Pokemon species information.
  species_url = "https://pokeapi.co/api/v2/pokemon-species/" + name
  species_req = requests.get(species_url)

  # Raise an exception if fetching data failed.
  if species_req.status_code != 200:
    raise Exception("Request failed with status code: " + str(species_req.status_code))

  # Access the species resource for Pokemon description, habitat,
  # and legendary status.
  species = species_req.json()
  output = {}
  output["species_name"] = species["name"]
  output["is_legendary"] = species["is_legendary"]

  # Sometimes, a Pokemon species has no habitat (e.g. lucario).
  try:
    output["habitat"] = species["habitat"]["name"]
  except:
    output["habitat"] = "???"

  # Take first English-language flavour text as description.
  i = 0
  while species["flavor_text_entries"][i]["language"]["name"] != "en":
    i += 1
  output["description"] = species["flavor_text_entries"][i]["flavor_text"]\
    .replace("\n", " ").replace("\f", " ")

  if fetch_pokemons:
    output["varieties"] = [p["pokemon"]["name"] for p in species["varieties"]]

  return output

def main() -> None:

  print(
    "#######################",
    "\n\nWelcome to Pokemonpy!",
    "\n\nGet basic information on any Pokemon, or type 'exit' to quit!",
    "\n\n#######################\n"
  )

  exit = False
  while not exit:
    user_input = input("Enter a Pokemon name: ")

    if user_input == "exit":
      exit = True
      continue

    try:
      pokemon_info = get_pokemon(user_input)
      print()
    except Exception as e:
      print("\nFailed to retrieve Pokemon data!")
      print("Error:", e, "\n")
      print("Checking the api/v2/pokemon-species/ endpoint...")
      try:
        pokemon_info = get_species(user_input)
        print("Found species info! To get more details, enter one of the species' varieties.\n")
      except Exception as e1:
        print("Failed to retrieve Pokemon species data!")
        print("Error:", e1, "\n")
        continue

    for key, val in pokemon_info.items():
      print("" + key + ":", val)
    print()

  return None

if __name__ == '__main__':
  main()


from sklearn.datasets import load_files
from keras.utils import np_utils
import numpy as np
from keras.preprocessing import image
from tqdm import tqdm
from PIL import ImageFile
from numpy import save

num_classes = 2
img_width, img_height, channels = 48, 48, 3

def load_dataset(path, shuffle):
    data = load_files(path,shuffle=shuffle)
    condition_files = np.array(data['filenames'])
    print(len(condition_files))
    condition_targets = np_utils.to_categorical(np.array(data['target']), num_classes)
    return condition_files, condition_targets

def path_to_tensor(img_path):
    img = image.load_img(img_path, target_size=(img_width, img_height))
    x = image.img_to_array(img)
    return np.expand_dims(x, axis=0)

def paths_to_tensor(img_paths):
    list_of_tensors = [path_to_tensor(img_path) for img_path in tqdm(img_paths)]
    return np.vstack(list_of_tensors)

# load train, test, and validation datasets
train_files, train_targets = load_dataset('training', True)
valid_files, valid_targets = load_dataset('validation', True)
test_files, test_targets = load_dataset('testing', True)

ImageFile.LOAD_TRUNCATED_IMAGES = True

train_tensors = paths_to_tensor(train_files).astype('float32')/255
valid_tensors = paths_to_tensor(valid_files).astype('float32')/255
test_tensors = paths_to_tensor(test_files).astype('float32')/255

save('train_data.npy', train_tensors)
save('train_targets.npy', train_targets)
save('test_data.npy', test_tensors)
save('test_targets.npy', test_targets)
save('valid_data.npy', valid_tensors)
save('valid_targets.npy', valid_targets)


# coding: utf-8
from PIL import Image
from torch.utils.data import Dataset
import torch
import pandas as pd

def age_class(age):
    if age<60:
        age=0
    if age<65 and age>=60:
        age=1
    if age<70 and age>=65:
        age=2
    if age<75 and age>=70:
        age=3
    return age
class MyDataset(Dataset):
    def __init__(self, txt_path, transform=None, target_transform=None):
        data = pd.read_csv(txt_path)
        imgs, age, gender, bmi = data['root'], data['age'], data['gender'], data['bmi']

        self.imgs = imgs
        self.age = age
        self.gender = gender
        self.bmi = bmi

        self.transform = transform
        self.target_transform = target_transform

    def __getitem__(self, index):
        fn, age, gender, bmi = self.imgs[index], self.age[index], self.gender[index], self.bmi[index]
        img = Image.open(fn).convert('RGB')  # 像素值 0~255，在transfrom.totensor会除以255，使像素值变成 0~1
        age=age_class(age)
        if self.transform is not None:
            img = self.transform(img)

        return img, torch.tensor(age, dtype=torch.int64), torch.tensor(gender, dtype=torch.int64), \
               torch.tensor(bmi, dtype=torch.float64)

    def __len__(self):
        return len(self.imgs)


from boa.interop.System.App import RegisterAppCall, DynamicAppCall
from boa.interop.System.Runtime import Log, Notify

CallContract = RegisterAppCall('b16e976491982ddccd195dd73bd952a423a5e833', 'operation', 'args')

# input = b'\x33...\xb1''
# b16e976491982ddccd195dd73bd952a423a5e833

NAME = "Dynamic"

def Main(operation, args):
    if operation == "DynamicCallContract":
        if len(args) != 3:
            return False
        revesedContractAddress = args[0]
        opt = args[1]
        params = args[2]
        return DynamicCallContract(revesedContractAddress, opt, params)
    if operation == "StaticCallContract":
        opt = args[0]
        params = args[1]
        return StaticCallContract(opt,params)

    if operation == "name":
        return getName()
    return False

def DynamicCallContract(revesedContractAddress, operation, params):
    Notify(["bytearray: ", revesedContractAddress])
    res = DynamicAppCall(revesedContractAddress, operation, params)
    Notify(["111_DynamicCall", revesedContractAddress, operation, params])
    Notify(["222_DynamicCall", res])
    return res

def StaticCallContract(opt, params):
    return CallContract(opt, params)

def getName():
    return NAME


import numpy as np
import pandas as pd
import config
import time
import sys

def get_samples(species):
    data_dir = config.data_directory
    snps_dir = f"{data_dir}snps/{species}"

    hosts = ["am","ae","ao","an"]
    tp_matched = pd.read_pickle(f"{config.metadata_directory}Poyet_collection_dates.pkl")
    samples_all = list(pd.read_csv(f"{snps_dir}/snps_depth.txt.bz2",sep="\t",index_col=0, nrows=0))

    samples_between = {}

    for host in hosts:
        samples_host = config.Poyet_samples[host]
        samples_host = tp_matched[samples_host].sort_values().index
        samples_host = [sample for sample in samples_host if sample in samples_all]
        L = len(samples_host)
        if L > 4:
            samples_between[host] = [samples_host[0],samples_host[int(L/4)],samples_host[int(L/2)],samples_host[int(3*L/4)], samples_host[-1]]

    return samples_between

## implement pi within/between estimate from Schloissnig (2013)
def calculate_pi_within_between(samples_host,species,chunk_size = 40000):

    if samples_host[0] == samples_host[1]:
        samples_host = [samples_host[0]]

    data_dir = config.data_directory
    snps_dir = f"{data_dir}snps/{species}"

    pi_vals = pd.DataFrame(0,index=samples_host,columns=samples_host)
    df_depth_reader = pd.read_csv(f"{snps_dir}/snps_depth.txt.bz2",sep="\t",index_col=0,iterator=True,low_memory=False)
    df_refreq_reader = pd.read_csv(f"{snps_dir}/snps_ref_freq.txt.bz2",sep="\t",index_col=0, iterator=True,low_memory=False)

    df_depth = df_depth_reader.get_chunk(1)
    df_refreq = df_refreq_reader.get_chunk(1)

    tp_matched = pd.read_pickle(f"{config.metadata_directory}Poyet_collection_dates.pkl")

    t1 = time.time()
    reader=True
    i=0
    S=0
    G=pd.Series(0,index=samples_host)

    L = len(samples_host)
    var_sites_df = pd.DataFrame(columns=samples_host)
    var_sites_depth_df = pd.DataFrame(columns=samples_host)

    while reader:

        df_depth = df_depth_reader.get_chunk(chunk_size)
        df_refreq = df_refreq_reader.get_chunk(chunk_size)

        df_depth = df_depth[samples_host]
        df_refreq = df_refreq[samples_host]

        if df_depth.shape[0] < chunk_size:
            reader=False
            sys.stderr.write("Complete")

        df_depth = df_depth[(df_depth > 5).all(1)]

        G += df_depth.shape[0]

        df_refreq = df_refreq.loc[df_depth.index]

        df_refreq = df_refreq.where(df_refreq > .05,0)
        df_refreq = df_refreq.where(df_refreq < .95,1)

        df_altfreq = 1 - df_refreq

        df_pi_mat = (df_refreq.T.values @ df_altfreq.values) + (df_altfreq.T.values @ df_refreq.values)

        pi_vals += df_pi_mat

        var_sites = np.abs(df_refreq[samples_host[-1]] - df_refreq[samples_host[0]]) > .8

        var_sites_df = var_sites_df.append(df_refreq.loc[var_sites])
       # i+=1
       # if i > 3:
       #     reader=False

    if G[0] == 0:
        sys.stderr.write(f"Warning: no shared sites between samples {samples_host[0]} and {samples_host[1]}")
        #pi = pd.DataFrame(0)

    else:
        pi = pi_vals/G

    return(pi,G,var_sites_df)

def calculate_Fst(pi):

    Fst = 1 - ((pi.iloc[0][0] + pi.iloc[1][1])/2)/pi.iloc[0][1]

    return(Fst)

species = sys.argv[1]
samples = get_samples(species)

all_samples = []
for s in list(samples.values()):
    all_samples.extend(s)

pi_df = pd.DataFrame(0,index = all_samples,columns = all_samples)
fst_df = pd.DataFrame(0,index = all_samples,columns = all_samples)

hosts = list(samples.keys())
for h1 in range(len(hosts)):
    host1 = hosts[h1]
    print(f"host {host1}!!")
    sys.stderr.write(f"Starting host {host1} \n")
    for h2 in range(h1, len(hosts)):
        host2 = hosts[h2]
        sys.stderr.write(f"... comparing with host {host2} \n")
        for s1 in samples[host1]:

            sys.stderr.write(f"Starting sample {s1} \n")

            for s2 in samples[host2]:

                sys.stderr.write(f"... comparing with sample {s2} \n")

                pi,G,var_sites_df = calculate_pi_within_between([s1,s2], species)

                if s1 != s2:
                    between = pi.iloc[0][1]
                    pi_df.loc[s2,s1] = between
                    pi_df.loc[s1,s2] = between
                    #print(between)
                    fst = calculate_Fst(pi)
                    fst_df.loc[s2,s1] = fst
                    fst_df.loc[s1,s2] = fst
                    #print(fst)
                else:
                    within = pi.iloc[0][0]
                    print(within)
                    pi_df.loc[s1,s1] = within
                    #print(within)
            #print(pi_df)
            sys.stderr.write(f"Finished sample {s1} \n \n \n")
        sys.stderr.write(f"... finished comparing {host1} with host {host2} \n \n \n")
    sys.stderr.write(f"Finished {host1} \n \n \n")

import os
out_path = f"{config.analysis_directory}/pi/{species}"
os.makedirs(out_path, exist_ok=True)

pi_df.to_csv(f"{out_path}/{species}_pi.txt")
fst_df.to_csv(f"{out_path}/{species}_fst.txt")

sys.stderr.write(f"Files written {host1} \n \n \n")


import logging
logging.basicConfig(level=logging.INFO,format='{asctime} {levelname} ({threadName:11s}) {message}', style='{')

""" /// FUNCIONES VARIAS /// """

#funcion para descargar info diaria. Para intra se utilizará alphavange
def getInfoDiaria(ticker, start="2000-01-01",interval="1d",end=None):
    """Recibe un ticjer y devuelve la info diaria historica del papel"""
    logging.info(f"importando info de {ticker} ")
    import yfinance as yf
    df=yf.download(ticker,start=start,end=end,interval=interval,auto_adjust=True)
    return df

def getDataExcel(ticker):
    '''
       SOLO SIRVE PARA EXCEL DESCARGADO DEYAHOO FINANCE
       Busca excel de datos y devuelve DF las columnas: 'Open','High','Low','Close','Volume'.
       La columna 'Close' trae el precio ajustado.
       |
       |_ ticker:  El ticker a buscar
       '''
    import pandas as pd
    try:
        data = pd.read_excel(ticker + '.xlsx').set_index('Date').sort_index()
        #data.index.names=["Date"]
        data.columns = ['Open', 'High', 'Low','Close', 'Volume']
    except:
        try:
            data = pd.read_excel('excels_csvs/ADRs/' + ticker + '.xlsx').set_index('timestamp').sort_index()
            data.columns = ['Open', 'High', 'Low', 'Close', 'AdjClose', 'Volume']
            data['pctChange'] = data.AdjClose.pct_change()
        except:
            data = 'Sorry man no encontre el archivo en tu directorio'
    #data = data.drop(["Borrar"],axis=1)
    return data

def cruceSMA(df,fast=10,slow=20):
    """Recibe un df y una cantidad de ruedas y devuelve una columna con el SMA_ruedas"""
    logging.info(f"Creando cruce SMA, fast: {fast} slow: {fast} ")
    df["cruce"] = round((df.Close.rolling(fast).mean() / df.Close.rolling(slow).mean() -1) *100,2)
    return df

def cruceEMA(df,fast=10,slow=20): #ewm(span=ruedas)
    """Recibe un df y una cantidad de ruedas y devuelve una columna con el SMA_ruedas"""
    logging.info(f"Creando cruce EMA, fast: {fast} slow: {fast} ")
    df["cruce"] = round((df.Close.ewm(span=fast).mean() / df.Close.ewm(span=slow).mean() - 1) * 100, 2)
    return df

def getRSI(df,ruedas=14):
    """Recibe un df y una cantidad de ruedas (por defecto 14) y devuelve una columna con el RSI"""
    logging.info(f"Creando RSI, ruedas: {ruedas}")
    import numpy as np

    df["diferencia"]=df.Close.diff()
    df["dif_pos"] = np.where(df["diferencia"] > 0,df["diferencia"],0)
    df["dif_neg"] = np.where(df["diferencia"] < 0, df["diferencia"], 0)
    df["media_pos"] = df["dif_pos"].ewm(alpha=1/ruedas).mean()
    df["media_neg"] = df["dif_neg"].ewm(alpha=1/ruedas).mean()
    df["rs"] = df["media_pos"] / abs(df["media_neg"])
    df["RSI"] = round(100 - 100 / (1 + df["rs"]),2)
    df=df.drop(["diferencia","dif_pos","dif_neg","media_pos","media_neg","rs"],axis=1)
    return df

def getMACD(df,fast=12,slow=26,signal=9):
    """Recibe un df y un numero para fast (defecto 12), slow (defecto 26) u signal (defecto 9) devuelve una columna con el MACD"""
    logging.info(f"Creando MACD")
    df["ema_fast"] = df.Close.ewm(span=fast).mean()
    df["ema_slow"] = df.Close.ewm(span=slow).mean()
    df["macd"] = df["ema_fast"] - df["ema_slow"]
    df["signal"] = df["macd"].ewm(span=signal).mean()
    df["histograma"] = df["macd"] - df["signal"]
    df = df.drop(["ema_fast", "ema_slow"], axis=1)
    return df

""" /// FUNCIONES DE BACKTEST /// """

def getAlertras(df,media=True,mediaTipo="SMA",fast=5,slow=20,buy_cr=0,sell_cr=0,
                rsi=True,rsi_q=14,buy_rsi=50,sell_rsi=35,
                stopActivado=False,porcentaje=1.0,
                tipo="both"):
    """Recibe un df y los parametros y agrega los indicadores y la señal, por ahora solo SMA, EMA, RSI y STOP LOSS
    Tambien agrega volatilidad y variacion"""
    logging.info(f"Creando Alertas")

    df["Variacion"] = data.Close.pct_change()*100
    df["Volatilidad"] = data.Variacion.rolling(250).std() * 250**0.5
    #Medias
    compraMedia=True
    ventaMedia=True
    if media:
        if mediaTipo=="SMA":
            df=cruceSMA(df,fast,slow).copy()
        else:
            df=cruceEMA(df,fast,slow).copy()
        compraMedia= df.cruce > buy_cr
        ventaMedia= df.cruce < sell_cr

    #RSI
    compraRSI=True
    ventaRSI=True
    if rsi:
        df=getRSI(df,rsi_q).copy()
        compraRSI= df.RSI > buy_rsi
        ventaRSI= df.RSI < sell_rsi

    df= getSenales(df,compraMedia,ventaMedia,compraRSI,ventaRSI,stopActivado=stopActivado,porcentaje=porcentaje,tipo=tipo)
    df.set_index("Date",inplace=True)

    return df

def getSenales(df,compraMedia,ventaMedia,compraRSI,ventaRSI,stopActivado,porcentaje,tipo):
    """ ACÁ VIENE LA LOGICA CON EL STOP LOSS
    Funcion que recibe el df y los parametros y agrega señales al df
    Primero verifico la señal de stop (verifica que esté comprado o vendido antes)
    y luego si no da STOP, pasa a la otra logica que seria si da compra o venta.
    """
    logging.info(f"Añadiendo las señales")
    copia = df.copy()
    copia = copia.reset_index()

    #ACA VIENE LA LOGICA DEL STOP LOSS
    #variable stop es un diccionario que tiene el porcentaje, el precio y el estado actual
    stop={"porcentaje":porcentaje,"pStop":False,"estado":"sin señal"}
    listaSenal=[] #esta lista la hago para luego meterlo en el df

    for i in range(len(copia)):
        precioActual = copia.loc[i]["Close"]

        if stopActivado: #verifica si se toma o no el stop loss

            if tipo != "short" and stop["estado"] == "compra" and precioActual < stop["pStop"]: #stop si es long o both y está comprado
                listaSenal.append("stop")
                stop["pStop"] = False
                stop["estado"] = "stop"
                continue
            elif tipo != "long" and stop["estado"] == "venta" and precioActual > stop["pStop"]: #stop si es short y está vendido
                listaSenal.append("stop")
                stop["pStop"] = False
                stop["estado"] = "stop"
                continue

        if compraRSI[i] and compraMedia[i]: #señal compra
            if stop["estado"] == "compra": #si ya estoy comprado no pone señal
                listaSenal.append("sin señal")

            elif tipo == "short" and stop["estado"] != "venta": #si voy short y no estoy vendido no puede comprar
                listaSenal.append("sin señal")

            else: #si estoy long/both y no estoy comprado o si estoy short y esta vendido
                listaSenal.append("compra")
                stop["pStop"] = precioActual * stop["porcentaje"] #pone el nuevo stop
                stop["estado"]="compra"

        elif ventaMedia[i] and ventaRSI[i]: #señal venta
            if stop["estado"] == "venta": #si ya estoy vendido no pone señal
                listaSenal.append("sin señal")
            elif tipo == "long" and stop["estado"] != "compra": #si voy long y no estoy comprado no puedo vender
                listaSenal.append("sin señal")
            else: #si voy short/both y no estoy vendido, o si voy long y estoy comprado
                listaSenal.append("venta")
                stop["pStop"] = precioActual * (1 + (1- stop["porcentaje"]))
                stop["estado"] = "venta"

        else: #no es ni stop, ni compra ni venta
            listaSenal.append("sin señal")

    copia["Señal"] = listaSenal

    return copia

def getActions(df,tipo="both"):
    """Recibe el df, saca los sin señal y setea si es compra o venta para los primeros y ultimos trades"""
    logging.info(f"Seteando el data frame ")
    actions = df.loc [ df.Señal != "sin señal"] . copy()
    actions = actions.reset_index()

    primera = actions.iloc[0]["Señal"]
    ultima = actions.iloc[-1]["Señal"]

    #Elimina aperturas y cierres que no tienen sentido
    if tipo == "long":
        if primera == "venta":
            actions = actions.iloc[1:]
        if ultima == "compra":
            actions = actions.iloc[:-1]

    if tipo == "short":
        if primera == "compra":
            actions = actions.iloc[1:]
        if ultima == "venta":
            actions = actions.iloc[:-1]

    actions = actions.set_index("Date")
    return actions

def getTrades(df,tipo="both"): #estoy n esto

    """toma las acciones y me arma un libro con cada trade"""
    logging.info(f"Creando libro de trades")
    trades={}
    f_ini=[]
    f_fin=[]
    p_ini=[]
    p_fin=[]
    listaSide=[]
    df=df.reset_index()
    abierto = False

    for i in range(len(df)):

        if tipo != "both": #si es diferente de both, funciona la regla de que los pares abren operacion
            # tomo los pares para empezar por el primero ya que viene seteado desde antes

            if i % 2 == 0 and i != (len(df) - 1):
                f_ini.append(df.iloc[i]["Date"])
                p_ini.append(df.iloc[i]["Close"])
                listaSide.append(tipo) #cuando abre tambien pone el side
            elif i % 2 != 0:
                f_fin.append(df.iloc[i]["Date"])
                p_fin.append(df.iloc[i]["Close"])

        else:
            senal = df.iloc[i]["Señal"] #le agrego el side
            if senal == "compra":
                direccion = "long"
            elif senal == "venta":
                direccion = "short"

            if i == 0:
                #abro el primer trade
                f_ini.append(df.iloc[i]["Date"])
                p_ini.append(df.iloc[i]["Close"])
                abierto = True
                listaSide.append(direccion)

            elif i == (len(df) - 1): #si es el ultimo, lo cierro
                f_fin.append(df.iloc[i]["Date"])
                p_fin.append(df.iloc[i]["Close"])
                break

            elif senal == "stop":
                f_fin.append(df.iloc[i]["Date"])
                p_fin.append(df.iloc[i]["Close"])
                abierto = False

            elif i>0 and senal != "stop":
                if abierto == True: #si viene un trade abierto, lo cierro y abro otro
                    f_fin.append(df.iloc[i]["Date"])
                    p_fin.append(df.iloc[i]["Close"])

                    f_ini.append(df.iloc[i]["Date"])
                    p_ini.append(df.iloc[i]["Close"])
                    listaSide.append(direccion)

                else: #si vengo de un trade cerrado, solo lo abro
                    f_ini.append(df.iloc[i]["Date"])
                    p_ini.append(df.iloc[i]["Close"])
                    abierto=True
                    listaSide.append(direccion)

    trades["Fecha_ini"]=f_ini
    trades["Precio_ini"]=p_ini
    trades["Side"] = listaSide
    trades["Fecha_fin"]=f_fin
    trades["Precio_fin"]=p_fin

    trades=pd.DataFrame(trades) #creo el data frame con el diccionario

    df = df.set_index("Date") #pongo el indice como estaba
    trades = getResult(trades)

    return trades

def getResult(df):
    """Recibe un df con acciones de compra venta y stop y le agrega el Yield y la cantidad de Dias"""
    logging.info(f"Calculando Yield y Dias")
    df["Yield"] = np.where(df["Side"] == "long",(df["Precio_fin"] / df["Precio_ini"] -1)*100,(df["Precio_ini"] / df["Precio_fin"] -1)*100)
    df["Dias"] = (df.Fecha_fin - df.Fecha_ini).dt.days

    return df

def signalMetrics(df,tipo="both"):
    """Recibe un df y un side con señales y entrega variables estadisticas. Toma tiempos comprados, vendidos
    y sin posicion que hubieran operado según la estrategia.
    -Volatilidad media
    -Variacion media
    -Cantidad total de en cada estado
    -Volumen medio de cada estado
    -Tiempo total en cada estado"""

    df_copia = df.copy()
    df_copia = seteoSignal(df_copia,tipo=tipo)

    #COMIENZO CON LAS METRICAS
    #creo las medias en base a las señales
    medias = df_copia.groupby("Señal").mean()

    #genero un df nuevo que será el de las metricas, en este caso agrego volatilidad media
    res = pd.DataFrame(medias.Volatilidad)
    res.loc["Total"] = df_copia.Volatilidad.mean()

    #variacion
    res["Variacion"] = medias.Variacion
    res.loc["Total","Variacion"] = df_copia.Variacion.mean()

    #cantidad
    res["Cantidad"] = df_copia.groupby("Señal").size()
    res.loc["Total","Cantidad"] = df_copia.Señal.count()

    #volumen
    res["Volumen"] = medias.Volume /1000000
    res.loc["Total","Volumen"] = df_copia.Volume.mean() /1000000

    #tiempo
    res["TiempoIn"] = (df_copia.groupby("Señal").size() / df_copia.Señal.count()) *100
    res.loc["Total", "TiempoIn"] = 1

    #agrupado = metricas.drop(["Close","Volume","Variacion","Volatilidad"],axis=1)
    #agrupado= agrupado.groupby("Señal").size()

    return res

def seteoSignal(df,tipo="both"): # SETEO EL DF_COPIA para poder sacar metricas
    """ Recibe el df y side de signamMetrics y lo setea para colocar el estado que hubiera estado, ya sea
    comprado, vendido o sin posicion"""

    #reviso cuando da la primer señal
    df = df.reset_index()
    for i in range(len(df)):
        senal = df.iloc[i]["Señal"]
        if senal != "sin señal":
            fechaIni = i
            break

    # reviso cuando da la ultima señal
    for x in range(len(df)-1,0,-1):
        senalFin = df.iloc[x]["Señal"]
        if senalFin != "sin señal":
            fechaFin = x
            break
    df = df.set_index("Date").sort_index()

    # interpolo para que quede el "estado"
    df = df.reset_index()
    for z in range(fechaIni,fechaFin):
        if df.loc[z,"Señal"] == "sin señal" or df.loc[z,"Señal"] == "stop":
            df.loc[z, "Señal"] = np.nan

    df["Señal"] = df.Señal.fillna(method="ffill")
    df = df.set_index("Date")

    # como tomo precios close y no podría comprar al cierre, tomo las variaciones del dia posterior
    df["Señal"] = df.Señal.shift(-1)

    # seteo si es long o short
    if tipo == "long":
        df["Señal"] = np.where(df.Señal == "venta", "sin señal",
                                     df.Señal)  # saco la posicion vendido
        df["Señal"] = np.where(df.Señal == "stop", "sin señal", df.Señal)  # saco la posicion stop
    if tipo == "short":
        df["Señal"] = np.where(df.Señal == "compra", "sin señal", df.Señal)  # saco posicion compra
        df["Señal"] = np.where(df.Señal == "stop", "sin señal", df.Señal)  # saco posicion stop

    return df

""" /// PONGO EN MARCHA LA ESTRATEGIA /// """
import pandas as pd
import numpy as np
import matplotlib.pyplot as plt
pd.options.display.max_rows=50
pd.options.display.max_columns=10

#data=getDataExcel("pruebaY")
data=getInfoDiaria("AAPL")
side = "both"

#Medias
media=True
fast=5
slow=20
mediaTipo="EMA"
buy_cr=0
sell_cr=0

#RSI
rsi=True
rsi_q=14
buy_rsi=50
sell_rsi=35

#STOPLOSS
stopActivar=True
porcen=0.9

data=data.drop(["Open","High","Low"],axis=1)
data=getAlertras(data,media=media,fast=fast, slow=slow, buy_cr=buy_cr, sell_cr=sell_cr,mediaTipo=mediaTipo,
                 rsi_q=rsi_q, buy_rsi=buy_rsi, sell_rsi=sell_rsi,rsi=rsi,
                 stopActivado=stopActivar,porcentaje=porcen,tipo=side)

print(data)

acciones=getActions(data,side)
print(acciones)

trades=getTrades(acciones,side)
print(trades)

Python/PythonTraders-master/JupyterNotebook/Curso1/Clase 11 - Exposición TPs/backtest_stop_loss_NicoPacheco.py


from requests import get
from requests.exceptions import RequestException
from contextlib import closing
from bs4 import BeautifulSoup

def simple_get(url):
    """
    Attempts to get the content at `url` by making an HTTP GET request.
    If the content-type of response is some kind of HTML/XML, return the
    text content, otherwise return None
    """
    try:
        with closing(get(url, stream=True)) as resp:
            if is_good_response(resp):
                return resp.content
            else:
                return None

    except RequestException as e:
        log_error('Error during requests to {0} : {1}'.format(url, str(e)))
        return None

def is_good_response(resp):
    """
    Returns true if the response seems to be HTML, false otherwise
    """
    content_type = resp.headers['Content-Type'].lower()
    return (resp.status_code == 200
            and content_type is not None
            and content_type.find('html') > -1)

def log_error(e):
    """
    It is always a good idea to log errors.
    This function just prints them, but you can
    make it do anything.
    """
    print(e)

def get_html_soup(url):
    raw_html = simple_get(url)
    return BeautifulSoup(raw_html, 'html.parser')

def get_ica_recipe(url):
    html_soup = get_html_soup(url)

    ingreds = []

    for tag in html_soup.find_all("span", "ingredient"):
        amount = tag.get('data-amount')
        unit = tag.get('data-type')
        item = tag.string

        item = item.replace(amount, '').replace(unit, '')

        amount = amount.replace(',', '.')

        ingreds.append((amount, unit, item))

    name = html_soup.title.string.replace("| Recept ICA.se", "").strip()
    return name, ingreds

def get_koket_recipe(url):
    html_soup = get_html_soup(url)

    ingreds = []

    for tag in html_soup.find_all("span", "ingredient"):
        amount_unit = tag.contents[0].string
        item = tag.contents[1].string

        if amount_unit is None:
            amount = None
            unit = ""

        else:
            amount_unit_list = amount_unit.split()

            if len(amount_unit_list) > 1:
                amount = amount_unit_list[0].replace(',', '.')
                unit = amount_unit_list[1]

            elif len(amount_unit_list) == 1:
                amount = amount_unit_list[0].replace(',', '.')
                unit = ""

            else:
                amount = None
                unit = ""

        ingreds.append((amount, unit, item))

    name = html_soup.title.string.replace("| Recept från Köket.se", "").strip()
    return name, ingreds

def get_coop_recipe(url):
    html_soup = get_html_soup(url)

    ingreds = []

    for tag in html_soup.find_all("li", "Recipe-ingredient"):
        item = tag.find("span", "Recipe-ingredientType").string
        amount_unit = tag.find("span", "Recipe-ingredientAmount").string

        if amount_unit is None:
            amount = None
            unit = ""

        else:
            amount_unit_list = amount_unit.split()

            if len(amount_unit_list) > 1:
                amount = amount_unit_list[0].replace(',', '.')
                unit = amount_unit_list[1]

            elif len(amount_unit_list) == 1:
                amount = amount_unit_list[0].replace(',', '.')
                unit = ""

            else:
                amount = None
                unit = ""

        ingreds.append((amount, unit, item))

    name = html_soup.title.string.strip()
    return name, ingreds

def parse_recipe_from_url(html_address):
    if "www.ica.se" in html_address:
        recipe_name, ingreds = get_ica_recipe(html_address)
    elif "www.coop.se" in html_address:
        recipe_name, ingreds = get_coop_recipe(html_address)
    elif "www.koket.se" in html_address:
        recipe_name, ingreds = get_koket_recipe(html_address)
    else:
        recipe_name = ""
        ingreds = ""

    if ingreds:
        parse_successful = True
    else:
        parse_successful = False

    return recipe_name, ingreds, parse_successful

if __name__ == "__main__":
    #from_url = 'https://www.ica.se/recept/fryst-cheesecake-med-saffran-722867/'
    #from_url = 'https://www.coop.se/Recept--mat/Recept/l/lax-med-chunky-pesto-och-tagliatelle/'
    from_url = 'https://www.koket.se/sara_begner/soppor_och_grytor/korv_och_chark/korv_stroganoff/'
    recipe_title, recipe_ingreds, success = parse_recipe_from_url(from_url)
    print("Success: ", success)
    print(recipe_title)
    print(recipe_ingreds)


import sys
from io import StringIO
import unittest

class TestClass(unittest.TestCase):
    def assertIO(self, input, output):
        stdout, stdin = sys.stdout, sys.stdin
        sys.stdout, sys.stdin = StringIO(), StringIO(input)
        resolve()
        sys.stdout.seek(0)
        out = sys.stdout.read()[:-1]
        sys.stdout, sys.stdin = stdout, stdin
        self.assertEqual(out, output)

    # def test_Sample_Input_1(self):
    #     input = """2 1"""
    #     output = """4"""
    #     self.assertIO(input, output)

    def test_Sample_Input_2(self):
        input = """3 1"""
        output = """16"""
        self.assertIO(input, output)

    # def test_Sample_Input_2(self):
    #     input = """2525 -425"""
    #     output = """10314607400"""
    #     self.assertIO(input, output)

def resolve():
  N, K = map(int, input().split(" "))
  ans = 0
  for a in range(1, N+1):
    a_count = 0
    for b in range(1, N+1):
      for c in range(1, N+1):
        for d in range(1, N+1):
          if a+b-c-d == K:
            a_count += 1
            ans += 1
    # print(a, ":", a_count)
  print(ans)

if __name__ == "__main__":
  resolve()

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


# -*- coding: utf-8 -*-
"""
Created on Fri Dec 23 16:31:15 2022

@author: Nikhiel
"""

import numpy as np
import pandas as pd

import matplotlib.pyplot as plt
import seaborn as sns

def pharray(df):

    num_sigs = len(df)
    m_adc = []
    timebin = []

    for i in range(30):

        s = np.concatenate((np.array(df.iloc[:, i]),
                             np.array(df.iloc[:, i+30]),
                             np.array(df.iloc[:, i+60])), axis=None).sum()
        m_adc.append(s/num_sigs)
        timebin.append(i)

    return timebin, m_adc

df = pd.read_csv("Clean_simsigs_50k.csv")

L = df.shape[0]

t = np.arange(0,30)

x = np.tile(t, df.shape[0])

sigs = df.iloc[:, :90].to_numpy()

ph_sigs = sigs.reshape(L, 3, 30).sum(axis=1)

edgey = np.arange(0, 300, 7)

H, xe, ye = np.histogram2d(x, ph_sigs.flatten(), bins=[t,edgey], range=[[0,30],[0,400]])

tavg, avg = pharray(df)

plt.figure(figsize=(12, 6))
#sns.heatmap(H, cmap='viridis')
plt.imshow(H.T, cmap='viridis', extent=[xe[0], xe[-1], ye[-1], ye[0]], aspect='auto')
plt.plot(tavg, avg, marker='.', color='red', linestyle='', label='Average')
plt.ylim(ye[0], ye[-1])
plt.colorbar()
plt.legend()
plt.title("Pulse Height Spectrum", fontsize=12)
plt.xlabel("Time bin (100ns)", fontsize=11)
plt.ylabel("ADC", fontsize=11)
plt.tight_layout()
plt.show()

from scipy.stats import chi2

def calc_chi(obs, exp):

    L = len(obs)
    vals = np.zeros(L)
    # get the length of the arrays

    # loop over each element in the arrays and compute the squared diff divided by the expected

    for i in range(L):
        vals[i] = ((obs[i] - exp[i])**2)/(exp[i])

    chisq = vals.sum()

    return chisq

dfs = pd.read_csv("Clean_simsigs_50k.csv")
dfr = pd.read_csv("Clean_realsigs_LHC22o.csv")

t_s, a_s = pharray(dfs)
t_r, a_r = pharray(dfr)

calc_chi(obs = a_s, exp=a_r)

chi = calc_chi(obs = a_s, exp=a_r)

crit_val = chi2.ppf(q=0.95, df=30)
p_val = 1 - chi2.cdf(x=chi, df=30)

print("Chi Squared value = ", chi)
print("\nCritical value = ", crit_val)
print("\nP-value = ", p_val)


class Solution(object):
    def thirdMax(self, nums):
        """
        :type nums: List[int]
        :rtype: int
        """
        n1 = list(set(nums))
        n1.sort()
        if len(n1) < 3:
            return n1[-1]
        else:
            return n1[-3]


import spacy
from flask import Flask, request, jsonify
app = Flask(__name__)

model_dir = "model"

@app.route('/')
def predict():
    input = request.args.get("input", "This is a wonderful movie!")
    nlp = spacy.load(model_dir)
    doc = nlp(input)
    result = (input, doc.cats)
    return jsonify(result)

if __name__ == '__main__':
    app.run()


from aiogram.filters import Filter
from aiogram.types import Message

from tools import remove_proto

class IpAddress(Filter):
    async def __call__(self, m: Message) -> bool:
        text = remove_proto(m.text)
        parts = text.split('.')
        if len(parts) != 4:
            return False

        for part in parts:
            if not (part.isnumeric() and int(part) in range(0, 256)):
                return False

        return True


import os, os.path
import pickle
import pytest
from sqlalchemy import inspect
import vedana
import pkdiagram
from pkdiagram import util, Scene, ServerFileManagerModel, Person

from fdserver.extensions import db
from fdserver.models import Diagram

@pytest.fixture
def create_model(request):

    created = []

    def _create_model(session=True):
            model = ServerFileManagerModel()
            _session = pkdiagram.Session()
            if session:
                if session is True:
                    test_session = request.getfixturevalue('test_session')
                else:
                    test_session = session
                _session.init(sessionData=test_session.account_editor_dict(), syncWithServer=False)
            else:
                _session.init(syncWithServer=False)

            model.init()
            model.setSession(_session)
            assert util.wait(model.updateFinished)

            created.append(model)
            return model

    yield _create_model

    for model in created:
        if model.session:
            model.session.deinit()
        model.deinit()

def _grant_ro_access(diagrams, grantee):
    for diagram in diagrams:
        if diagram.user_id != grantee.id:
            diagram.grant_access(grantee, vedana.ACCESS_READ_ONLY)
    db.session.commit()

def test_get_index(test_user_diagrams, test_user, create_model):
    model = create_model()

    db.session.add_all((test_user, *test_user_diagrams))
    _grant_ro_access(test_user_diagrams, test_user)
    diagrams = Diagram.query.all()
    model.update()
    assert util.Condition(model.updateFinished).wait()
    assert model.rowCount() == len(test_user_diagrams) + 1
    # assert model.data(model.index(0, 0), model.IDRole) == diagrams[0].id
    # assert model.data(model.index(1, 0), model.IDRole) == diagrams[1].id
    # assert model.data(model.index(2, 0), model.IDRole) == diagrams[2].id
    # assert model.data(model.index(3, 0), model.IDRole) == diagrams[3].id
    # assert model.data(model.index(4, 0), model.IDRole) == diagrams[4].id
    # assert model.data(model.index(5, 0), model.IDRole) == diagrams[5].id
    # assert model.data(model.index(6, 0), model.IDRole) == diagrams[6].id
    # assert model.data(model.index(7, 0), model.IDRole) == diagrams[7].id
    # assert model.data(model.index(8, 0), model.IDRole) == diagrams[8].id
    # assert model.data(model.index(9, 0), model.IDRole) == diagrams[9].id
    # assert model.data(model.index(0, 0), model.IDRole) == test_user.free_diagram.id
    # assert model.data(model.index(0, 0), model.OwnerRole) == diagrams[0].user.username
    # assert model.data(model.index(1, 0), model.OwnerRole) == diagrams[1].user.username
    # assert model.data(model.index(2, 0), model.OwnerRole) == diagrams[2].user.username
    # assert model.data(model.index(3, 0), model.OwnerRole) == diagrams[3].user.username
    # assert model.data(model.index(4, 0), model.OwnerRole) == diagrams[4].user.username
    # assert model.data(model.index(5, 0), model.OwnerRole) == diagrams[5].user.username
    # assert model.data(model.index(6, 0), model.OwnerRole) == diagrams[6].user.username
    # assert model.data(model.index(7, 0), model.OwnerRole) == diagrams[7].user.username
    # assert model.data(model.index(8, 0), model.OwnerRole) == diagrams[8].user.username
    # assert model.data(model.index(9, 0), model.OwnerRole) == diagrams[9].user.username
    # assert model.data(model.index(10, 0), model.OwnerRole) == test_user.free_diagram.user.username

def test_disk_cache(test_user, test_user_diagrams, create_model):
    model = create_model()

    db.session.add_all((test_user, *test_user_diagrams))
    assert model.rowCount() == len([x for x in test_user_diagrams if x.user_id == test_user.id]) + 1
    model.write()

    model2 = ServerFileManagerModel(dataPath=model.dataPath)
    model2.init()
    model2.setSession(model.session)
    updateFinished = util.Condition(model2.updateFinished)
    indexGETResponse2 = util.Condition(model2.indexGETResponse)
    diagramGETResponse2 = util.Condition(model2.diagramGETResponse)
    assert updateFinished.wait() == True
    assert indexGETResponse2.callCount == 1
    assert diagramGETResponse2.callCount == 0
    assert model2.rowCount() == model.rowCount()
    # assert encryption.isEncrypted(model.index(0, 0).data(role=model.DiagramDataRole)) == False
    # assert encryption.isEncrypted(model.index(1, 0).data(role=model.DiagramDataRole)) == False
    # assert encryption.isEncrypted(model.index(2, 0).data(role=model.DiagramDataRole)) == False
    # assert encryption.isEncrypted(model.index(3, 0).data(role=model.DiagramDataRole)) == False
    # assert encryption.isEncrypted(model.index(4, 0).data(role=model.DiagramDataRole)) == False

# def test_cached_fds_are_encrypted(test_user_diagrams, create_model):
#     model = create_model()
#     assert model.rowCount() == 6
#     def _is_fd_encrypted(row):
#         diagram_id = model.index(row, 0).data(model.IDRole)
#         fpath = model.localPathForID(diagram_id)
#         with open(os.path.join(fpath, 'diagram.pickle'), 'rb') as f:
#             ebdata = f.read()
#             return encryption.isEncrypted(ebdata)
#     assert _is_fd_encrypted(0)
#     assert _is_fd_encrypted(1)
#     assert _is_fd_encrypted(2)
#     assert _is_fd_encrypted(3)
#     assert _is_fd_encrypted(4)

def test_dataChanged_on_poll(test_user, create_model):
    model = create_model()
    dataChanged = util.Condition(model.dataChanged)
    model.syncDiagramFromServer(test_user.free_diagram_id)
    assert dataChanged.callCount == 0
    assert model.rowCount() == 1

    # Simulate save on another machine
    diagram = Diagram.query.get(test_user.free_diagram_id)
    data = {}
    scene = Scene()
    scene.read(pickle.loads(diagram.data))
    scene.addItems(Person(name="Patrick"))
    scene.write(data)
    diagram.update(data=pickle.dumps(data), _commit=True)
    inspect(diagram).session.add(diagram)
    inspect(diagram).session.commit()

    # Polled update on this machine
    model.syncDiagramFromServer(test_user.free_diagram_id)
    assert dataChanged.callCount == 1
    assert dataChanged.callArgs[0] == (model.index(0, 0), model.index(0, 0), [model.DiagramDataRole])
    scene = Scene()
    bdata = model.data(dataChanged.callArgs[0][0], model.DiagramDataRole)
    scene.read(pickle.loads(bdata))
    assert scene.query1(name='Patrick')

    # Test sync idempotence
    model.syncDiagramFromServer(test_user.free_diagram_id)
    assert dataChanged.callCount == 1

def test_add_diagram_file(test_user, create_model):
    data = {}
    Scene().write(data)
    diagram = Diagram(
        user_id=test_user.id,
        data=pickle.dumps(data)
    )
    db.session.add(diagram)
    db.session.commit()

    model = create_model()
    db.session.add(diagram)
    _diagram = pkdiagram.Diagram.create(diagram.as_dict())
    model._addOrUpdateDiagram(_diagram)
    fpath = model.localPathForID(diagram.id)
    assert os.path.isdir(fpath) == True

def test_helpers(test_user_diagrams, create_model):
    ROW = 1

    model = create_model()
    diagram_1 = model.diagramForRow(ROW)
    diagram_id = model.index(ROW, 0).data(model.IDRole)
    assert diagram_id == diagram_1.id

    fpath = model.localPathForID(diagram_id)
    diagram = model.serverDiagramForPath(fpath)
    assert model.rowForDiagramId(diagram.id) == ROW

def test_searchText(test_user_diagrams, test_user, create_model):
    SEARCH_TERM = 'patrickkidd+unittest+2@gmail.com'

    db.session.add_all((test_user, *test_user_diagrams))
    num_matching_search = len([x for x in test_user_diagrams if SEARCH_TERM in x.user.username])
    _grant_ro_access(test_user_diagrams, test_user)

    model = create_model()
    assert model.rowCount() == len(test_user_diagrams) + 1

    model.searchText = SEARCH_TERM
    assert model.rowCount() == num_matching_search

    model.reset('searchText')
    assert model.rowCount() == len(test_user_diagrams) + 1

def test_clear_on_logout(test_user_diagrams, test_user, create_model):
    model = create_model()
    db.session.add_all(test_user_diagrams)
    assert model.rowCount() == len([x for x in test_user_diagrams if x.check_read_access(test_user)]) + 1

    cleared = util.Condition(model.cleared)
    model.session.logout()
    assert cleared.wait() == True
    assert model.rowCount() == 0

def test_dont_clear_cache_on_restart(test_user_diagrams, test_user, test_session, create_model):
    model = create_model()
    db.session.add_all(test_user_diagrams)
    assert model.rowCount() == len([x for x in test_user_diagrams if x.check_read_access(test_user)]) + 1

    model.deinit()
    session = pkdiagram.Session()
    session.init(sessionData=test_session.account_editor_dict(), syncWithServer=False)
    model2 = ServerFileManagerModel()
    model2.init()
    model2.setSession(session)
    assert util.wait(model2.updateFinished)
    assert model2.rowCount() == len([x for x in test_user_diagrams if x.check_read_access(test_user)]) + 1

def test_save_free_diagram_persists(test_session):
    # Read free diagram 1
    model = ServerFileManagerModel()
    session = pkdiagram.Session()
    session.init(sessionData=test_session.account_editor_dict(), syncWithServer=False)
    assert session.hasFeature(vedana.LICENSE_FREE) == True
    model.init()
    model.setSession(session)
    assert util.wait(model.updateFinished)
    assert model.rowCount() == 1

    # Write free diagram + logout
    scene = Scene(items=Person(name='Me'))
    bdata = pickle.dumps(scene.data())
    model.setData(model.index(0, 0), bdata, role=model.DiagramDataRole)
    session.logout()
    assert model.rowCount() == 0

    # Login + Read free diagram
    session.setData(test_session.account_editor_dict())
    assert util.wait(model.updateFinished)
    assert model.rowCount() == 1
    assert model.index(0, 0).data(model.DiagramDataRole) == bdata

def test_delete_file(qtbot, create_model):
    model = create_model()
    # session = Session()
    # session.init(sessionData=test_session.account_editor_dict(), syncWithServer=False)

    qtbot.clickYesAfter(lambda: model.deleteFileAtRow(0))
    assert model.rowCount() == 0


import os
import sys
import json
import logging
import time
import pandas as pd
import reporting.utils as utl
from requests_oauthlib import OAuth2Session

config_path = utl.config_path

class GsApi(object):
    sheets_url = 'https://sheets.googleapis.com/v4/spreadsheets'
    slides_url = 'https://slides.googleapis.com/v1/presentations'
    files_url = 'https://www.googleapis.com/drive/v3/files'
    drive_url = 'https://www.googleapis.com/drive/v3/drives'
    docs_url = 'https://docs.googleapis.com/v1/documents'
    body_str = 'body'
    cont_str = 'content'
    para_str = 'paragraph'
    head_str = 'header'
    doc_str = 'Doc'
    text_format = 'NORMAL_TEXT'

    def __init__(self):
        self.default_config = "gsapi_screenshots.json"
        self.config = None
        self.config_file = None
        self.client_id = None
        self.client_secret = None
        self.access_token = None
        self.refresh_token = None
        self.refresh_url = None
        self.sheet_id = None
        self.config_list = None
        self.client = None
        self.df = pd.DataFrame()
        self.r = None
        self.google_doc = False
        self.parse_response = self.parse_sheets_response

    def input_config(self, config):
        if str(config) == 'nan':
            logging.warning('Config file name not in vendor matrix.  '
                            'Aborting.')
            sys.exit(0)
        logging.info('Loading GS config file:{}'.format(config))
        self.config_file = os.path.join(config_path, config)
        self.load_config()
        self.check_config()

    def load_config(self):
        try:
            with open(self.config_file, 'r') as f:
                self.config = json.load(f)
        except IOError:
            logging.error('{} not found.  Aborting.'.format(self.config_file))
            sys.exit(0)
        self.client_id = self.config['client_id']
        self.client_secret = self.config['client_secret']
        self.access_token = self.config['access_token']
        self.refresh_token = self.config['refresh_token']
        self.refresh_url = self.config['refresh_url']
        self.sheet_id = self.config['sheet_id']
        self.config_list = [self.config, self.client_id, self.client_secret,
                            self.refresh_token, self.refresh_url, self.sheet_id]

    def check_config(self):
        for item in self.config_list:
            if item == '':
                logging.warning('{} not in GS config file.  '
                                'Aborting.'.format(item))
                sys.exit(0)

    def parse_fields(self, fields):
        if fields:
            for field in fields:
                if field == self.doc_str:
                    self.google_doc = True
                    self.parse_response = self.parse_google_doc

    def get_client(self):
        token = {'access_token': self.access_token,
                 'refresh_token': self.refresh_token,
                 'token_type': 'Bearer',
                 'expires_in': 3600,
                 'expires_at': 1504135205.73}
        extra = {'client_id': self.client_id,
                 'client_secret': self.client_secret}
        self.client = OAuth2Session(self.client_id, token=token)
        token = self.client.refresh_token(self.refresh_url, **extra)
        self.client = OAuth2Session(self.client_id, token=token)

    def create_url(self):
        if self.google_doc:
            url = '{}/{}'.format(self.docs_url, self.sheet_id)
        else:
            url = '{}/{}/values/A:ZZ'.format(self.sheets_url, self.sheet_id)
        return url

    def parse_sheets_response(self, response):
        if 'values' in response:
            self.df = pd.DataFrame(response['values'])
            logging.info('Data received, returning dataframe.')
        else:
            logging.warning('Values not in response: {}'.format(response))
            self.df = pd.DataFrame()
        return self.df

    def get_data(self, sd=None, ed=None, fields=None):
        logging.info('Getting df from sheet: {}'.format(self.sheet_id))
        self.parse_fields(fields)
        self.get_client()
        url = self.create_url()
        r = self.client.get(url)
        response = r.json()
        self.df = self.parse_response(response)
        return self.df

    def create_presentation(self, presentation_name=None):
        logging.info('Creating GSlides Presentation: {}'.format(
            presentation_name))
        body = {
            "title": presentation_name,
        }
        response = self.client.post(url=self.slides_url, json=body)
        response = response.json()
        presentation_id = response["presentationId"]
        self.add_permissions(presentation_id)
        return presentation_id

    def add_permissions(self, presentation_id, domain="liquidarcade.com"):
        url = self.files_url + "/" + presentation_id + "/permissions"
        body = {
            "role": "writer",
            "type": "domain",
            "domain": domain,
            "allowFileDiscovery": True
        }
        response = self.client.post(url=url, json=body)
        return response

    def add_image_slide(self, presentation_id=None, ad_id=None,
                        image_url=None):
        logging.info('Creating slide and adding image: {}, {}'.format(
            ad_id, image_url))
        url = self.slides_url + "/" + presentation_id + ":batchUpdate"
        headers = {"Content-Type": "application/json"}
        body = {
            "requests": [
                {
                    "createSlide": {
                        "objectId": ad_id
                    }
                },
                {
                    "createImage": {
                        "elementProperties": {
                            "pageObjectId": ad_id
                        },
                        "url": image_url
                    }
                }
            ]
        }
        response = self.client.post(url=url, json=body, headers=headers)
        return response

    def add_speaker_notes(self, presentation_id=None, page_id=None, text=''):
        logging.info('Adding speaker note: {}'.format(text))
        url = self.slides_url + "/" + presentation_id + "/pages/" + page_id
        notes_id = None
        for x in range(1, 11):
            response = self.client.get(url)
            response = response.json()
            if "slideProperties" in response:
                notes_id = response["slideProperties"][
                    "notesPage"]["notesProperties"]["speakerNotesObjectId"]
                break
            else:
                logging.warning('Slide not created yet. Attempt: {}'.format(x))
                time.sleep(3)
        if not notes_id:
            return {'error': 'Unable to add speaker notes to slide '
                             '{}.'.format(page_id)}
        url = self.slides_url + "/" + presentation_id + ":batchUpdate"
        headers = {"Content-Type": "application/json"}
        body = {
            "requests": [
                {
                    "insertText": {
                        "objectId": notes_id,
                        "insertionIndex": 0,
                        "text": text
                    }
                }
            ]
        }
        response = self.client.post(url=url, json=body, headers=headers)
        return response

    def parse_google_doc(self, r):
        if self.body_str not in r:
            logging.warning('Body not in response {}.'.format(r))
            return pd.DataFrame()
        r = r[self.body_str][self.cont_str]
        paragraph = []
        new_paragraph = {}
        for x in r:
            if self.para_str in x:
                tc = x[self.para_str]['elements'][0]['textRun'][self.cont_str]
                if tc == '\n':
                    paragraph.append(new_paragraph)
                    new_paragraph = {}
                    continue
                else:
                    if new_paragraph:
                        new_paragraph[self.cont_str] += tc
                    else:
                        new_paragraph[self.head_str] = tc.strip('\n')
                        new_paragraph[self.cont_str] = ''
        self.df = pd.DataFrame(paragraph)
        return self.df

    def create_google_doc(self, title=None):
        logging.info('Creating GSlides Presentation: {}'.format(title))
        body = {
            "title": title,
        }
        response = self.client.post(url=self.docs_url, json=body)
        response = response.json()
        doc_id = response["documentId"]
        self.add_permissions(doc_id)
        return doc_id

    @staticmethod
    def get_format_req(start_ind=1, end_ind=1, style=text_format):
        format_req = {
            "updateParagraphStyle": {
                "range": {
                    "startIndex": start_ind,
                    "endIndex": end_ind
                },
                "paragraphStyle": {
                    "namedStyleType": style
                },
                "fields": "namedStyleType"
            }
        }
        return format_req

    @staticmethod
    def fill_row(row, index):
        row_requests = []
        for cell in row:
            if not str(cell).strip():
                cell = '0'
            row_requests.append({
                "insertText":
                    {
                        "text": str(cell).strip(),
                        "location":
                            {
                                "index": index
                            }
                    }
            })
            index += len(str(cell).strip()) + 2
        index += 1
        return row_requests, index

    def add_table(self, data, index):
        if not data:
            return index
        start_ind = index
        table_requests = [{'insertTable': {
            'rows': len(data) + 1,
            'columns': len(data[0]),
            'endOfSegmentLocation': {
                'segmentId': ''
            }
        }}]
        index += 4
        column_req, index = self.fill_row(data[0].keys(), index)
        table_requests.append(column_req)
        for row in data:
            row_request, index = self.fill_row(row.values(), index)
            table_requests += row_request
        table_requests.append(self.get_format_req(start_ind, index - 1,
                                                  self.text_format))
        return table_requests, index - 1

    def add_text(self, doc_id, text_json=None, index=1, newline=True):
        logging.info('Adding text to doc.')
        url = self.docs_url + "/" + doc_id + ":batchUpdate"
        headers = {"Content-Type": "application/json"}
        request = []
        format_request = []
        for item in text_json:
            if item['selected'] == 'false':
                continue
            if 'message' not in item:
                continue
            text = item['message']
            if newline:
                text += '\n'
            request.append({
                'insertText': {
                    'location': {
                        'index': index,
                    },
                    'text': text
                }
            })
            style = item['format'] if 'format' in item else self.text_format
            end_ind = index + len(text) - 1
            format_request.append(self.get_format_req(index, end_ind, style))
            index += len(text)
            if 'data' in item:
                table_req, index = self.add_table(item['data']['data'],
                                                  index=index)
                request += table_req
        request += format_request
        body = {"requests": request}
        response = self.client.post(url=url, json=body, headers=headers)
        return response, body


import json
import logging
import math
import os
import signal
import sys
from datetime import datetime, timedelta
from threading import Event

import pyowm
import pytz
from pyowm.weatherapi25.forecaster import Forecaster
from pyowm.weatherapi25.observation import Observation

from ecobee_data import EcobeeData
from utils import wait, string_to_bool

log_handler = logging.StreamHandler(sys.stderr)
log_handler.flush = sys.stderr.flush

logging.basicConfig(format='%(asctime)s,%(msecs)d %(levelname)-8s [%(filename)s:%(lineno)d] %(message)s',
                    datefmt='%d-%m-%Y:%H:%M:%S',
                    level=logging.DEBUG, handlers=[log_handler])
logger = logging.getLogger(__name__)
logging.getLogger('requests').setLevel(logging.CRITICAL)
logging.getLogger('urllib3').setLevel(logging.CRITICAL)
logging.getLogger('pyecobee').setLevel(logging.CRITICAL)
logging.getLogger('ecobee_data').setLevel(logging.DEBUG)

TEMP_DELTA = 20
R_VALUE = 2.5
OUTER_FILM_R = 0.05
INNER_FILM_R = 0.8
polling_interval = 30

ecobee: EcobeeData = None
ecobee_api_key: str = None
owm_api_key: str = None

shelf_name = 'pyecobee.shelf'
thermostat_name = 'Home'

exit_signal = Event()

def signal_handler(sig, frame):
    global ecobee
    logging.warning("Got signal %s, exiting", signal.Signals(sig).name)

    if ecobee is None and ecobee_api_key is not None:
        ecobee = EcobeeData(shelf_name, thermostat_name, ecobee_api_key, exit_signal)
        ecobee.get_token(True)
    logging.warning("Persisting to shelf")
    ecobee.graceful_shutdown()
    logging.warning("Exiting...")
    exit()

signal.signal(signal.SIGINT, signal_handler)
signal.signal(signal.SIGTERM, signal_handler)

def calc_relative_humidity(temp, dewpoint):
    temp = (temp - 32) * 5 / 9
    dewpoint = (dewpoint - 32) * 5 / 9
    rh = 100 * (math.exp((17.625 * dewpoint) / (243.04 + dewpoint)) / math.exp((17.625 * temp) / (243.04 + temp)))
    return rh

def desired_humid_perc(inside_temp, outside_temp, r_value: float = 2.5,
                       # diff: float = 20
                       ):
    des_dewpoint = (inside_temp - outside_temp) / (OUTER_FILM_R + INNER_FILM_R + r_value) * (
                r_value + OUTER_FILM_R) + outside_temp
    # des_dewpoint = outside_temp + diff
    return calc_relative_humidity(inside_temp, des_dewpoint)

def adjust_fan_min(ecobee):
    occupied = ecobee.occupied()
    current_fan = ecobee.get_fan_min_on_time()
    occupied_fan = int(os.environ.get('FAN_OCCUPIED_TIME', 20))
    away_fan = int(os.environ.get('FAN_AWAY_TIME', 5))
    if occupied:
        if current_fan != occupied_fan:
            logger.info("Changing fan to occupied: %d", occupied_fan)
            ecobee.set_fan_min_on_time(occupied_fan)
        else:
            logger.info("no need to change fan min runtime")
    else:
        if current_fan != away_fan:
            logger.info("Changing fan to away: %d", away_fan)
            ecobee.set_fan_min_on_time(away_fan)
        else:
            logger.info("no need to change fan min runtime")

def switch_backlight():
    if string_to_bool(os.environ.get('SWITCH_BACKLIGHT', 'true')):
        # if str(os.environ.get('SWITCH_BACKLIGHT', 1)).lower() not in ['0', 'false', 'f']:
        if ecobee.occupied():
            ecobee.turn_backlight_on()
        else:
            ecobee.turn_backlight_off()

def switch_humidifier():
    cur_humid = ecobee.get_cur_inside_humidity()
    cur_humid_mode = ecobee.get_humidity_mode()
    cur_hvac_mode = ecobee.get_cur_hvac_mode()
    if 'auxHeat' in cur_hvac_mode:
        if cur_humid_mode != 'manual':
            logger.debug('heat on, setting humidifier to manual')
            ecobee.set_humidity_mode('manual')
        else:
            logger.debug('heat on, already set to manual, doing nothing')
        return

    if cur_humid_mode == 'manual' and \
            cur_humid >= max_steam_humidity + steam_humidity_hysteresis:
        logger.debug('heat not on and humidity (%0.0f%%) above (%0.0f%%), turning off humidifier', cur_humid,
                     max_steam_humidity + steam_humidity_hysteresis)
        ecobee.set_humidity_mode('off')
    elif cur_humid_mode != 'manual' and \
            cur_humid <= max_steam_humidity:
        logger.debug('heat not on and humidity (%0.0f%%) below (%0.0f%%), turning on humidifier', cur_humid,
                     max_steam_humidity)
        ecobee.set_humidity_mode('manual')
    else:
        logger.debug('heat not on and humidifier mode is "%s" with humidity of %0.0f%%, not changing anything',
                     cur_humid_mode, cur_humid)

    # if 'auxHeat' not in ecobee.get_cur_hvac_mode() and \
    #         'manual' == ecobee.get_humidity_mode() and \
    #         cur_humid > max_steam_humidity:
    #     logger.debug('heat not on and humidity (%0.0f%%) above (%0.0f%%), turning off humidifier', cur_humid,
    #                  max_steam_humidity)
    #     ecobee.set_humidity_mode('off')
    # else:
    #     logger.debug('setting humidifier to manual')
    #     ecobee.set_humidity_mode('manual')

def get_fan_runtime():
    temps = ecobee.sensor_temps
    sensor_delta = max(temps.values()) - min(temps.values())
    # sensor_delta = 4

    fan_max = json.loads(os.environ.get('FAN_MAX', '[8,60]'))
    fan_min = json.loads(os.environ.get('FAN_MIN', '[1,5]'))
    if sensor_delta > fan_max[0]:
        runtime = fan_max[1]
    elif sensor_delta < fan_min[0]:
        runtime = fan_min[1]
    else:
        runtime = fan_factors[0] * pow(sensor_delta, 5) + \
                  fan_factors[1] * pow(sensor_delta, 4) + \
                  fan_factors[2] * pow(sensor_delta, 3) + \
                  fan_factors[3] * pow(sensor_delta, 2) + \
                  fan_factors[4] * sensor_delta + \
                  fan_factors[5]
    rt_rounded = min(max(int(5 * round(runtime / 5)), fan_min[1]), fan_max[1])
    logger.debug("Fan runtime setting %d (%0.3f) for ΔT=%0.1f", rt_rounded, runtime, sensor_delta)
    return rt_rounded

def run():
    global ecobee
    ecobee = EcobeeData(shelf_name, thermostat_name, ecobee_api_key, exit_signal)
    ecobee.get_token()
    # ecobee.get_humidity_mode()
    # return
    ecobee.store_backlight_settings()
    fan_mode = os.environ.get('FAN_MODE', 'DELTA').lower()
    if fan_mode[:3] == 'del':
        fantime = get_fan_runtime()
        logger.info('Setting min fan runtime to %d', fantime)
        ecobee.set_fan_min_on_time(fantime)
    elif fan_mode[:3] == 'occ':
        adjust_fan_min(ecobee)
    switch_backlight()

    in_temp, des_in_temp = ecobee.get_cur_inside_temp()
    outside_temp, future_out_temp = get_owm_outside_temps()
    future_des_temp = ecobee.get_future_set_temp()
    cur_out_cur_in_rh = desired_humid_perc(in_temp, outside_temp, r_value)
    logger.info("RH Based on current inside (%0.1f F) and outside (%0.1f F) temp: %0.1f%%",
                in_temp, outside_temp,
                cur_out_cur_in_rh)
    future_out_future_in_rh = desired_humid_perc(future_des_temp, future_out_temp, r_value)
    logger.info("RH Based on desired inside (%0.1f F) and future outside (%0.1f F) temp: %0.1f%%",
                future_des_temp, future_out_temp, future_out_future_in_rh)

    rh_set = max(min(max_humidity,
                     cur_out_cur_in_rh,
                     future_out_future_in_rh,
                     ), min_humidity)
    logger.info("RH unrounded: %0.1f%%", rh_set)

    rh_set = round(rh_set / 2) * 2
    logger.info("actual humidity setting %0.1f%%", rh_set)
    ecobee.set_humidity(round(rh_set))
    switch_humidifier()
    ecobee = None

def get_owm_outside_temps():
    cur_weather: Observation
    cur_forecast: Forecaster
    owm = pyowm.OWM(owm_api_key).weather_manager()
    location_lat = os.environ.get('OWM_LATITUDE', None)
    location_lon = os.environ.get('OWM_LONGITUDE', None)
    location_id = os.environ.get('OWM_ID', None)
    location_name = os.environ.get('OWM_LOCATION', None)
    if location_lon and location_lat:
        location_lon = float(location_lon)
        location_lat = float(location_lat)
        cur_weather = owm.weather_at_coords(location_lat, location_lon)
        cur_forecast = owm.forecast_at_coords(location_lat, location_lon, interval='3h')
    elif location_id:
        location_id = int(location_id)
        cur_weather = owm.weather_at_id(location_id)
        cur_forecast = owm.forecast_at_id(location_id, interval='3h')
    elif location_name:
        cur_weather = owm.weather_at_place(location_name)
        cur_forecast = owm.forecast_at_place(location_name, interval='3h')
    else:
        raise ValueError('One OWM location type needs to be specified (lat-lon,id,or string)')
    cur_outside_temp = cur_weather.weather.temperature(unit='fahrenheit')
    future_time = datetime.now(pytz.utc) + timedelta(hours=1)
    mintime = 60 * 60 * 2  # 2 hours
    future_outside_temp = None
    for f in cur_forecast.forecast:
        timediff = abs((f.reference_time('date') - future_time).total_seconds())

        if timediff < mintime:
            mintime = timediff
            future_outside_temp = f.temperature(unit='fahrenheit')
            logger.debug("OWM: %s, %0.1f -> %0.1f", f.reference_time('date'), mintime, future_outside_temp['temp'])
    return cur_outside_temp['temp'], future_outside_temp['temp']

if __name__ == '__main__':
    thermostat_name = 'My Thermostat'
    ecobee_api_key = os.environ['ECOBEE_API_KEY']
    owm_api_key = os.environ['OWM_API_KEY']
    temp_delta = float(os.environ.get('DEWPOINT_DELTA', TEMP_DELTA))
    r_value = float(os.environ.get('R_VALUE', R_VALUE))
    update_interval = int(os.environ.get('UPDATE_INTERVAL', 600))
    max_steam_humidity = float(os.environ.get('MAX_STEAM_HUMIDITY', 40))
    steam_humidity_hysteresis = float(os.environ.get('STEAM_HUMIDITY_HYST', 2))

    max_humidity = float(os.environ.get('MAX_HUMIDITY', 50))
    min_humidity = float(os.environ.get('MIN_HUMIDITY', 10))
    loglevel = os.environ.get('LOG_LEVEL', "INFO")
    numeric_level = getattr(logging, loglevel.upper(), 20)
    logger.setLevel(numeric_level)
    logger.warning("Logging set to %s", logging.getLevelName(numeric_level))
    fan_factors = json.loads(os.environ.get(
        'FAN_FACTORS',
        '[0.43651,-5.99206,29.9206,-19.3651]'
    ))

    fan_factors = [0] * (6 - len(fan_factors)) + fan_factors
    logger.debug("Fan factors are %s", fan_factors)

    while not exit_signal.is_set():
        run()
        log_handler.flush()
        # break
        show_interval = max(10, update_interval / 10.0)
        wait(update_interval, exit_signal, interval=show_interval,
             extra_message='/{} seconds waiting ...'.format(update_interval),
             log_signal=string_to_bool(os.environ.get('SHOW_WAIT_COUNTDOWN', 'true')))


from datetime import datetime, timedelta
import os
from airflow import DAG
from airflow.operators.dummy_operator import DummyOperator
from airflow.operators import (StageToRedshiftOperator, LoadFactOperator,
                               LoadDimensionOperator, DataQualityOperator)
from helpers import SqlQueries

default_args = {
    'owner': 'guido',
    'start_date': datetime(2019, 1, 12),
    'retries': 3,
    'retry_delay': timedelta(minutes=5),
    'email_on_retry': False,
    'depends_on_past': False
}

dag = DAG('udac_example_dag',
          default_args=default_args,
          description='Load and transform data in Redshift with Airflow',
          schedule_interval='0 * * * *',
          catchup=False
          )

# Mark start of pipeline
start_operator = DummyOperator(task_id='Begin_execution',  dag=dag)

# Populate events table with origin data from S3
stage_events_to_redshift = StageToRedshiftOperator(
    task_id="load_events_from_s3_to_redshift",
    aws_credentials_id="aws_credentials",
    dag=dag,
    redshift_conn_id="redshift",
    s3_bucket="udacity-dend",
    s3_key="log_data",
    table="staging_events",
    json_path='s3://udacity-dend/log_json_path.json'
)

# Populate songs table with origin data from S3
stage_songs_to_redshift = StageToRedshiftOperator(
    task_id="load_songs_from_s3_to_redshift",
    aws_credentials_id="aws_credentials",
    dag=dag,
    redshift_conn_id="redshift",
    s3_bucket="udacity-dend",
    s3_key="song_data",
    ignore_headers="0",
    table="staging_songs",
)

# Extract data for songplays table and insert
load_songplays_table = LoadFactOperator(
    task_id='Load_songplays_fact_table',
    dag=dag,
    redshift_conn_id="redshift",
    sql_query=SqlQueries.songplay_table_insert,
    table='songplays',
)

# Extract data for users table and insert
load_user_dimension_table = LoadDimensionOperator(
    task_id='Load_user_dim_table',
    dag=dag,
    redshift_conn_id="redshift",
    sql_query=SqlQueries.user_table_insert,
    table='users',
)

# Extract data for songs table and insert
load_song_dimension_table = LoadDimensionOperator(
    task_id='Load_song_dim_table',
    dag=dag,
    redshift_conn_id="redshift",
    sql_query=SqlQueries.song_table_insert,
    table='songs',
)

# Extract data for artists table and insert
load_artist_dimension_table = LoadDimensionOperator(
    task_id='Load_artist_dim_table',
    dag=dag,
    redshift_conn_id="redshift",
    sql_query=SqlQueries.artist_table_insert,
    table='artists',
)

# Extract data for time table and insert
load_time_dimension_table = LoadDimensionOperator(
    task_id='Load_time_dim_table',
    dag=dag,
    redshift_conn_id="redshift",
    sql_query=SqlQueries.time_table_insert,
    table='time',
)

# Make sure tables contain at least one record
run_quality_checks = DataQualityOperator(
    task_id='Run_data_quality_checks',
    dag=dag,
    redshift_conn_id="redshift",
    tables=['artists', 'songplays', 'songs', 'time', 'users'],
)

# Mark end of pipeline
end_operator = DummyOperator(task_id='Stop_execution',  dag=dag)

# Dag orchestrator
start_operator >> stage_events_to_redshift
start_operator >> stage_songs_to_redshift

stage_events_to_redshift >> load_songplays_table
stage_songs_to_redshift >> load_songplays_table

load_songplays_table >> load_song_dimension_table
load_songplays_table >> load_user_dimension_table
load_songplays_table >> load_artist_dimension_table
load_songplays_table >> load_time_dimension_table

load_user_dimension_table >> run_quality_checks
load_song_dimension_table >> run_quality_checks
load_artist_dimension_table >> run_quality_checks
load_time_dimension_table >> run_quality_checks

run_quality_checks >> end_operator