import torch
import torch.nn as nn
import torch.nn.functional as F
import torchvision.models as models

# from captioning_config import Config as Config
from captioning.captioning_config import Config

config = Config()

class DecoderRNN(nn.Module):
    def __init__(self, embed_size, hidden_size, vocab_size, num_layers=1):
        super().__init__()
        self.embedding = nn.Embedding(vocab_size, embed_size)

        self.project_feature_layer = nn.Linear(embed_size, hidden_size)

        self.lstm = nn.LSTM(
            input_size=embed_size,
            hidden_size=hidden_size,
            num_layers=num_layers,
            batch_first=True,
        )

        self.linear = nn.Linear(hidden_size, vocab_size)
        self.softmax = nn.Softmax(dim=1)

    def forward(self, features, captions):
        captions = captions[:, :-1]
        # print(captions.shape)
        embed = self.embedding(captions)
        # print(embed.shape)
        embed = torch.cat((features.unsqueeze(1), embed), dim=1)
        # print(embed.shape)
        lstm_outputs, _ = self.lstm(embed)
        # print(lstm_outputs.shape)
        out = self.linear(lstm_outputs)
        # print(out.shape)
        return out

    def init_search(self, inputs, states=None, max_len=20):
        """ accepts pre-processed image tensor (inputs) and
        returns predicted sentence (list of tensor ids of length max_len) """
        # input 1,300
        states = (None, 0)
        inputs = inputs.unsqueeze(1)
        return (inputs, states)

    def predict_next(self, encoder_out, current_word, state):
        lstm_states, iteration = state
        if iteration == 0:
            lstm_outputs, lstm_states = self.lstm(encoder_out, lstm_states)
        else:
            current_word = self.embedding(current_word).unsqueeze(0)

            lstm_outputs, lstm_states = self.lstm(current_word, lstm_states)

        lstm_outputs = lstm_outputs.squeeze(1)  # 1,512
        out = self.linear(lstm_outputs)  # 1,3004

        return out, (lstm_states, iteration + 1)


import os
import responder
from logging import getLogger, Formatter, StreamHandler, INFO
from logging.handlers import TimedRotatingFileHandler

cors = {
    'allow_origins': ['*']
}
api = responder.API(
    openapi='3.0.0',
    title="Image Inference API",
    docs_route='/docs',
    version='0.0.1',
    cors=True,
    cors_params=cors
)

logger = getLogger(__name__)
logger.setLevel(INFO)
formatter = Formatter('%(asctime)s [%(levelname)s] :%(message)s')
if os.environ.get('GITHUB_ACTIONS') is None:  # for Github Actions
    filename = os.environ.get('LOG_PATH', 'logs/access.log')
    file_handler = TimedRotatingFileHandler(
        filename=filename,
        when='midnight',
        backupCount=7,
        encoding='utf-8'
    )
    file_handler.setLevel(INFO)
    file_handler.setFormatter(formatter)
    logger.addHandler(file_handler)

stream_handler = StreamHandler()
stream_handler.setLevel(INFO)
stream_handler.setFormatter(formatter)
logger.addHandler(stream_handler)
logger.propagate = False


# -*- coding: utf-8 -*-
# -*- Channel Repelis.live -*-
# -*- Created for Alfa-addon -*-
# -*- By the Alfa Develop Group -*-

import re
import urllib
import urlparse

from channelselector import get_thumb
from core import httptools
from core import jsontools
from core import scrapertools
from core import servertools
from core.item import Item
from platformcode import config, logger
from core import tmdb
from channels import filtertools
from channels import autoplay

IDIOMAS = {'Latino': 'LAT', 'Castellano':'CAST', 'Subtitulado': 'VOSE'}
list_language = IDIOMAS.values()
list_quality = []
list_servers = ['openload', 'streamango', 'rapidvideo', 'netutv']

host = "http://repelis.live/"

def mainlist(item):
    logger.info()

    autoplay.init(item.channel, list_servers, list_quality)
    itemlist = list()

    itemlist.append(
        Item(channel=item.channel,
             title="Ultimas",
             action="list_all",
             url=host,
             thumbnail=get_thumb("last", auto=True)))

    itemlist.append(
        Item(channel=item.channel,
             title="Castellano",
             action="list_all",
             url=host+'pelis-castellano/',
             thumbnail=get_thumb("cast", auto=True)))

    itemlist.append(
        Item(channel=item.channel,
             title="Latino",
             action="list_all",
             url=host+'pelis-latino/',
             thumbnail=get_thumb("lat", auto=True)))

    itemlist.append(
        Item(channel=item.channel,
             title="VOSE",
             action="list_all",
             url=host+'pelis-subtitulado/',
             thumbnail=get_thumb("vose", auto=True)))

    itemlist.append(
        Item(channel=item.channel,
             title="Generos",
             action="categories",
             url=host,
             thumbnail=get_thumb('genres', auto=True)
             ))

    itemlist.append(
        Item(channel=item.channel,
             title="Por Año",
             action="categories",
             url=host,
             thumbnail=get_thumb('year', auto=True)
             ))

    itemlist.append(
        Item(channel=item.channel,
             title="Buscar",
             action="search",
             url=host + '?s=',
             thumbnail=get_thumb("search", auto=True)
             ))

    autoplay.show_option(item.channel, itemlist)

    return itemlist

def get_source(url):
    logger.info()
    data = httptools.downloadpage(url).data
    data = re.sub(r'\n|\r|\t| |
|\s{2,}', "", data)
    return data

def categories(item):
    logger.info()
    itemlist = []

    data = get_source(item.url)
    if item.title != 'Generos':
        patron = '<option value="([^"]+)">([^<]+)</option>'
    else:
        data = scrapertools.find_single_match(data, 'Categories

(.*?)
')
        patron = '([^<]+)'

    matches = re.compile(patron, re.DOTALL).findall(data)

    for url, title in matches:
        itemlist.append(Item(channel=item.channel,
                             action="list_all",
                             title=title,
                             url=url
                             ))
    return itemlist

def list_all(item):
    logger.info()
    itemlist = []

    data = get_source(item.url)

    if item.title == 'Buscar':
        pattern = '
 .*?<img src="([^"]+)".*?'
        pattern += '
Pelicula del (\d{4})'
    else:
        pattern = '
.?
 .*?"anio".*?>(\d{4}).*?src="([^"]+)"'

    matches = scrapertools.find_multiple_matches(data, pattern)

    for url, title, year, thumb in matches:

        new_item = Item(channel=item.channel,
                        title=title,
                        url=url,
                        action='findvideos',
                        contentTitle=title,
                        thumbnail=thumb,
                        infoLabels = {'year': year}
                        )

        itemlist.append(new_item)

    tmdb.set_infoLabels(itemlist, seekTmdb=True)

    next_page = scrapertools.find_single_match(data, '<link rel="next" href="([^"]+)"')
    if next_page != '':
        itemlist.append(Item(channel=item.channel,
                             action="list_all",
                             title=">> Página siguiente",
                             url=next_page,
                             ))
    return itemlist

def findvideos(item):
    logger.info()
    itemlist = []
    trailer = ''
    data = get_source(item.url)
    patron = '([^<]+)<'

    matches = re.compile(patron, re.DOTALL).findall(data)

    for url, language in matches:
        url = url.replace('&','&')
        data = httptools.downloadpage(url, follow_redirects=False, headers={'Referer':item.url}, only_headers=True)
        url = data.headers['location']

        if config.get_setting('unify'):
            title = ''
        else:
            title = ' [%s]' % language

        if 'youtube' in url:
            trailer = Item(channel=item.channel, title='Trailer', url=url, action='play', server='youtube')
        else:
            itemlist.append(Item(channel=item.channel,
                                 title='%s'+title,
                                 url=url,
                                 action='play',
                                 language=IDIOMAS[language],
                                 infoLabels=item.infoLabels))

    itemlist = servertools.get_servers_itemlist(itemlist, lambda i: i.title % i.server.capitalize())

    if trailer != '':
        itemlist.append(trailer)

    # Requerido para FilterTools

    itemlist = filtertools.get_links(itemlist, item, list_language)

    # Requerido para AutoPlay

    autoplay.start(itemlist, item)

    if config.get_videolibrary_support() and len(itemlist) > 0 and item.extra != 'findvideos':
        itemlist.append(Item(channel=item.channel, title='[COLOR yellow]Añadir esta pelicula a la videoteca[/COLOR]',
                             url=item.url, action="add_pelicula_to_library", extra="findvideos",
                             contentTitle=item.contentTitle
                             ))

    return itemlist

def search(item, texto):
    logger.info()
    texto = texto.replace(" ", "+")
    try:
        if texto != '':
            item.url += texto
            return list_all(item)
        else:
            return []
    except:
        import sys
        for line in sys.exc_info():
            logger.error("%s" % line)
        return []

def newest(category):
    logger.info()
    item = Item()
    try:
        if category == 'peliculas':
            item.url = host
        elif category == 'infantiles':
            item.url = host + 'category/animacion'
        elif category == 'terror':
            item.url = host + 'category/terror'
        itemlist = list_all(item)

        if itemlist[-1].title == '>> Página siguiente':
            itemlist.pop()
    except:
        import sys
        for line in sys.exc_info():
            logger.error("%s" % line)
        return []

    return itemlist


#!/usr/bin/python
import socketserver
import json
from typing import List

clients = []

ROWS, COLS = 24, 79

def replace_substring_at_index(s: str, new_substring: str, index: int) -> str:
    return s[:index] + new_substring + s[index + len(new_substring):]

def initial_canvas() -> List[str]:
    canvas: List[str] = [f" __MINITALK{'_'*(COLS-12)} "]
    canvas.append(f"/{' '*(COLS-2)}\\")
    for _ in range(ROWS-3):
        canvas.append(f"|{' '*(COLS-2)}|")
    canvas.append(f"\\{'_'*(COLS-2)}/")
    return canvas

class TextEditorServer(socketserver.BaseRequestHandler):
    canvas: List[str] = initial_canvas()

    def handle(self):
        print(f"Client {self.client_address} connected.")

        # Add client to the list
        clients.append(self.request)

        # First connection: send the whole canvas
        first_message = {
            "type": "sync",
            "canvas": TextEditorServer.canvas
        }

        self.request.sendall(json.dumps(first_message).encode())

        try:
            while True:
                # Wait for any client to send us data
                data = self.request.recv(1024).decode()
                if not data:
                    print(f"Client {self.client_address} disconnected.")
                    break

                print(f"Received data:", data)

                # We expect from a client:
                # { "type": "update", "text": "...", "row": ..., "col": ..., "client_id": "...", "username": "..." }

                # Sometimes multiple messages are sent together
                # which means we receive invalid json: {...}{...}
                split_data = data.replace("}{", "}|{").split('|')

                for d in split_data:
                    update = json.loads(d)

                    if update["text"] == "\u000b":
                        print("received C-k so clearing the canvas")
                        TextEditorServer.canvas = initial_canvas()
                        update = {
                            "type": "sync",
                            "canvas": TextEditorServer.canvas
                        }
                        data = json.dumps(update)
                    else:
                        TextEditorServer.canvas[update["row"]] = \
                            replace_substring_at_index(
                                TextEditorServer.canvas[update["row"]],
                                update["text"],
                                update["col"]
                            )

                    # Broadcast received data to other clients
                    print(f"broadcasting {update['type']}")
                    data = json.dumps(update)
                    for client in clients:
                        if update["type"] == "sync" or client != self.request:
                            client.sendall(data.encode())
                            print(f"Sent data to client")
        finally:
            clients.remove(self.request)
            print(f"Client {self.client_address} removed from active clients.")

if __name__ == "__main__":
    HOST, PORT = "0.0.0.0", 9999
    print(f"Starting server on {HOST}:{PORT}.")
    server = socketserver.ThreadingTCPServer((HOST, PORT), TextEditorServer)
    server.serve_forever()


"""
Test cases for the image depth conversion function.

The function works can perform all the possible conversion.
The function also acts as a copy function when the two given images (input
and output) have the same depth.

Here is the list of legal operations:
     8 -> 1
     1 -> 8
    32 -> 1
     1 -> 32
    32 -> 8 (downscaling)
     8 -> 32
     and copy :
     1 -> 1
     8 -> 8
    32 ->32

When converting from 8-bit/32-bit to binary, only the pixels that have a value
of 255/0xffffffff are set to true(1) in the binary image.
All the others are set to False(0). In the other way, binary to 8-bit/32-bit,
the True pixels are set to 255/0xffffffff and 0 for the False ones.
The 32bit to 8bit conversion is a downscaling and the 8-bit to 32-bit is
equivalent to copyBytePlane for plane 0.

Python function:
    convert
    imageMb.convert

C function:
    MB_Convert
"""

from mamba import *
import unittest
import random

class TestConvert(unittest.TestCase):

    def setUp(self):
        # Creating two images for each possible depth
        self.im1_1 = imageMb(1)
        self.im1_2 = imageMb(1)
        self.im1_3 = imageMb(1)
        self.im8_1 = imageMb(8)
        self.im8_2 = imageMb(8)
        self.im8_3 = imageMb(8)
        self.im32_1 = imageMb(32)
        self.im32_2 = imageMb(32)
        self.im32_3 = imageMb(32)
        self.im8s2_1 = imageMb(128,128,8)
        self.im1s2_1 = imageMb(128,128,1)

    def tearDown(self):
        del(self.im1_1)
        del(self.im1_2)
        del(self.im1_3)
        del(self.im8_1)
        del(self.im8_2)
        del(self.im8_3)
        del(self.im32_1)
        del(self.im32_2)
        del(self.im32_3)
        del(self.im8s2_1)
        del(self.im1s2_1)

    def testSizeCheck(self):
        """Tests that different sizes raise an exception"""
        self.assertRaises(MambaError, convert, self.im8s2_1, self.im1_1)
        self.assertRaises(MambaError, convert, self.im8_1, self.im1s2_1)

    def testConversion_1_8(self):
        """Verifies that converting a binary image into an 8-bit image works fine"""
        (w,h) = self.im1_1.getSize()

        self.im1_1.fill(1)
        self.im8_2.fill(255)
        convert(self.im1_1, self.im8_1)
        (x,y) = compare(self.im8_2, self.im8_1, self.im8_3)
        self.assertLess(x, 0)

        self.im1_1.reset()
        self.im8_2.fill(0)
        convert(self.im1_1, self.im8_1)
        (x,y) = compare(self.im8_2, self.im8_1, self.im8_3)
        self.assertLess(x, 0)

        self.im1_1.reset()
        self.im8_2.reset()
        for wi in range(w):
            for hi in range(h):
                if wi%2==0:
                    self.im1_1.setPixel(1, (wi,hi))
                    self.im8_2.setPixel(255, (wi,hi))
                else:
                    self.im1_1.setPixel(0, (wi,hi))
                    self.im8_2.setPixel(0, (wi,hi))
        convert(self.im1_1, self.im8_1)
        (x,y) = compare(self.im8_2, self.im8_1, self.im8_3)
        self.assertLess(x, 0)
        self.im1_1.convert(8)
        (x,y) = compare(self.im8_2, self.im1_1, self.im8_3)
        self.assertLess(x, 0)
        self.im1_1.convert(1)

    def testConversion_8_1(self):
        """Verifies that converting an 8-bit image into a binary image works fine"""

        for i in range(256):
            self.im8_1.fill(i)
            if i==255:
                self.im1_2.fill(1)
            else:
                self.im1_2.reset()
            convert(self.im8_1, self.im1_1)
            (x,y) = compare(self.im1_1, self.im1_2, self.im1_3)
            self.assertLess(x, 0)
            self.im8_1.convert(1)
            (x,y) = compare(self.im8_1, self.im1_2, self.im1_3)
            self.assertLess(x, 0)
            self.im8_1.convert(8)

        (w,h) = self.im8_1.getSize()
        self.im8_1.reset()
        drawSquare(self.im8_1, (w//2-w//4, h//2-h//4, w//2+w//4, h//2+h//4), 255)
        self.im1_2.reset()
        drawSquare(self.im1_2, (w//2-w//4, h//2-h//4, w//2+w//4, h//2+h//4), 1)

        convert(self.im8_1, self.im1_1)
        (x,y) = compare(self.im1_1, self.im1_2, self.im1_3)
        self.assertLess(x, 0)

    def testConversion_1_32(self):
        """Verifies that converting a binary image into an 32-bit image works fine"""
        (w,h) = self.im1_1.getSize()

        self.im1_1.fill(1)
        self.im32_2.fill(0xffffffff)
        convert(self.im1_1, self.im32_1)
        (x,y) = compare(self.im32_2, self.im32_1, self.im32_3)
        self.assertLess(x, 0)

        self.im1_1.reset()
        self.im32_2.fill(0)
        convert(self.im1_1, self.im32_1)
        (x,y) = compare(self.im32_2, self.im32_1, self.im32_3)
        self.assertLess(x, 0)

        self.im1_1.reset()
        self.im32_2.reset()
        for wi in range(w):
            for hi in range(h):
                if wi%2==0:
                    self.im1_1.setPixel(1, (wi,hi))
                    self.im32_2.setPixel(0xffffffff, (wi,hi))
                else:
                    self.im1_1.setPixel(0, (wi,hi))
                    self.im32_2.setPixel(0, (wi,hi))
        convert(self.im1_1, self.im32_1)
        (x,y) = compare(self.im32_2, self.im32_1, self.im32_3)
        self.assertLess(x, 0)
        self.im1_1.convert(32)
        (x,y) = compare(self.im32_2, self.im1_1, self.im32_3)
        self.assertLess(x, 0)
        self.im1_1.convert(1)

    def testConversion_32_1(self):
        """Verifies that converting an 32-bit image into a binary image works fine"""

        for i in [0, 0x1000, 0x80000000, 0xfffffffe, 0xffffffff]:
            self.im32_1.fill(i)

            if i==0xffffffff:
                self.im1_2.fill(1)
            else:
                self.im1_2.reset()
            convert(self.im32_1, self.im1_1)
            (x,y) = compare(self.im1_1, self.im1_2, self.im1_3)
            self.assertLess(x, 0)
            self.im32_1.convert(1)
            (x,y) = compare(self.im32_1, self.im1_2, self.im1_3)
            self.assertLess(x, 0)
            self.im32_1.convert(32)

        (w,h) = self.im32_1.getSize()
        self.im32_1.reset()
        drawSquare(self.im32_1, (w//2-w//4, h//2-h//4, w//2+w//4, h//2+h//4), 0xffffffff)
        self.im1_2.reset()
        drawSquare(self.im1_2, (w//2-w//4, h//2-h//4, w//2+w//4, h//2+h//4), 1)

        convert(self.im32_1, self.im1_1)
        (x,y) = compare(self.im1_1, self.im1_2, self.im1_3)
        self.assertLess(x, 0)

    def testConversion_32_8(self):
        """Verifies that converting an 32-bit image into a greyscale image works fine"""
        (w,h) = self.im32_1.getSize()
        self.im32_1.reset()
        drawSquare(self.im32_1, (w//3,0,(2*w)//3-1,h-1), 0x80000000)
        drawSquare(self.im32_1, ((w*2)//3,0,w-1,h-1), 0xffffffff)
        self.im8_2.reset()
        drawSquare(self.im8_2, (w//3,0,(2*w)//3-1,h-1), 127)
        drawSquare(self.im8_2, ((w*2)//3,0,w-1,h-1), 255)
        convert(self.im32_1, self.im8_1)
        (x,y) = compare(self.im8_1, self.im8_2, self.im8_3)
        self.assertLess(x, 0)

    def testConversion_8_32(self):
        """Verifies that converting an 8-bit image into a 32-bit image works fine"""
        (w,h) = self.im8_1.getSize()
        self.im32_2.reset()
        drawSquare(self.im32_2, (w//3,0,(2*w)//3-1,h-1), 127)
        drawSquare(self.im32_2, ((w*2)//3,0,w-1,h-1), 255)
        self.im8_1.reset()
        drawSquare(self.im8_1, (w//3,0,(2*w)//3-1,h-1), 127)
        drawSquare(self.im8_1, ((w*2)//3,0,w-1,h-1), 255)
        convert(self.im8_1, self.im32_1)
        (x,y) = compare(self.im32_1, self.im32_2, self.im32_3)
        self.assertLess(x, 0)

    def testComputation_1_1(self):
        """Verifies that converting a binary image into a binary image amounts to copy it"""
        self.im1_1.fill(1)
        convert(self.im1_1, self.im1_2)
        (x,y) = compare(self.im1_2, self.im1_1, self.im1_3)
        self.assertLess(x, 0)
        self.im1_1.reset()
        convert(self.im1_1, self.im1_2)
        (x,y) = compare(self.im1_2, self.im1_1, self.im1_3)
        self.assertLess(x, 0)

    def testComputation_8_8(self):
        """Verifies that converting a 8-bit image into a 8-bit image amounts to copy it"""
        for i in range(100):
            vi = random.randint(0,255)
            self.im8_1.fill(vi)
            convert(self.im8_1, self.im8_2)
            (x,y) = compare(self.im8_2, self.im8_1, self.im8_3)
            self.assertLess(x, 0)

    def testComputation_32_32(self):
        """Verifies that converting a 32-bit image into a 32-bit image amounts to copy it"""
        for i in range(100):
            vi = random.randint(1,0xffffffff)
            self.im32_1.fill(vi)
            convert(self.im32_1, self.im32_2)
            (x,y) = compare(self.im32_2, self.im32_1, self.im32_3)
            self.assertLess(x, 0)


import threading
import time

def redirect_stdio():
    # disable stdout & stderr when frozen
    if getattr(sys, 'frozen', False):
        # running in a bundle (mean frozen)
        # if frozen, disable child process stdio, otherwise stdio buffer may exceed
        # maxBuffer of node.js execFile, and this child process would be killed.
        F_NULL = open(os.devnull, 'w')
        sys.stdout = F_NULL
        sys.stderr = F_NULL

def flush_stdio():
    while True:
        time.sleep(0.01)
        sys.stdout.flush()
        sys.stderr.flush()

t = threading.Thread(target=flush_stdio)
t.start()

if __name__ == '__main__':
    import sys
    import os
    redirect_stdio()

    import multiprocessing
    multiprocessing.freeze_support()

    from logger_config import configure_logger
    import environ

    configure_logger()

    try:
        import logging
        from server import start_rpc_server
        # run RPCServer
        port = int(os.environ['rpcServerPort'])
        start_rpc_server(port=port)

    except Exception as e:
        # If error in main loop, log to file and re-raise.
        logging.exception('RPC-Server runtime error')
        logging.critical('RPC-Server crashed')


#!/usr/bin/env python3

from RoboticsUtilities import trajectory
from RoboticsUtilities import Transformations
from InverseKinematics import leg_IK
from math import floor
import numpy as np

class gait_generator():

    def __init__(self, beta, t_cycle, robot_height, robot_dimensions, robot_leg):
        # constant
        self.beta = beta
        self.t_cycle = t_cycle
        self.leg_raise_time = 0.05
        self.robot_leg = robot_leg
        self.robot_height = robot_height
        self.robot_dimensions = robot_dimensions # [length, width]

        # define leg base frame
        l = self.robot_dimensions[0]/2
        b = self.robot_dimensions[1]/2
        self.l1_base = [l, b]
        self.l2_base = [l, -b]
        self.l3_base = [-l, -b]
        self.l4_base = [-l, b]

        # updates with velocity command
        self.v_body_g = None
        self.yaw_rate = None
        self.l_stride = None

        self.leg_pos = None
        self.robot_body_pos = None
        self.body_pos_init = False
        self.previous_timestamp = 0

    def run(self, sim_time, velocity_command, yaw_rate_command):
        # new v_body_g and l_stride from velocity command
        self.update_gait(velocity_command, yaw_rate_command)

        # get kinematic phase array to time leg movement
        self.get_kinematic_phase()
        self.kinematic_phase[3] = self.kinematic_phase[0]
        self.kinematic_phase[2] = self.kinematic_phase[1]

        # settling time stance
        if sim_time < 0:
            stance = [0.0, 0.0, self.robot_height]
            angles = []
            for i in range(0, 4):
                leg_angles = self.robot_leg.inverse_kinematics(stance, i)
                angles.append(leg_angles[0])
                angles.append(leg_angles[1])
                angles.append(leg_angles[2])

            return angles

        else:
            leg_pos = self.get_leg_pos(sim_time, yaw_rate_command)
            leg_pos = self.get_leg_rotation_offset(leg_pos, yaw_rate_command)
            print("rotated", leg_pos)
            angles = []
            for i in range(0, 4):
                leg_angles = self.robot_leg.inverse_kinematics(leg_pos[i], i)
                angles.append(leg_angles[0])
                angles.append(leg_angles[1])
                angles.append(leg_angles[2])

            return angles

    def update_gait(self, velocity_command, yaw_rate):
        self.v_body_g = velocity_command.transpose()[0]
        self.l_stride = self.v_body_g*self.t_cycle
        self.yaw_rate = yaw_rate
        print("v_body", self.v_body_g)
        print("t_cycle", self.t_cycle)
        print("l_stride", self.l_stride)

    def get_kinematic_phase(self):
        "creates kinematic phase array for leg 1 to leg 4"
        leg1_phase = 0
        leg2_phase = 0.5
        leg3_phase = leg1_phase + self.beta
        leg4_phase = leg2_phase + self.beta

        if leg3_phase >= 1:
            leg3_phase = leg3_phase - 1
        if leg4_phase >= 1:
            leg4_phase = leg4_phase - 1

        self.kinematic_phase = [leg1_phase, leg2_phase, leg3_phase, leg4_phase]

    def get_leg_rotation_offset(self, leg_pose, yaw_rate):
        new_leg_pose = []
        for i in range(0, 4):
            l = self.robot_dimensions[0] / 2
            b = self.robot_dimensions[1] / 2
            offset = [l, b, 0]
            rotated_pose = np.matmul(Transformations.rotz(yaw_rate*(-1**((i+1)%2))), np.add(leg_pose[i], offset))
            new_leg_pose.append(np.subtract(rotated_pose, offset))

        return new_leg_pose

    def get_leg_pos(self, sim_time, yaw_rate):
        "gives local position which is added in to default stance"
        leg_raise_height = 0.03
        leg_vz = 0.0

        cycle_number = floor(sim_time/self.t_cycle)
        print("cycle number", cycle_number)

        leg_pos = []
        i = 0

        for phase in self.kinematic_phase:
            x = 0
            y = 0
            z = 0

            start_phase = phase + self.beta
            end_phase = phase

            if start_phase >= 1:
                start_phase = start_phase - 1
            if end_phase == 0:
                end_phase = 1

            start_phase = start_phase + cycle_number
            end_phase = end_phase + cycle_number

            l_swing = self.l_stride*self.beta

            print("new lswing", l_swing)
            t0 = self.t_cycle*cycle_number
            t1 = self.t_cycle*start_phase
            t2 = self.t_cycle*start_phase + self.t_cycle*self.leg_raise_time
            t3 = self.t_cycle*end_phase - self.t_cycle*self.leg_raise_time
            t4 = self.t_cycle*end_phase

            print("gait trajectory")
            print(self.kinematic_phase)
            print(t1, t2, t3, t4)

            if sim_time < t1:
                print("phase T1")
                y = (-l_swing[1] / (self.t_cycle)) * (sim_time % self.t_cycle)
                x = (-l_swing[0] / (self.t_cycle)) * (sim_time % self.t_cycle)
                z = self.robot_height

            if sim_time >= t1 and sim_time < t2:
                print("phase T2")
                x = (-l_swing[0] / (self.t_cycle)) * (sim_time % self.t_cycle)
                y = (-l_swing[1] / (self.t_cycle)) * (sim_time % self.t_cycle)
                z_traj = trajectory.Trajectory(0, leg_raise_height, 0, leg_vz, t1, t2)
                z = self.robot_height - z_traj.at_time(sim_time)[0]

            if sim_time >= t2 and sim_time <= t3:
                print("phase T3")
                x_traj = trajectory.Trajectory((-l_swing[0] / self.t_cycle) * (t2 % self.t_cycle), ((-l_swing[0] / self.t_cycle) * (t2 % self.t_cycle)) + l_swing[0], 0, 0, t2, t3)
                y_traj = trajectory.Trajectory((-l_swing[1] / self.t_cycle) * (t2 % self.t_cycle), ((-l_swing[1] / self.t_cycle) * (t2 % self.t_cycle) )+ l_swing[1], 0, 0, t2, t3)
                z_traj = trajectory.Trajectory(leg_raise_height, leg_raise_height, leg_vz, -leg_vz, t2, t3)

                x = x_traj.at_time(sim_time)[0]
                y = y_traj.at_time(sim_time)[0]
                z = self.robot_height - z_traj.at_time(sim_time)[0]

            if sim_time >= t3 and sim_time <= t4:
                print("phase T4")
                x = ((-l_swing[0] / (self.t_cycle)) * (t2 % self.t_cycle)) + l_swing[0] + ((-l_swing[0] / (self.t_cycle)) * ((sim_time - t2) % self.t_cycle))
                y = ((-l_swing[1] / (self.t_cycle)) * (t2 % self.t_cycle)) + l_swing[1] + ((-l_swing[1] / (self.t_cycle)) * ((sim_time - t2) % self.t_cycle))

                z_traj = trajectory.Trajectory(leg_raise_height, 0, -leg_vz, 0, t3, t4)
                z = self.robot_height - z_traj.at_time(sim_time)[0]

            if sim_time > t4:
                print("phase T5")
                x = ((-l_swing[0] / (self.t_cycle)) * (t2 % self.t_cycle)) + l_swing[0] + (
                            (-l_swing[0] / (self.t_cycle)) * ((sim_time - t2) % self.t_cycle))
                y = ((-l_swing[1] / (self.t_cycle)) * (t2 % self.t_cycle)) + l_swing[1] + (
                            (-l_swing[1] / (self.t_cycle)) * ((sim_time - t2) % self.t_cycle))

                z = self.robot_height
            print("answer", x, y, z)
            leg_pos.append([x, y, z])
            i=i+1

        print(leg_pos)
        return leg_pos

if __name__ == '__main__':
    body = [0.1908, 0.080]
    legs = [0.0, 0.04, 0.100, 0.094333]
    # initialize robot gait generator
    beta = 0.75
    t_cycle = 0.5
    robot_height = 0.15
    robot_leg = leg_IK.robot_leg(legs)
    robot_gait = gait_generator.gait_generator(beta, t_cycle, robot_height, body, robot_leg)


# Exercício 5

soma = 0
cont = 0
valor = 0

while valor >= 0:
    valor = int(input("Qual é o valor?"))
    if valor < 0:
        break
    soma += valor
    cont += 1

media = soma/cont
print("Média dos valores lidos: ", media)