import constants as keys
from services.price.convert_price import convert_price

class GittigidiyorHelper:
    @staticmethod
    def extract_product_info(product) -> dict:
        product_name = product["title"]
        url = (product["href"])[2:]
        src = product.find("img", class_="img-cont")["data-original"]
        price_div = product.find(
            "div",
            class_="gg-w-24 gg-d-24 gg-t-24 gg-m-24 padding-none product-price-info",
        )
        price = (
            (price_div.find("p"))
            .text.replace(".", "")
            .replace(",", ".")
            .replace("TL", "")
            .strip()
        )
        p = {
            keys.LINK: url,
            keys.NAME: product_name,
            keys.SRC: src,
            keys.PRICE: convert_price(price),
            keys.MARKET: keys.GITTIGIFIYOR,
        }

        return p


import os
from typing import Optional, Union

class IteratorTask5:
    '''iterator class for task 5'''
    def __init__(self, dataset: str, classname: str, path: str) -> Union[str, None]:
        '''class constructor'''
        self.pathdir = ""
        self.classname = ""
        self.names = []
        self.limit = 0
        self.counter = 0
        self.dataset = ""
        self.init(dataset, classname, path)

    def __next__(self) -> Union[str, None]:
        '''!!!looped!!!move on to the next element on the task after the iteration'''
        if self.counter < self.limit:
            self.counter += 1
            return self.names[self.counter - 1]
        elif self.counter == self.limit:
            self.counter = 0
            self.counter += 1
            return self.names[self.counter - 1]

    def __iter__(self) -> Union[str, None]:
        '''iterator defining'''
        return self

    def init(self, dataset: str, classname: str, pathdir: str) -> Union[str, None]:
        '''we check the objects (items) with which we will have to work in the future'''
        if not "dataset" in pathdir:
            raise ("error")
        self.pathdir = pathdir
        self.classname = classname
        self.names = os.listdir(os.path.join(dataset, self.pathdir, self.classname))

        for i in self.names:
            if not ".jpg" in i:
                self.names.remove(i)
        self.limit = len(self.names)
        self.counter = 0

    def clear(self) -> Union[str, None]:
        '''cleansing'''
        self.counter = 0

    def setclassName(self, classname: str) -> Union[str, None]:
        '''setting the class name'''
        self.init(self.dataset, classname, self.pathdir)

    def getclassName(self) -> Union[str, None]:
        '''getting the class name'''
        print(self.classname)

    def setPath(self, pathdir: str) -> Union[str, None]:
        '''setting the path'''
        self.init(self.dataset, self.classname, pathdir)


"""
200. Number of Islands
Given an m x n 2D binary grid which represents a map of "1"s (land) and "0"s (water), return the number of islands.

An island is surrounded by water and is formed by connecting adjacent lands horizontally or vertically. You may assum all four edges of the grid are all surrounded by water.

Example1:
Input: grid = [
  ["1","1","1","1","0"],
  ["1","1","0","1","0"],
  ["1","1","0","0","0"],
  ["0","0","0","0","0"]
]
Output: 1

Example2:
Input: grid = [
  ["1","1","0","0","0"],
  ["1","1","0","0","0"],
  ["0","0","1","0","0"],
  ["0","0","0","1","1"]
]
Output: 3
"""

"""
Note:
1. Recursion (DFS): O(nm) time | O(nm) space
2. Iteration (BFS): O(nm) time | O(nm) space
"""

from collections import deque
from typing import List
import unittest
class Solution:
    def numIslands(self, grid: List[List[str]]) -> int:
        # edge
        if not grid:
            return 0
        numOfIslands = 0
        for row in range(len(grid)):
            for col in range(len(grid[row])):
                if grid[row][col] == "1":
                    self.dfs(grid, row, col)
                    numOfIslands += 1
        return numOfIslands

    def dfs(self, grid, row, col):
        if self.isWater(grid, row, col):
            return
        grid[row][col] = "0"
        directions = [(row - 1, col), (row + 1, col),
                      (row, col + 1), (row, col - 1)]
        for x, y in directions:
            self.dfs(grid, x, y)

    def numIslands2(self, grid: List[List[str]]) -> int:
        if not grid:
            return 0
        numOfIslands = 0
        for row in range(len(grid)):
            for col in range(len(grid[row])):
                if grid[row][col] == "1":
                    self.bfs(grid, row, col)
                    numOfIslands += 1
        return numOfIslands

    def bfs(self, grid, row, col):
        queue = deque([(row, col)])
        while queue:
            currentRow, currentCol = queue.popleft()
            directions = [(currentRow + 1, currentCol), (currentRow - 1, currentCol),
                          (currentRow, currentCol + 1), (currentRow, currentCol - 1)]
            for x, y in directions:
                if not self.isWater(grid, x, y):
                    queue.append((x, y))
                    grid[x][y] = "0"

    def isWater(self, grid, row, col):
        return row < 0 or col < 0 or row >= len(grid) or col >= len(grid[0]) or grid[row][col] == "0"

# Unit Tests
funcs = [Solution().numIslands, Solution().numIslands2]

class TestNumIslands(unittest.TestCase):
    def testNumIslands1(self):
        for func in funcs:
            grid = [
                ["1", "1", "0", "0", "0"],
                ["1", "1", "0", "0", "0"],
                ["0", "0", "1", "0", "0"],
                ["0", "0", "0", "1", "1"]
            ]
            self.assertEqual(func(grid=grid), 3)

    def testNumIslands2(self):
        for func in funcs:
            grid = [
                ["1", "1", "1", "1", "0"],
                ["1", "1", "0", "1", "0"],
                ["1", "1", "0", "0", "0"],
                ["0", "0", "0", "0", "0"]
            ]
            self.assertEqual(func(grid=grid), 1)

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


from django.core.paginator import Paginator
from django.urls import reverse, reverse_lazy
from django.views.generic import ListView, DetailView, UpdateView, CreateView, DeleteView
from django.shortcuts import render
from movies.models import Movie

# Create your views here.

class MoviesView(ListView):
    """Show the Movie lists"""

    model = Movie
    paginate_by = 10
    paginate_orphans = 5
    ordering = "-created_at"
    context_object_name = "movies"

class MovieDetail(DetailView):
    """ Show the movie details"""
    model = Movie
    context_object_name = "movie"

class UpdateMovie(UpdateView):
    """ Edit Movie's information """
    model = Movie
    fields = (
        "title",
        "year",
        "cover_image",
        "rating",
        "category",
        "director",
        "cast",
    )

    def get_success_url(self):
        movie_pk = self.kwargs.get("pk")
        print(movie_pk)
        return reverse("movies:movie", kwargs={"pk": movie_pk})

class CreateMovie(CreateView):
    """ Create Movie's information """
    model = Movie
    fields = (
        "title",
        "year",
        "cover_image",
        "rating",
        "category",
        "director",
        "cast",
    )

    def get_success_url(self):
        return reverse("movies:movies")

class DeleteMovie(DeleteView):
    """Delete Movie's information"""
    model = Movie
    success_url = reverse_lazy("movies:movies")


import telebot
import time

# instanciamos el bot de Telegram
bot = telebot.TeleBot('6208005709:AAGfEH4BmxypLKtCsnnAE_FkDuyPuixaV-I')

# responde al comando /start
@bot.message_handler(commands=["start", "ayuda", "help"])
def cmd_start(message):
    bot.reply_to(message, "Hola mundo")

#responde a los mensajes de texto que no son comandos
@bot.message_handler(content_types=["text"])
def bot_mensajes_texto(message):
    """Gestiona los mensajes recibidos"""
    if message.text.startswith("/"):
        bot.send_message(message.chat.id, "Comando no disponible")
    else:
        mensajeRespuesta = bot.send_message(message.chat.id, "Mensaje recibido")
        time.sleep(3)
        bot.delete_message(message.chat.id, mensajeRespuesta.message_id)
        bot.delete_message(message.chat.id, message.message_id)

if __name__=='__main__':
    print('Iniciando el bot')
    bot.infinity_polling()
    print('Fin')

Software/W10/Bot Telegram/Prueba API Bot 2.py


'''
Escreva um programa que leia dois números inteiros e compare-os,
mostrando na tela uma mensagem:
- o primeiro valor é maior
- o segundo valor é maior
- não existe valor maior; os dois são iguais
'''
numa = float(input('Digite um número: '))
numb = float(input('Digite o segundo número: '))
if numa > numb:
    print(f'O número {numa:.0f} é maior que {numb:.0f}')
elif numb > numa:
    print(f'O número {numb:.0f} é maior que {numa:.0f}')
else:
    print('Os números são iguais!')


import requests
import openai

def handler(event, context):
    print(event)

    query = event.get('queryStringParameters', {}).get('query')

    search_term = f'&searchTerm={query}' if query else ''

    response = requests.get(
        'https://www.encodeproject.org/search/?type=Award'
        '&field=description&field=lab&field=pi.lab.title'
        '&format=json&limit=3' + search_term
    )

    results = response.json()['@graph']

    if event.get('queryStringParameters', {}).get('summarize'):

        results = []

        for award in response.json()['@graph']:
            prompt = award['description'] + ' tl;dr:'
            summary = openai.Completion.create(
                model='text-davinci-003',
                prompt=prompt,
                temperature=0.7,
                max_tokens=200,
                top_p=1.0,
                frequency_penalty=0.0,
                presence_penalty=1
            )
            results.append(
                {
                    'summary': summary['choices'][0]['text'],
                    'original': award
                }
            )

    return {
        'message': 'ok',
        'results': results
    }


import argparse
import os
import random
import shutil
import xml.etree.ElementTree as ET
from pathlib import Path
from glob import glob
from sklearn.model_selection import train_test_split
import argparse

def move_files_to_folder(list_of_files, destination_folder):
    for f in list_of_files:
        try:
            shutil.copy(f, destination_folder)
        except:
            print(f)
            assert False

def get_annotations(path):
    annotations = []
    images = []
    for txt_file in glob(path + '/*.txt'):
        annotations.append(txt_file)
        image = txt_file.replace('txt', 'jpg')
        images.append(image)

    return annotations, images

def main():
    parser = argparse.ArgumentParser()
    parser.add_argument('--path', type=str, required=True, help='Path to images')
    opt = parser.parse_args()

    annotations, images = get_annotations(opt.path)

    # Split the dataset into train-valid-test splits
    train_images, val_images, train_annotations, val_annotations = train_test_split(images, annotations, test_size = 0.2, random_state = 1)
    val_images, test_images, val_annotations, test_annotations = train_test_split(val_images, val_annotations, test_size = 0.5, random_state = 1)

    os.system('mkdir data/images data/annotations')
    os.system('mkdir data/images/train data/images/val data/images/test data/annotations/train data/annotations/val data/annotations/test')

    move_files_to_folder(train_images, 'data/images/train')
    move_files_to_folder(val_images, 'data/images/val/')
    move_files_to_folder(test_images, 'data/images/test/')
    move_files_to_folder(train_annotations, 'data/annotations/train/')
    move_files_to_folder(val_annotations, 'data/annotations/val/')
    move_files_to_folder(test_annotations, 'data/annotations/test/')

    os.system('cp -r data/annotations data/labels')

if __name__ == "__main__":
    main()


import traceback
import yaml
import gc

from src.neural_analysis import *
from src.wiener_filter import *
from src.filters import *
from src.folder_handler import *
from src.tdt_support import *
from src.decoders import *
from src.plotter import *
from src.phase_decoder_support import *
from sklearn.metrics import r2_score
from sklearn.utils import shuffle
from scipy.signal import resample, find_peaks
from scipy.stats import mode
from sklearn.decomposition import PCA
from sklearn.preprocessing import MinMaxScaler
import scipy.io as sio
import numpy as np
import pandas as pd
import cv2
import copy

class CortProcessor:
    '''
    class that can handle neural + kinematic/EMG data simultaneously
    upon initialization, extracts data from TDT and anipose file
    see cort_processor.md in 'docs' for more information
    '''
    def __init__(self, folder_path):
        if os.path.isdir(folder_path):
            #see docs/data_folder_layout.md for how to structure folder_path
            self.handler = FolderHandler(folder_path)
            self.tdt_data, self.kin_data = self.extract_data()

            self.crop_list = None
            crop = self.parse_config()
            if isinstance(crop, list):
                self.crop_list = crop

            self.data={}
            self.data['rates'] = 'run_process_first'
            self.data['coords'] = 'run_process_first'
            self.data['angles'] = 'run_process_first'
            self.data['toe_height'] = 'run process first, then run process\
                    toehight'

            self.gait_indices = 'run get_gait_indices first'
            self.avg_gait_samples = 'run get_gait_indices first'

        else:
            print('this is filipe data i belive')
            self.handler = sio.loadmat(folder_path)
            self.gait_indices=None
            self.avg_gait_samples=None
            self.extract_filipe()

    def extract_filipe(self):
        self.data={}
        #remoivng 0 rate channels, which
        #throws an error in wiener filter
        temp_rates = self.handler['SelectedSpikeData']
        mask = np.average(temp_rates, 0) > .1
        temp_rates_remove = temp_rates[:, mask]
        self.data['rates'] = [temp_rates_remove]

        self.data['coords'] = [self.handler['SelectedKinematicData']['kindata'][0,0]]
        angles_temp = self.handler['SelectedKinematicData']['kinmeasures'][0,0][0,0]
        self.data['angles'] = [np.squeeze(np.array(angles_temp.tolist())).T]
        angle_names = ['ankle', 'limbfoot', 'hip', 'knee', 'toeheight']
        self.data['angle_names'] = angle_names

        temp_channels  =\
        self.handler['SelectedFieldDatastruct']['FieldCh2Use'][0][0][0].tolist()

        which_channels = copy.deepcopy(temp_channels)
        for idx in range(temp_rates.shape[1]):
            if np.average(temp_rates[:, idx]) < .1:
                baddy = temp_channels[idx]
                which_channels.remove(baddy)

        self.data['which_channels'] = which_channels
#        samples = temp_rates.shape[0]
#        num_channels = 32
#        original_rates = np.zeros((samples, num_channels))
#
#        for idx in range(num_channels):
#            if idx in which_channels:
#                position = np.where(which_channels==idx)[0][0]
#                if np.average(temp_rates[:, position]) > .1:
#                    original_rates[:, idx] = temp_rates[:, position]
#                else:
#                    original_rates[:,idx] = np.nan
#            else:
#                original_rates[:,idx] = np.nan
#
#        self.data['original_rates'] = [original_rates]
#
    def parse_config(self):
        '''
        this loads config.yaml file
        '''
        try:
            path = self.handler.folder_path
            with open(f"{path}/config.yaml", "r") as stream:
                yaml_stuff = yaml.safe_load(stream)
                crop = 'crop'

                if crop in yaml_stuff:
                    return yaml_stuff[crop]
                else:
                    print('no crop')
                    return 0
        except yaml.YAMLError as exc:
            print(exc)

    def extract_data(self):
        '''
        this is called when a CortProcessor is initialized.
        It extracts raw neural,raw angles, and raw coords
        neural data is saved under CortProcessr.tdt_data
        kinematic data is saved under CortProcessor.kin_data

        If you use process cort script, all these attriibutes are overwritten
        since raw data isnt saved after processing.
        '''
        tdt_data_list = []
        raw_ts_list = self.handler.ts_list
        raw_tdt_list = self.handler.tdt_list
        for i in range(len(raw_tdt_list)):
            tdt_data_list.append(extract_tdt(raw_tdt_list[i], raw_ts_list[i]))

        kin_data_list = []

        raw_coords_list = self.handler.coords_list
        raw_angles_list = self.handler.angles_list
        raw_phase_list = self.handler.phase_list
        for i in range(len(raw_coords_list)):
            kin_data_list.append(extract_kin_data(raw_coords_list[i],
                raw_angles_list[i], raw_phase_list[i]))

        return tdt_data_list, kin_data_list

    def process(self, manual_crop_list=None, threshold_multiplier = -3.0, window = 60, binsize = 0.05, clear_storage = True):
        """
        1) takes raw neural data, then bandpass+notch filters, then extracts
        spikes using threshold_multiplier, then bins into firing rates with bin
        size
        2) takes coordinates/angles, then resamples at 20 HZ
        3) saves all under CortHandler.data

        crop is automatically read from config.yaml file, unless manual crop
        list is set.
        """
        if self.crop_list is not None:
            crop_list = self.crop_list
        elif manual_crop_list is not None:
            crop_list = manual_crop_list
        else:
            #TODO
            print('need to make it so that it is uncropped')

        tdt_data_list = self.tdt_data
        kin_data_list = self.kin_data

        self.data = {}

        self.data['bodyparts'] = kin_data_list[0]['bodyparts']
        self.data['angle_names'] = kin_data_list[0]['angles_list']

        self.data['rates']=[]
        self.data['coords']=[]
        self.data['angles']=[]
        self.data['phase'] = []

        for i in range(len(tdt_data_list)):
            #syncs neural data/kinematic data, then crops
            self.tdt_data[i], self.kin_data[i] = self.crop_data(tdt_data_list[i],
                    kin_data_list[i], crop_list[i])

            fs = self.tdt_data[i]['fs'] #quick accessible variable
            neural = self.tdt_data[i]['neural'] #quick accessible variable

            #notch and bandpass filter

            ##common mode rejection assumes equal impedence and is therefore not recommended
            # means = np.mean(neural, axis = 1)
            # commonmode = []
            # for j in range(neural.shape[1]):
            #     commonhold = neural[:,j] - means
            #     commonmode.append(commonhold)
            # commonmode = np.array(commonmode).T

            half_filtered_neural = fresh_filt(neural, 350, 8000, fs, order = 4)
            filtered_neural = notch_filter(half_filtered_neural, fs)
            clean_filtered_neural = remove_artifacts(filtered_neural, fs)

            #extract spikes with rolling window stdv
            spikes = rolling_threshold_crossings(clean_filtered_neural, fs,
                    threshold_multiplier, window)
            firing_rates = spike_binner(spikes, fs, binsize)

            #old processing method
            # spikes = autothreshold_crossings(clean_filtered_neural,
            #         threshold_multiplier)
            # firing_rates = spike_binner(spikes, fs, binsize)

            self.data['rates'].append(firing_rates)

            temp_angles = self.kin_data[i]['angles'] #quick accessible variable
            temp_coords = self.kin_data[i]['coords']
            temp_phase = self.kin_data[i]['phase']

            #resample at same frequency of binned spikes
            resampled_angles = resample(temp_angles, firing_rates.shape[0],
                    axis=0)
            resampled_coords = resample(temp_coords, firing_rates.shape[0],
                    axis=0)
            resampled_phase = self.resample_mode(temp_phase, firing_rates.shape[0])

            self.data['angles'].append(resampled_angles)
            self.data['coords'].append(resampled_coords)
            self.data['phase'].append(resampled_phase)

            #remove raw data to save memory
            if clear_storage == True:
                self.tdt_data[i] = 0
                self.kin_data[i] = 0
            gc.collect()

        #returning stitched rates --- we don't directly use this for anything.
        return np.vstack(self.data['rates']), np.vstack(self.data['angles']), np.hstack(self.data['phase'])

    def resample_mode(self, phase, shape):
        re = resample(phase, shape, axis=0)
        for i in range(re.shape[0]):
            re[i] = int(np.round(re[i]))
        return re

    def process_toe_height(self):
        """
        extracts toe height from data['coords'], then scales such that lowest
        toe height is 0.

        toe_num is which bodypart in data['coords'] is the toe. default is
        bodypart 0
        """
        try:
            toe_num = self.bodypart_helper('toe')
            temp_list = []
            self.data['toe_height'] = []
            minimum_toe = 1000 #arbitrary high number to be beat
            for i in range(len(self.data['coords'])):
                #find y-value of toe
                toe_height = self.data['coords'][i][:, toe_num, 1]
                if np.min(toe_height) < minimum_toe:
                    minimum_toe = np.min(toe_height)
                temp_list.append(toe_height)
            for i in range(len(temp_list)):
                norm_toe_height = temp_list[i] - minimum_toe
                self.data['toe_height'].append(norm_toe_height)

            return np.hstack(self.data['toe_height'])
        except Exception as e:
            print('failed!! did you run process first')
            print(e)

    def marker_position(self, bodypart, dimension):
        """
        updated version of process_toe_height that
        a) takes any bodypart
        b) accounts for reformatting splices
        """
        mark_num = self.bodypart_helper(bodypart)
        mark_stack = []
        for i in range(len(self.data['coords'])):
            mark_stack.append(self.data['coords'][i][9:, mark_num, dimension])
        mark_y = np.hstack(mark_stack)
        mark_min = np.min(mark_y)
        mark_y_norm = mark_y - mark_min
        return mark_y_norm.T

    def crop_data(self, tdt_data, kin_data, crop):
        '''
        helper function that both syncs and crops neural/kinematic data
        see docs/cam_something.odg for how it syncs em.
        '''

        crop_tdt_datafile=tdt_data
        crop_kin_datafile=kin_data

        start_time = crop[0]
        end_time = crop[1]

        kin_start = start_time*200
        kin_end = end_time * 200

        init_start_sample = get_sync_sample(tdt_data)

        start_sample = round(init_start_sample + (start_time * tdt_data['fs']))
        end_sample = round(init_start_sample + (end_time * tdt_data['fs']))

        temp_neural = tdt_data['neural'] #going to slice variable
        temp_ts = tdt_data['ts']

        crop_tdt_datafile['neural'] = temp_neural[start_sample:end_sample,:]
        crop_tdt_datafile['ts'] = temp_ts[start_sample:end_sample]

        del(temp_neural)
        del(temp_ts)

        gc.collect()

        temp_coords = kin_data['coords']
        temp_angles = kin_data['angles']
        temp_phase = kin_data['phase']
        temp_frames = kin_data['fnum']

        crop_kin_datafile['coords'] = temp_coords[kin_start:kin_end,:,:]
        crop_kin_datafile['angles'] = temp_angles[kin_start:kin_end,:]
        crop_kin_datafile['phase'] = temp_phase[kin_start:kin_end]
        crop_kin_datafile['fnum'] = temp_frames[kin_start:kin_end]

        #maybe need edge-case if only single angle/bodypart

        return crop_tdt_datafile, crop_kin_datafile

    def stitch_and_format(self, firing_rates_list=None,
            resampled_angles_list=None, N = 10):
        """
        takes list of rates, list of angles, then converts them into lags of 10
        using format rate in wiener_filter.py, and then stitches them into one
        big array

        both lists must have same # of elements, and each array inside list
        must have the same size as the corresponding array in the other list.
        """
        if firing_rates_list == None and resampled_angles_list == None:
            firing_rates_list = self.data['rates']
            resampled_angles_list = self.data['angles']

        assert isinstance(firing_rates_list, list), 'rates must be list'
        assert isinstance(resampled_angles_list, list), 'angles must be list'
        formatted_rates = []
        formatted_angles = []

        for i in range(len(firing_rates_list)):
            f_rate, f_angle = format_data(firing_rates_list[i],
                    resampled_angles_list[i], N)
            formatted_rates.append(f_rate)
            formatted_angles.append(f_angle)

        if len(formatted_rates)==1: #check if just single array in list
            rates = np.array(formatted_rates)
        else: #if multiple, stitch into single array
            rates = np.vstack(formatted_rates)

        if len(formatted_angles)==1: #check if single array
            kin = np.array(formatted_angles)
        elif formatted_angles[0].ndim > 1: #check if multiple angles
            kin = np.vstack(formatted_angles)
        else:
            kin = np.hstack(formatted_angles)

        return np.squeeze(rates), np.squeeze(kin)

    def stitch_data(self, firing_rates_list, resampled_angles_list):
        '''
        deprecated. you can just use np.vstack instead of this
        WARNING: VSTACK WILL NOT BE INDEXED AT PARITY TO STITCH AND FORMAT UNLESS THE LAST 10 ENTRIES OF EACH LIST IS OMITTED
        '''
        rates = np.vstack(firing_rates_list)
        kin = np.vstack(resampled_angles_list)

        return rates, kin

    def subsample(self, percent, X=None, Y=None):
        '''
        function to subsample RAW data (not gait aligned).
        we keep it in order since we go by folds.
        '''
        if X is None:
            X = self.data['rates']
        if Y is None:
            Y = self.data['angles']

        if percent==1.0:
            return X, Y

        new_x=[]
        new_y=[]

        for i in range(len(X)):
            subsample = int(np.round(percent * X[i].shape[0]))
            new_x.append(X[i][:subsample,:])
            new_y.append(Y[i][:subsample,:])

        return new_x, new_y

    def decode_angles(self, X=None, Y=None, metric_angle='limbfoot', scale=False):
        """
        takes list of rates, angles, then using a wiener filter to decode.
        if no parameters are passed, uses data['rates'] and data['angles']

        returns best_h, vaf (array of all angles and all folds), test_x (the
        x test set that had best performance, and test_y (the y test set that
        had best formance)
        """
        try:
            if X is None:
                X = self.data['rates']
            if Y is None:
                Y = self.data['angles']

            if scale is True:
                X = self.apply_scaler(X)
            X, Y = self.stitch_and_format(X,Y)

            metric = self.angle_name_helper(metric_angle)

            h_angle, vaf_array, final_test_x, final_test_y, _ = decode_kfolds(X,Y,
                    metric_angle=metric)

            self.h_angle = h_angle
            return h_angle, vaf_array, final_test_x, final_test_y
        except Exception as e:
            print(e)
            print('did you run process() first.')

    def decode_toe_height(self):
        '''
        a PIPELINE code, which you can you only after you run
        process_toe_height. You cannot pass any custom parameters in this. it
        uses a wiener filter to create a decoder just for toe height
        '''
        try:
            X,Y = self.stitch_and_format(self.data['rates'],
                    self.data['toe_height'])
            h_toe, vaf_array, final_test_x, final_test_y = decode_kfolds_single(X, Y)
            self.h_toe = h_toe
            return h_toe, vaf_array, final_test_x, final_test_y
        except:
            print('did you run process_toe_height() yet?????')

#     def decode_phase(self, rates=None, angles=None, metric_angle='limbfoot'):
#         '''
#         this has a non-zero chance of returning overfit cos test cases
#         this probability is assumed to be less than the 1% predicted by random selection of kfolds
#         as the quality of the data along equally divded splits is assumed to be variable
#         '''
#         if rates is None and angles is None:
#             full_rates, full_angles = self.stitch_and_format(self.data['rates'],
#                         self.data['angles'])

#         elif isinstance(rates, list):
#             full_rates, full_angles = self.stitch_and_format(rates, angles)
#         else:
#             full_rates = rates
#             full_angles = angles

#         angle_number = self.angle_name_helper(metric_angle)
#         phase_list = []

#         for i in range(full_angles.shape[1]):
#             peak_list = tailored_peaks(full_angles, i, self.data['angle_names'][i])
#             phase_list_tmp = to_phasex(peak_list, full_angles[:,i])
#             phase_list.append(phase_list_tmp)
#         phase_list = np.array(phase_list).T
#         sin_array, cos_array = sine_and_cosine(phase_list)

#         h_sin, r2_sin, test_rates, test_sin, sin_test_index = decode_kfolds(X=full_rates, Y=sin_array, metric_angle=angle_number, vaf_scoring=False)
#         h_cos, r2_cos, _, test_cos, _ = decode_kfolds(X=full_rates, Y=cos_array, metric_angle=angle_number, vaf_scoring=False, forced_test_index = sin_test_index)
#         predicted_sin = predicted_lines(test_rates, h_sin)
#         predicted_cos = predicted_lines(test_rates, h_cos)
#         # order_test = predicted_lines(test_rates, h_atantest)
#         predicted_arctans = arctan_fn(predicted_sin, predicted_cos)
#         test_arctans = phase_list[sin_test_index, :]

#         self.h_sin = h_sin
#         self.h_cos = h_cos
#         self.phase_list = phase_list

#         return h_sin, h_cos, np.mean((r2_sin,r2_cos), axis=0), predicted_arctans, test_arctans, test_rates, phase_list

    def phase_train(self):
        rect_phase_list = []
        for i in range(len(self.data['phase'])):
            scrub_phase = ss_cleaner(self.data['phase'][i], 3)
            rect_phase_list.append(scrub_phase)
        form_rates, form_phase = self.stitch_and_format(self.data['rates'], rect_phase_list)
        phase_12 = form_phase[np.nonzero(form_phase)]
        rates_12 = form_rates[np.nonzero(form_phase),:][0]
        phase_angles, swing_mean = get_phase_angles(phase_12)
        sin_arr, cos_arr = sine_and_cosine(phase_angles)
        h_sin_nl, lsq_sin, r2_sin_nl, test_rates, test_sin, sin_test_index = decode_kfolds_single_nonlinear(X=rates_12, Y=sin_arr, scoring='R2')
        h_cos_nl, lsq_cos, r2_cos_nl, _, test_cos, _ = decode_kfolds_single_nonlinear(X=rates_12, Y=cos_arr, scoring='R2', forced_test_index = sin_test_index)
        predicted_sin_nl = test_nonlinear_wiener_filter(test_rates, h_sin_nl, lsq_sin)
        predicted_cos_nl = test_nonlinear_wiener_filter(test_rates, h_cos_nl, lsq_cos)
        predicted_arctans_nl = arctan_fn(predicted_sin_nl, predicted_cos_nl)
        test_arctans = phase_angles[sin_test_index]

        self.predicted_arctans_nl = predicted_arctans_nl
        self.test_arctans = test_arctans
        self.swing_mean = swing_mean
        self.h_sin_nl = h_sin_nl
        self.lsq_sin = lsq_sin
        self.h_cos_nl = h_cos_nl
        self.lsq_cos = lsq_cos

        return h_sin_nl, lsq_sin, h_cos_nl, lsq_cos, predicted_arctans_nl, test_arctans, swing_mean

    def phase_evaluate(self, manual_threshold = None, refractory_tics = 0, bounds = [-4, 4], plotting = False):
        if manual_threshold == None:
            threshold = self.swing_mean
        else:
            threshold = manual_threshold
        crossingsA = np.diff(self.test_arctans >threshold, prepend=0)
        np.put(crossingsA, np.where(crossingsA==-1), 0)
        crossingsB = np.diff(self.predicted_arctans_nl >threshold, prepend=0)
        np.put(crossingsB, np.where(crossingsB==-1), 0)
        crossingsC = stim_cooldown(crossingsB, refractory_tics)
        true_indicies, new_indicies, delay_array_list, spacing_mean = phase_sychrony(crossingsA, crossingsC)
        true_score, effective_score = phase_diagnositc(self.predicted_arctans_nl, self.test_arctans, threshold, true_indicies, new_indicies, delay_array_list, spacing_mean, bounds, plotting)
        return true_score, effective_score

    def get_H(self, H):
        if H == 'toe':
            H_mat = self.h_toe
        if H == 'angle':
            H_mat = self.h_angle
        if H == 'cos':
            H_mat = self.h_cos
        if H == 'sin':
            H_mat = self.h_sin
        return H_mat

    def impulse_response(self, AOI, H = None, plotting = True):
        phase_list = self.phase_list
        if H == None:
            H = 'sin'
        h_mat = self.get_H(H)
        response = impulse_response(AOI, h_mat, phase_list, plotting)
        return response

    def neuron_tuning(self, rates_gait=None):
        '''
        this takes in neural data that is divided into gaits, and sorts each
        channel by where in the gait cycle each channel is most active

        feed the output of this into plot_raster!
        '''
        try:
            if rates_gait is None:
                rates_gait = self.rates_gait
            rates_gait = np.vstack(rates_gait)
            gait_array_avg = np.average(rates_gait, axis=0)
            df = pd.DataFrame(gait_array_avg)
            temp = df.iloc[:, df.idxmax(axis=0).argsort()]
            self.norm_sorted_neurons=((temp-temp.min())/(temp.max()-temp.min()))
            return self.norm_sorted_neurons

        except Exception as e:
            print(e)
            print('make sure you run divide into gaits first')

    def apply_PCA(self, dims=None, X=None, transformer=None):
        '''
        this works now?
        '''
        if X is None:
            X=self.data['rates']
        if dims is None:
            dims=.95
        X_full = np.vstack(X)
        if transformer is None:
            pca_object = PCA(n_components = dims)
            pca_object.fit(X_full)
        else:
            pca_object = transformer

        x_pca = []

        for X_recording in X:
            x_pca.append(pca_object.transform(X_recording))

        self.num_components = x_pca[0].shape[1]
        self.pca_object = pca_object
        return x_pca

    def apply_scaler(self, X=None, scaler=None):
        if X is None:
            X=self.data['rates']
        if scaler is None:
            my_scaler=StandardScaler()
            X_full = np.vstack(X)
            my_scaler.fit(X_full)
        else:
            my_scaler = scaler

        scaled_X = []
        for X_recording in X:
            scaled_X.append(my_scaler.transform(X_recording))

        self.scaler = my_scaler
        return scaled_X

    def display_frame(self, video_path, recording_number, sample_number):
        cap = cv2. VideoCapture(video_path)
        crop_times = self.crop_list[recording_number]
        first_frame = crop_times[0] * 200
        my_frame = first_frame + (sample_number * 4)
        cap.set(1, my_frame)
        ret, frame = cap.read()

        video_time = my_frame/200
        print(f'video_time is: {video_time}')

        return frame

    def predicted_lines_malleable(self, h_sin, h_cos):
        try:
            full_rates, full_angles = self.stitch_and_format(self.data['rates'],
                            self.data['angles'])
            phase_list = self.phase_list
            sin_array, cos_array = sine_and_cosine(phase_list)
            predicted_sin = predicted_lines(full_rates, h_sin)
            predicted_cos = predicted_lines(full_rates, h_cos)
            arctans = arctan_fn(predicted_sin, predicted_cos)
            r2_array = []
            for i in range(sin_array.shape[1]):
                r2_sin = r2_score(sin_array[:,i], predicted_sin[:,i])
                r2_cos = r2_score(cos_array[:,i], predicted_cos[:,i])
                r2_array.append(np.mean((r2_sin,r2_cos)))
            return arctans, phase_list, r2_array
        except:
            print('error lol')
            print('Feed in sin and cos H matricies from another session to test gernealizability')

    def angle_name_helper(self, angle_name):
        return self.data['angle_names'].index(angle_name)

    def bodypart_helper(self, bodypart):
        return self.data['bodyparts'].index(bodypart)


import os
import sys
import numpy as np
from numpy.testing import assert_allclose
import porespy as ps
import openpnm as op
from pathlib import Path

class ExportTest():

    def setup_class(self):
        self.path = os.path.dirname(os.path.abspath(sys.argv[0]))

    def test_export_to_palabos(self):
        X = Y = Z = 20
        S = X * Y * Z
        im = ps.generators.blobs(shape=[X, Y, Z], porosity=0.7, blobiness=1)
        tmp = os.path.join(self.path, 'palabos.dat')
        ps.io.to_palabos(im, tmp, solid=0)
        assert os.path.isfile(tmp)
        with open(tmp) as f:
            val = f.read().splitlines()
        val = np.asarray(val).astype(int)
        assert np.size(val) == S
        assert np.sum(val == 0) + np.sum(val == 1) + np.sum(val == 2) == S
        os.remove(tmp)

    def test_to_vtk_2d(self):
        im = ps.generators.blobs(shape=[20, 20])
        ps.io.to_vtk(im, filename='vtk_func_test')
        assert os.stat('vtk_func_test.vti').st_size == 831
        os.remove('vtk_func_test.vti')

    def test_to_vtk_3d(self):
        im = ps.generators.blobs(shape=[20, 20, 20])
        ps.io.to_vtk(im, filename='vtk_func_test')
        assert os.stat('vtk_func_test.vti').st_size == 8433
        os.remove('vtk_func_test.vti')

    def test_dict_to_vtk(self):
        im = ps.generators.blobs(shape=[20, 20, 20])
        ps.io.dict_to_vtk({'im': im}, filename="dictvtk")
        a = os.stat('dictvtk.vti').st_size
        os.remove('dictvtk.vti')
        ps.io.dict_to_vtk({'im': im, 'im_neg': ~im}, filename="dictvtk")
        b = os.stat('dictvtk.vti').st_size
        assert a < b
        os.remove('dictvtk.vti')

    def test_to_stl(self):
        im = ps.generators.blobs(shape=[50, 50, 50])
        ps.io.to_stl(im, filename="im2stl")
        os.remove("im2stl.stl")

    def test_spheres_to_comsol_radii_centers(self):
        radii = np.array([10, 20, 25, 5])
        centers = np.array([[0, 10, 3],
                            [20, 20, 13],
                            [40, 25, 55],
                            [60, 0, 89]])
        ps.io.spheres_to_comsol(filename='sphere_pack', centers=centers, radii=radii)
        # os.remove("sphere_pack.mphtxt")

    def test_spheres_to_comsol_im(self):
        im = ps.generators.overlapping_spheres(shape=[100, 100, 100],
                                               r=10, porosity=0.6)
        ps.io.spheres_to_comsol(filename='sphere_pack', im=im)
        # os.remove("sphere_pack.mphtxt")

    def test_zip_to_stack_and_folder_to_stack(self):
        p = Path(os.path.realpath(__file__),
                 '../../../test/unit/blobs_layers.zip').resolve()
        im = ps.io.zip_to_stack(p)
        assert im.shape == (100, 100, 10)
        p = Path(os.path.realpath(__file__),
                 '../../../test/unit/blobs_layers').resolve()
        im = ps.io.folder_to_stack(p)
        assert im.shape == (100, 100, 10)

if __name__ == "__main__":
    t = ExportTest()
    self = t
    t.setup_class()
    for item in t.__dir__():
        if item.startswith("test"):
            print(f"Running test: {item}")
            t.__getattribute__(item)()


# -*- coding: utf-8 -*-

__author__ = 'kaspar lilja'
__email__ = 'kalilja@nmbu.no'

def char_counts(textfilename):
    file_name = open(textfilename)
    str_text = file_name.read()
    file_name.close()
    count_ = {}

    for key_value in range(256):
        count_[key_value] = 0

    for index, char in enumerate(str_text):
        if ord(char) in count_.keys():
            count_[ord(char)] += 1
        else:
            count_[ord(char)] = 1
    return count_

if __name__ == '__main__':

    filename = 'file_stats.py'
    frequencies = char_counts(filename)
    for code in range(256):
        if frequencies[code] > 0:
            character = ''
            if code >= 32:
                character = chr(code)

            print(
                '{:3}{:>4}{:6}'.format(
                    code, character, frequencies[code]
                )
            )


from fastapi import FastAPI, Request
from fastapi.responses import HTMLResponse
from fastapi.staticfiles import StaticFiles
from fastapi.templating import Jinja2Templates

from databse.db import init_db

app = FastAPI()
app.mount("/static", StaticFiles(directory="static"), name="static")
templates = Jinja2Templates(directory="templates")

@app.on_event("startup")
async def start_db():
    await init_db()

@app.get("/")
async def root():
    return {"message": "Hello World"}

@app.get("/student", response_class=HTMLResponse)
async def first(request: Request):
    return templates.TemplateResponse("add_student.html", {"request": request})


class REINFORCE(object):

  def __init__(
      self, number_of_arms, step_size=0.1, baseline=False, temperature=1.0):
    self._number_of_arms = number_of_arms
    self._lr = step_size
    self._baseline = baseline
    self._temperature = temperature
    self.name = 'reinforce, baseline: {}, temperature: {}'.format(
        baseline, temperature)
    self.reset()

#   def policy(self, *args):
#     T = self._temperature
#     if len(args) == 1:
#       h_a = self._estimates[args]
#       h_bs = np.sum(self._estimates[np.arange(self._number_of_arms) != h_a])
#     else:
#       h_a = self._estimates[args[0]:args[len(args)]]
#       h_bs = [np.sum([args[j] for j in range(len(args)) if j != i]) for i in range(len(args))]

#     p_a = np.divide(np.exp(h_a / T), np.exp(h_bs / T))
#     return p_a

  def get_baseline(self):
    if self._baseline:
      t = np.sum(self._counts)
      return self.R_t / t

    return self._baseline

#   def update(self, *action, reward, selected=True):
#     H_t = self._estimates[action]
#     b = self.get_baseline()
#     r = reward
#     if selected:
#       G_th = (r - b) * (1 - policy(action))
#       return H_t + self._lr * G_th
#     else:
#       G_th = (r - b) * policy(action)
#       return H_t - self._lr * G_th

  def step(self, previous_action, reward):
    T = self._temperature
    if previous_action is not None:
      r = reward
      self._counts[previous_action] += 1.0
      self.R_t += r
      b = self.get_baseline()
      self._estimates -= (self._lr * (r - b) * self._policy) / T
      self._estimates[previous_action] += (self._lr * (r - b)) / T
#       unselected_actions = np.concatenate([range(previous_action)], [range(previous_action + 1, self._number_of_arms)])

      phi = (self._estimates - self._estimates[previous_action])
      self._policy = np.divide(np.exp(phi / T), np.sum(np.exp(phi / T)))
      probs = np.exp(self._estimates) / np.exp(self._estimates).sum()
      a = np.random.choice(probs, p=probs)
      action = np.argmax(self._estimates == a)
      return action

    action = np.random.randint(self._number_of_arms)
    return action

  def reset(self):
    """
    Resets all the statistics (estimated rewards and counts) to zero.

    This is also used to initialise these statistics on initialisation.
    """
    self.R_t = 0
    self._policy = np.ones((self._number_of_arms,)) / self._number_of_arms
    self._estimates = np.zeros((self._number_of_arms,))
    self._counts = np.zeros((self._number_of_arms,))


#In order to populate the database once created, from the SQL script:

import sqlite3
connection = sqlite3.connect('expenses_tracker.db')

def scriptexecution(filename):
    with open(filename, 'r') as s:
        sql_script = s.read()
        connection.executescript(sql_script)
    s.closed

scriptexecution('create_values.sql')


"""Command line tool for importing digital objects."""
from __future__ import unicode_literals

import datetime
import fnmatch
import os
import platform
import sys
from uuid import uuid4
import errno

import click
import six

import file_scraper
import premis
from siptools.mdcreator import MetsSectionCreator
from siptools.utils import scrape_file, calc_checksum
from siptools.scripts.premis_event import premis_event, create_premis_event
from siptools.scripts.create_agent import create_agent
from siptools.utils import generate_digest, encode_path

click.disable_unicode_literals_warning = True

ALLOWED_CHARSETS = ['ISO-8859-15', 'UTF-8', 'UTF-16', 'UTF-32']

DEFAULT_VERSIONS = {
    'application/vnd.oasis.opendocument.text': '1.0',
    'application/vnd.oasis.opendocument.spreadsheet': '1.0',
    'application/vnd.oasis.opendocument.presentation': '1.0',
    'application/vnd.oasis.opendocument.graphics': '1.0',
    'application/vnd.oasis.opendocument.formula': '1.0',
}

# For mimetypes that has no version applicable for them.
NO_VERSION = '(:unap)'

# For cases where scraper does not know the version
UNKNOWN_VERSION = '(:unav)'

# Supported bit-level preservation types
SUPPLEMENTARY_TYPES = ["xml_schema"]

@click.command()
@click.argument('filepaths', nargs=-1, type=str)
@click.option(
    '--workspace', type=click.Path(exists=True), default='./workspace/',
    metavar='<WORKSPACE PATH>',
    help="Workspace directory for the metadata files. "
         "Defaults to ./workspace")
@click.option(
    '--base_path', type=click.Path(exists=True), default='.',
    metavar='<BASE PATH>',
    help="Source base path of digital objects. If used, give objects in "
         "relation to this base path.")
@click.option(
    '--skip_wellformed_check', is_flag=True,
    help='Skip file format well-formed check.')
@click.option(
    '--charset', type=str, metavar='<CHARSET>',
    help='Charset encoding of a file.')
@click.option(
    '--original_name', type=str, metavar='<NAME>',
    help='Original name of the file.')
@click.option(
    '--file_format', nargs=2, type=str,
    metavar='<MIMETYPE> <FORMAT VERSION>',
    help='Mimetype and file format version of a file. Use "" for empty '
         'version string.')
@click.option(
    '--format_registry', type=str, nargs=2,
    metavar='<REGISTRY NAME> <REGISTRY KEY>',
    help='The format registry name and key of the digital object.')
@click.option(
    '--identifier', nargs=2, type=str,
    metavar='<IDENTIFIER TYPE> <IDENTIFIER VALUE>',
    help='The identifier type and value of a digital object.')
@click.option(
    '--checksum', nargs=2, type=str,
    metavar='<CHECKSUM ALGORITHM> <CHECKSUM VALUE>',
    help='Checksum algorithm and value of a given file.')
@click.option(
    '--date_created', type=str,
    metavar='<ISO-8601 TIME>',
    help='The actual or approximate date and time the object was created.')
@click.option(
    '--creating_application', nargs=2, type=str,
    metavar='<SOFTWARE NAME> <SOFTWARE VERSION>',
    help='The software and software version that was used to create the '
         'object. Use "" for empty version string.')
@click.option(
    '--order', type=int,
    metavar='<ORDER NUMBER>',
    help='Order number of the digital object.')
@click.option(
    '--event_datetime', type=str,
    metavar='<EVENT DATETIME>',
    help='Timestamp of the event documenting the script actions.')
@click.option(
    '--event_target', type=str,
    metavar='<EVENT TARGET>',
    help='Target for events, if it is not given the package root is used.')
@click.option(
    '--stdout', is_flag=True, help='Print result also to stdout.')
@click.option(
    '--bit_level', is_flag=True,
    help='Mark only for bit-level preservation. If used, then --file_format '
         'is mandatory.')
@click.option(
    '--supplementary', type=click.Choice(SUPPLEMENTARY_TYPES),
    multiple=True, metavar='<SUPPLEMENTARY TYPE>',
    help='Used to mark supplementary files, files that are not part of the '
         'contents per se, but are to be included in the SIP. May be used '
         'multiple times, but currently only "xml_schema" type is supported.')
# pylint: disable=too-many-arguments
def main(**kwargs):
    """Import files to generate digital objects.

    If attributes --charset, --file_format, --identifier, --checksum or
    --date_created are not given, then these are created automatically.

    FILEPATHS: Files or a directory to import, relative path in relation
    to current directory or to --base_path. It depends on your
    attributes whether you may give several files or a single file. For
    example --checksum and --identifier are file dependent metadata, and
    if these are used, then use the script only for one file.
    """
    import_object(**kwargs)
    return 0

def _attribute_values(given_params):
    """
    Give attribute values as a dict for the script.

    :given_params: Arguments as dict.
    :returns: Attribute value dict
    """
    attributes = {
        "filepaths": given_params["filepaths"],
        "workspace": "./workspace/",
        "base_path": ".",
        "skip_wellformed_check": False,
        "charset": None,
        "original_name": None,
        "file_format": (),
        "format_registry": (),
        "identifier": (),
        "checksum": (),
        "date_created": None,
        "creating_application": (),
        "order": None,
        "event_datetime": None,
        "event_target": None,
        "stdout": False,
        "bit_level": None,
        "supplementary": ()
    }
    for key in given_params:
        if given_params[key]:
            attributes[key] = given_params[key]

    if attributes["bit_level"]:
        if not attributes["file_format"]:
            raise ValueError(
                "Argument --file_format is mandatory if --bit_level is given.")
        attributes["skip_wellformed_check"] = True

    return attributes

def import_object(**kwargs):
    """Import files to generate digital objects.

    If attributes charset, file_format, identifier, checksum or
    date_created are not given, then these are created automatically.

    :attributes: Given arguments
                 filepaths: Files or a directory to import
                 workspace: Workspace path
                 base_path: Base path of digital objects
                 skip_wellformed_check: True skips well-formedness
                                        checking
                 charset: Character encoding of a file
                 original_name: Original filename
                 file_format: File format and version (tuple) of a file
                 format_registry: Format registry name and value (tuple)
                 identifier: File identifier type and value (tuple)
                 checksum: Checksum algorithm and value (tuple)
                 date_created: Creation date of a file
                 creating_application: Software and its version that created
                                       the file
                 order: Order number of a file
                 event_datetime: Timestamp of the events. Defaults to
                                 current date YYYY-MM-DD.
                 event_target: The target of the events
                 stdout: True prints output to stdout
                 bit_level: True marks files for bit-level preservation only
                 supplementary: Object type for supplementary files
    """
    attributes = _attribute_values(kwargs)
    date_now = datetime.datetime.utcnow().date().isoformat()

    # Loop files and create premis objects
    files = collect_filepaths(dirs=attributes["filepaths"],
                              base=attributes["base_path"])
    creator = PremisCreator(attributes["workspace"])
    agents = []
    for filepath in files:

        # If the given path is an absolute path and base_path is current
        # path (i.e. not given), relpath will return ../../.. sequences,
        # if current path is not part of the absolute path. In such case
        # we will use the absolute path for filerel and omit base_path
        # relation.
        if attributes["base_path"] not in ['.']:
            filerel = os.path.relpath(filepath, attributes["base_path"])
        else:
            filerel = filepath

        properties = {}
        if attributes["order"] is not None:
            properties['order'] = six.text_type(attributes["order"])
        properties["bit_level"] = attributes["bit_level"]
        properties["supplementary"] = attributes["supplementary"]

        (streams, scraper_info) = creator.add_premis_md(
            filepath, attributes, filerel=filerel, properties=properties)
        for index in scraper_info:
            agents.append(_parse_scraper_tools(scraper_info[index]))

        grade = streams[0]['properties']['grade']

    is_native = grade in (
        file_scraper.defaults.BIT_LEVEL,
        file_scraper.defaults.BIT_LEVEL_WITH_RECOMMENDED
    )

    is_validated = (
        not bool(attributes["skip_wellformed_check"])
        and not is_native
    )

    creator.write(stdout=attributes["stdout"])

    # Resolve event target
    event_target = attributes["event_target"]
    if not event_target:
        event_target = "."

    # Resolve event datetime
    event_datetime = None
    if attributes["event_datetime"] is None:
        event_datetime = date_now
    else:
        event_datetime = attributes["event_datetime"]

    # Create events documenting the technical metadata creation
    _create_events(
        workspace=attributes["workspace"],
        base_path=attributes["base_path"],
        event_datetime=event_datetime,
        event_target=event_target,
        identification_event=not bool(attributes["file_format"]),
        validation_event=is_validated,
        checksum_event=not bool(attributes["checksum"]),
        agents=agents
    )

class PremisCreator(MetsSectionCreator):
    """PREMIS metadata generator for files and streams."""

    def add_premis_md(
            self, filepath, attributes, filerel=None, properties=None):
        """
        Create metadata for PREMIS metadata.

        This method:
        - Scrapes a file
        - Creates PREMIS metadata with amd references for a file
        - Creates PREMIS metadata with amd references for streams in a
          file
        - Returns stream dict from scraper

        :filepath: Full path to file (including base_path)
        :attributes: The following keys
                     skip_wellformed_check: True skips well-formedness
                                            checking
                     charset: Character encoding of a file
                     original_nme: Original filename
                     file_format: File format and version (tuple) of a
                                  file
                     format_registry: Format registry name and value
                                      (tuple)
                     identifier: File identifier type and value (tuple)
                     checksum: Checksum algorithm and value (tuple)
                     date_created: Creation date of a file
        :filerel: Relative path from base_path to file
        :returns: Stream dict and info dict from file-scraper as a tuple
        """
        if not attributes["file_format"]:
            mimetype = "(:unav)"
            version = "(:unav)"
        else:
            mimetype = attributes["file_format"][0]
            version = attributes["file_format"][1]

        (streams, info, grade) = scrape_file(
            filepath=filepath,
            skip_well_check=attributes["skip_wellformed_check"],
            mimetype=mimetype,
            version=version,
            charset=attributes["charset"],
            skip_json=True
        )

        # Add new properties of a file for other script files, e.g.
        # structMap
        streams[0]['properties'] = {'grade': grade}
        if properties:
            streams[0]['properties'].update(properties)

        premis_elem = create_premis_object(filepath, streams, **attributes)
        self.add_md(premis_elem, filerel, given_metadata_dict=streams)
        premis_list = create_streams(streams, premis_elem)

        if premis_list is not None:
            for index, premis_stream in six.iteritems(premis_list):
                self.add_md(
                    premis_stream, filerel, index, given_metadata_dict=streams)

        return (streams, info)

    # pylint: disable=too-many-arguments
    def write(self, mdtype="PREMIS:OBJECT", mdtypeversion="2.3",
              othermdtype=None, section=None, stdout=False,
              file_metadata_dict=None,
              ref_file="import-object-md-references.jsonl"):
        """Write PREMIS metadata."""
        super(PremisCreator, self).write(
            mdtype=mdtype, mdtypeversion=mdtypeversion,
            file_metadata_dict=file_metadata_dict, ref_file=ref_file
        )

def create_streams(streams, premis_file):
    """Create PREMIS objects for streams.

    :streams: Stream dict
    :premis_file: Created PREMIS XML file for the digital object file
    :returns: List of PREMIS etree objects
    """
    if len(streams) < 2:
        return None

    premis_list = {}
    for index, stream in six.iteritems(streams):
        if stream['stream_type'] not in ['video', 'audio']:
            continue

        id_value = six.text_type(uuid4())
        identifier = premis.identifier(
            identifier_type='UUID',
            identifier_value=id_value)
        version = "" if stream['version'] == NO_VERSION else stream['version']
        premis_format_des = premis.format_designation(
            stream['mimetype'], version)
        premis_format = premis.format(child_elements=[premis_format_des])
        premis_objchar = premis.object_characteristics(
            child_elements=[premis_format])
        el_premis_object = premis.object(
            identifier, child_elements=[premis_objchar], bitstream=True)

        premis_list[index] = el_premis_object

        premis_file.append(
            premis.relationship('structural', 'includes', [el_premis_object]))

    return premis_list

def check_metadata(mimetype, version, streams, fname):
    """Validate metadata.

    Check that we will not get None nor (:unav) values to mimetype and
    version. Check that multiple streams are found in
    video containers, and exist only for images or video containers.

    :mimetype: MIME type
    :version: File format version
    :streams: Streams returned from Scraper
    :fname: File name of the digital object
    :raises: ValueError if metadata checking results errors
    """
    if mimetype in [None, "(:unav)"]:
        raise ValueError('MIME type could not be identified for '
                         'file %s' % fname)
    if version in [None, "(:unav)"]:
        raise ValueError('File format version could not be identified for '
                         'file %s' % fname)
    if streams[0]['stream_type'] not in ['videocontainer', 'image'] and \
            len(streams) > 1:
        raise ValueError('The file contains multiple streams which '
                         'is supported only for images and video containers.')
    if streams[0]['stream_type'] in ['videocontainer'] and len(streams) < 2:
        raise ValueError('Video container format without contained streams '
                         'found.')

# pylint: disable=too-many-locals
def create_premis_object(fname, streams, **attributes):
    """
    Create Premis object for given file.

    :fname: File name of the digital object
    :streams: Streams from the Scraper
    :attributes: The following keys:
                 charset: Character encoding of a file
                 original_name: Original filename
                 file_format: File format and version (tuple) of a file
                 format_registry: Format registry name and value (tuple)
                 identifier: File identifier type and value (tuple)
                 checksum: Checksum algorithm and value (tuple)
                 date_created: Creation date of a file
                 creating_application: Software and its version that created
                                       the file
    :returns: PREMIS object as etree
    :raises: ValueError if character set is invalid for text files.
    """
    attributes = _attribute_values(attributes)
    date_created = attributes["date_created"] or creation_date(fname)
    if not attributes["checksum"]:
        attributes["checksum"] = ("MD5", calc_checksum(fname))

    application = None
    application_version = None
    if attributes["creating_application"]:
        (application, application_version) = attributes["creating_application"]

    if streams[0]['stream_type'] == 'text':
        charset = attributes["charset"] or streams[0]['charset']
    else:
        charset = None

    if not attributes["file_format"]:
        if streams[0]["version"] and streams[0]["version"] != UNKNOWN_VERSION:
            format_version = '' if streams[0]["version"] == NO_VERSION else \
                streams[0]["version"]
        else:
            format_version = DEFAULT_VERSIONS.get(streams[0]["mimetype"], None)

        file_format = (streams[0]["mimetype"], format_version)
    else:
        version = "" if attributes["file_format"][1] == NO_VERSION else \
            attributes["file_format"][1]
        file_format = (attributes["file_format"][0], version)

    check_metadata(file_format[0], file_format[1], streams, fname)

    charset_mime = ""
    if charset:
        if charset not in ALLOWED_CHARSETS:
            raise ValueError('Invalid charset.')
        charset_mime = '; charset={}'.format(charset)

    if attributes["identifier"]:
        identifier_type = attributes["identifier"][0]
        identifier_value = attributes["identifier"][1]
    else:
        identifier_type = 'UUID'
        identifier_value = six.text_type(uuid4())

    object_identifier = premis.identifier(
        identifier_type=identifier_type,
        identifier_value=identifier_value
    )

    premis_fixity = premis.fixity(attributes["checksum"][1],
                                  attributes["checksum"][0])
    premis_format_des = premis.format_designation(
        file_format[0] + charset_mime, file_format[1])
    if not attributes["format_registry"]:
        premis_format = premis.format(child_elements=[premis_format_des])
    else:
        premis_registry = premis.format_registry(
            attributes["format_registry"][0],
            attributes["format_registry"][1])
        premis_format = premis.format(child_elements=[premis_format_des,
                                                      premis_registry])
    application_elements = []
    if application:
        application_elements.append(
            premis.creating_application_name(application)
        )
    if application_version:
        application_elements.append(
            premis.creating_application_version(application_version)
        )
    application_elements.append(premis.date_created(date_created))

    premis_create = premis.creating_application(
        child_elements=application_elements
    )
    premis_objchar = premis.object_characteristics(
        child_elements=[premis_fixity, premis_format, premis_create])

    # Create object element
    el_premis_object = premis.object(
        object_identifier,
        original_name=attributes["original_name"],
        child_elements=[premis_objchar])

    return el_premis_object

def collect_filepaths(dirs=None, pattern='*', base='.'):
    """
    Collect file paths recursively from given directory.

    :dirs: Directories from arguments
    :pattern: Filter to match the file names
    :base: Base path (see --base_path)
    :raises: IOError if given path does not exist.
    """
    if dirs is None:
        dirs = ['.']
    files = []

    for directory in dirs:
        directory = os.path.normpath(os.path.join(base, directory))
        if os.path.isdir(directory):
            files += [os.path.join(looproot, filename)
                      for looproot, _, filenames in os.walk(directory)
                      for filename in filenames
                      if fnmatch.fnmatch(filename, pattern)]
        elif os.path.isfile(directory):
            files += [directory]
        else:
            raise IOError

    return files

def creation_date(path_to_file):
    """Return creation date for file.

    Try to get the date that a file was created, falling back to when it
    was last modified if that isn't possible.  See
    http://stackoverflow.com/a/39501288/1709587 for explanation.

    :path_to_file: File path
    :returns: Timestamp for a file
    """
    if platform.system() == 'Windows':
        return datetime.datetime.fromtimestamp(
            os.path.getctime(path_to_file)).isoformat()

    stat = os.stat(path_to_file)
    try:
        return datetime.datetime.fromtimestamp(
            stat.st_birthtime).isoformat()
    except AttributeError:
        # We're probably on Linux. No easy way to get creation dates
        # here, so we'll settle for when its content was last modified.
        return datetime.datetime.fromtimestamp(stat.st_mtime).isoformat()

def _parse_scraper_tools(scraper_info):
    """Helper function to parse the used third party components used
    when identifying files and extracting technical metadata to be used
    as agents when creating events documenting the packaging process.

    :returns: a dict of agent metadata
    """
    agent = {'agent_name': None,
             'detector': False,
             'agent_version': None,
             'tools': None,
             'detail_note': None}

    agent['agent_name'] = scraper_info['class']
    if 'Detector' in scraper_info['class']:
        agent['detector'] = True
    agent['agent_version'] = file_scraper.__version__
    tools = ''
    tools_list = []
    if 'tools' in scraper_info:
        for tool in scraper_info['tools']:
            tools_list.append(tool)
    if tools_list:
        tools = 'Used tools (name-version): ' + ', '.join(tools_list)
        agent['tools'] = tools
    detail_notes = scraper_info['messages'] + scraper_info['errors']
    agent['detail_note'] = ', '.join(detail_notes)

    return agent

def _create_events(
        workspace,
        base_path,
        event_datetime,
        event_target,
        identification_event=False,
        validation_event=False,
        checksum_event=False,
        agents=None):
    """Function to create events documenting the extraction of technical
    metadata as well as the potential message digest calculation and
    the identification and validation of digital objects.

    :workspace: The path to the workspace
    :base_path: Base path (see --base_path)
    :event_datetime: The timestamp for the event
    :event_target: The target of the metadata creation
    :identification_event: Boolean to indicate whether the file formats
                           were identified during the extraction
                           of technical metadata. If True, creates an
                           file format identifiaction event.
    :validation_event: Boolean to indicate whether the digital
                       objects were validated during the extraction
                       of technical metadata. If True, creates a digital
                       object validation event.
    :checksum_event: Boolean to indicate whether the message digest for
                     digital objects were calculated during the
                     extraction of technical metadata. If True, creates
                     a message digest calculation event.
    :agents: A list of the software, as dicts, used to extract the
             metadata
    """
    events = {
        'extraction': {
            'event_type': 'metadata extraction',
            'event_datetime': event_datetime,
            'event_detail': ('Technical metadata extraction as premis '
                             'metadata from digital objects'),
            'event_outcome': 'success',
            'event_outcome_detail': ('Premis metadata successfully created '
                                     'from extracted technical metadata.')},
        'identification': {
            'event_type': 'format identification',
            'event_datetime': event_datetime,
            'event_detail': 'MIME type and version identification',
            'event_outcome': 'success',
            'event_outcome_detail': ('File MIME type and format version '
                                     'successfully identified.')},
        'validation': {
            'event_type': 'validation',
            'event_datetime': event_datetime,
            'event_detail': 'Digital object validation',
            'event_outcome': 'success',
            'event_outcome_detail': ('Digital object(s) evaluated as '
                                     'well-formed and valid.')},
        'checksum': {
            'event_type': 'message digest calculation',
            'event_datetime': event_datetime,
            'event_detail': 'Checksum calculation for digital objects',
            'event_outcome': 'success',
            'event_outcome_detail': ('Checksum(s) successfully calculated '
                                     'for digital object(s).')},
    }

    # Do not create events for steps that haven't been performed by the
    # script
    if not identification_event:
        del events['identification']
    if not validation_event:
        del events['validation']
    if not checksum_event:
        del events['checksum']

    for event_name, event in six.iteritems(events):
        found_event = _find_event(workspace,
                                  event['event_type'],
                                  event['event_datetime'],
                                  event['event_detail'],
                                  event['event_outcome'],
                                  event['event_outcome_detail'])

        if not found_event:

            if event_name == 'checksum':
                create_agent(
                    workspace=workspace,
                    agent_name='file-scraper',
                    agent_version=file_scraper.__version__,
                    agent_type='software',
                    agent_role='executing program',
                    create_agent_file='import-object-%s' % event_name)

            for agent in agents:
                if event_name == 'identification' and not agent['detector']:
                    continue
                if event_name == 'checksum':
                    break
                create_agent(
                    workspace=workspace,
                    agent_name=agent['agent_name'],
                    agent_version=agent['agent_version'],
                    agent_note=agent['tools'],
                    agent_type='software',
                    agent_role='executing program',
                    create_agent_file='import-object-%s' % event_name)

            premis_event(event_type=event['event_type'],
                         event_datetime=event['event_datetime'],
                         event_detail=event['event_detail'],
                         event_outcome=event['event_outcome'],
                         event_outcome_detail=event[
                             'event_outcome_detail'],
                         workspace=workspace,
                         base_path=base_path,
                         event_target=(event_target, ),
                         create_agent_file='import-object-%s' % event_name)

            agent_file = os.path.join(
                workspace, "import-object-%s-AGENTS-amd.json" % event_name)
            try:
                os.remove(agent_file)
            except OSError as exc:  # FileNotFoundError on Python 3
                if exc.errno != errno.ENOENT:
                    raise

def _find_event(workspace,
                event_type,
                event_datetime,
                event_detail,
                event_outcome,
                event_outcome_detail):
    """Helper function to find if a similar event already is created
    by using the digest of the metadata to see if a file already
    exist.
    """

    event = create_premis_event(
        event_type=event_type,
        event_datetime=event_datetime,
        event_detail=event_detail,
        event_outcome=event_outcome,
        event_outcome_detail=event_outcome_detail)

    digest = generate_digest(event)
    expected_filename = encode_path("%s-PREMIS:EVENT-amd.xml" % digest)

    return os.path.exists(os.path.join(workspace, expected_filename))

if __name__ == "__main__":
    RETVAL = main()  # pylint: disable=no-value-for-parameter
    sys.exit(RETVAL)


class Color:

    def __init__(self, red, green, blue):
        self.reset = 0
        self.red = red
        self.green = green
        self.blue = blue

    def __mod__(self, msg):
        """
        Return the msg with color as foreground
        """
        rgb = f"{self.red};{self.green};{self.blue}"
        msg_colored = f"\x1b[38;2;{rgb}m{msg}\x1b[{self.reset}m"
        return msg_colored

    def mod(self, msg):
        return self.__mod__(msg)

white = Color(255, 255, 255)
blue = Color(51, 153, 255)
green = Color(0, 204, 0)
yellow = Color(255, 255, 51)
orange = Color(255, 128, 0)
red = Color(255, 51, 51)
grey = Color(192, 192, 192)
grey_dark_25 = Color(64, 64, 64)
grey_dark_30 = Color(77, 77, 77)
grey_dark_40 = Color(102, 102, 102)
grey_dark_50 = Color(128, 128, 128)
grey_blue = Color(0, 76, 153)


# AdventCode Day 12

from collections import deque

import time

debug = False
directions = {'E': (0, 1), 'S': (-1, 0), 'W': (0, -1), 'N': (1, 0)}

def timing(f):
    def wrap(*args, **kwargs):
        time1 = time.time()
        ret = f(*args, **kwargs)
        time2 = time.time()
        print('{:s} function took {:.3f} ms'.format(f.__name__, (time2 - time1) * 1000.0))
        return ret

    return wrap

@timing
def part1(input):
    x, y = 0, 0
    for dir, value in input:
        if dir == 'F':
            y += current_dir[0][0] * value
            x += current_dir[0][1] * value
        elif dir in directions:
            y += directions[dir][0] * value
            x += directions[dir][1] * value
        elif dir in {'L', 'R'}:
            current_dir.rotate({'L': 1, 'R': -1}[dir] * (value // 90))
    print("part1: manhattan distance:", abs(y) + abs(x))

# Main
# part 1 sample
debug = True
input_list_sample = [(item[0], int(item[1:])) for item in list(open("day12_sample.lst").read().splitlines())]
print(input_list_sample)
current_dir = deque(directions.values())
part1(input_list_sample)  # 25

input_list = [(item[0], int(item[1:])) for item in list(open("day12.lst").read().splitlines())]
print("orders: ", len(input_list))
current_dir = deque(directions.values())
part1(input_list)  # 2228

# part2
@timing
def part2(input):
    y, x = 0, 0
    y_way, x_way = 1, 10
    for action, value in input:
        if action == 'F':
            y += y_way * value
            x += x_way * value
        elif action in directions:
            y_way += directions[action][0] * value
            x_way += directions[action][1] * value
        else:
            for _ in range(0, value, 90):
                y_way, x_way = (x_way, -y_way) if action == 'L' else (-x_way, y_way)
    print("part2: ", abs(y) + abs(x))

part2(input_list_sample)
part2(input_list)


#!/usr/bin/env python3

import rospy
import actionlib
from sc627_helper.msg import ObsData
from geometry_msgs.msg import Twist
from nav_msgs.msg import Odometry
import math
from tf.transformations import euler_from_quaternion
import matplotlib.pyplot as plt
import time
import numpy as np

VEL_MAX = 0.15
ANG_MAX = math.pi/18

rospy.init_node('collision_avoidance', anonymous = True, disable_signals = True)

params = {}

params['vel_d'] = 15
params['ang_d'] = 20
params['obs_radi'] = 2*0.15

params['origin'] = (0.0, 0.0)
params['goal'] = (5.0, 0.0)
params['eps'] = 0.5
params['eps_ang'] = 0.0001

params['angles_cone'] = np.zeros(3)
params['obs_pose_x'] = params['obs_pose_y'] = np.ones(3)
params['obs_pose_vx'] = params['obs_pose_vy'] = np.ones(3)

params['my_pose'] = [0.0, 0.0, 0.0]
params['my_vel'] = [0.0, 0.0]
params['my_omega'] = 0.0

params['samples'] = []
params['feas_pts'] = []

params['dev_min'], params['dev_min_pt'] = 2*math.pi, None
params['dev_max'], params['dev_max_pt'] = 0, None

params['rate'] = rospy.Rate(30)

params['pub_vel'] = rospy.Publisher('/bot_1/cmd_vel', Twist, queue_size = 10)
params['start'] = time.time()
params['time_list'] = []
params['path_list'] = []

def velocity_convert(theta, vel_x, vel_y):
    '''
    Robot pose (x, y, theta)  Note - theta in (0, 2pi)
    Velocity vector (vel_x, vel_y)
    '''

    gain_ang = 1 #modify if necessary

    ang = math.atan2(vel_y, vel_x)
    if ang < 0:
        ang += 2 * math.pi

    ang_err = min(max(ang - theta, - ANG_MAX), ANG_MAX)

    v_lin =  min(max(math.cos(ang_err) * math.sqrt(vel_x ** 2 + vel_y ** 2), - VEL_MAX), VEL_MAX)
    v_ang = gain_ang * ang_err
    return v_lin, v_ang

def callback_odom(data):
    '''
    Get robot data
    '''

    params['my_pose'][0] = data.pose.pose.position.x
    params['my_pose'][1] = data.pose.pose.position.y

    params['my_vel'][0] = data.twist.twist.linear.x
    params['my_vel'][1] = data.twist.twist.linear.y
    params['my_omega'] = data.twist.twist.angular.z

    quaternion = (data.pose.pose.orientation.x, data.pose.pose.orientation.y, data.pose.pose.orientation.z, data.pose.pose.orientation.w)
    _, _, params['my_pose'][2] = euler_from_quaternion(quaternion)

    params['time_list'].append(time.time() - params['start'])
    params['path_list'].append((params['my_pose'][0], params['my_pose'][1]))

def clear_obs_params():
	params['obs_pose_x'] = params['obs_pose_y'] = np.zeros(3)
	params['obs_pose_vx'] = params['obs_pose_vy'] = np.zeros(3)
	# return params

def update_obs_params(obstacle, i):
	params['obs_pose_x'][i], params['obs_pose_y'][i] = obstacle.pose_x, obstacle.pose_y
	params['obs_pose_vx'][i], params['obs_pose_vy'][i] = obstacle.vel_x, obstacle.vel_y

def callback_obs(data):
	i = 0
	for obstacle in data.obstacles:
		update_obs_params(obstacle, i)
		i+=1

def euclid_dist(x1, x2):
	return ((x1[0]-x2[0])**2 + (x1[1]-x2[1])**2)**0.5

def goal_termination():
	return euclid_dist(params['goal'], params['my_pose'][:2]) < params['eps']

def radial_to_cartesian(vel, ang):
	return (params['origin'][0]+vel*np.cos(ang), params['origin'][1]+vel*np.sin(ang))

def gen_samples():
	theta = params['my_pose'][2]
	params['samples'] = []
	for vel in np.linspace(0, VEL_MAX, params['vel_d']):
		for ang in np.linspace(theta-ANG_MAX, theta+ANG_MAX, params['ang_d']):
			if vel!=0:
				params['samples'].append(radial_to_cartesian(vel, ang))

def gen_coll_cone(i):
	origin = params['my_pose'][:2]
	centre_obs = (params['obs_pose_x'][i], params['obs_pose_y'][i])
	obs_dist = ((origin[0]-centre_obs[0])**2+(origin[1]-centre_obs[1])**2)**0.5
	print(i, centre_obs, obs_dist)
	if params['obs_radi'] > obs_dist:
		return math.pi/2
	cone_angle = np.arcsin(params['obs_radi']/obs_dist)
	return cone_angle

def all_coll_cones():
	for i in range(len(params['obs_pose_x'])):
		params['angles_cone'][i] = gen_coll_cone(i)

def ang_vectors(a, b):
	if not (np.linalg.norm(a) and np.linalg.norm(b)):
		return 0
	return np.arccos(np.dot(a, b)/(np.linalg.norm(a)*np.linalg.norm(b)))

def coll_with_cone(pt, i):
	v_rel = (pt[0]-params['obs_pose_vx'][i], pt[1]-params['obs_pose_vy'][i])
	obs_vector = (params['obs_pose_x'][i]-params['my_pose'][0], params['obs_pose_y'][i]-params['my_pose'][1])
	theta = ang_vectors(v_rel, obs_vector)
	return abs(theta) < abs(params['angles_cone'][i])

def open_area(pt):
	for i in range(len(params['obs_pose_x'])):
		if coll_with_cone(pt,i):
			return False
	return True

def filter_points():
	cones = all_coll_cones()
	params['feas_pts'] = []
	for pt in params['samples']:
		if open_area(pt):
			params['feas_pts'].append(pt)

	for pt in params['feas_pts']:
		print(pt)

def opti_point():
	goal_dir = (params['goal'][0] - params['my_pose'][0], params['goal'][1]-params['my_pose'][1])
	params['dev_min'], params['dev_min_pt'] = 2*math.pi, None

	for pt in params['feas_pts']:
		curr_angle = ang_vectors(goal_dir, pt)
		print(curr_angle)
		if curr_angle<params['dev_min']:
			params['dev_min'] = curr_angle
			params['dev_min_pt'] = pt
		print(params['dev_min_pt'])

def proceed(towards_goal=False):
	v_lin, v_ang = velocity_convert(params['my_pose'][2], params['dev_min_pt'][0], params['dev_min_pt'][1])
	vel_msg = Twist()
	vel_msg.linear.x = v_lin
	vel_msg.angular.z = v_ang
	params['pub_vel'].publish(vel_msg)
	params['rate'].sleep()

def avoid_obs():
	while not goal_termination():
		gen_samples()
		filter_points()
		opti_point()
		proceed()

def plotData(time_list, path_list):
    wpX = [x[0] for x in path_list]
    wpY = [x[1] for x in path_list]

    size = min(len(wpX), len(time_list))

    wpX, wpY, time_list = wpX[:size], wpY[:size], time_list[:size]

    plt.plot(time_list, wpX)
    plt.xlabel("Time")
    plt.ylabel("X-coordinate")
    plt.title("X vs T")
    plt.grid()
    plt.show()

    plt.plot(wpX, wpY)
    plt.xlabel("X-coordinate")
    plt.ylabel("Y-coordinate")
    plt.title("Robot Path")
    plt.grid()
    plt.show()

rospy.Subscriber('/obs_data', ObsData, callback_obs)
rospy.Subscriber('/bot_1/odom', Odometry, callback_odom)

avoid_obs()
plotData(params['time_list'], params['path_list'])


# ---
# jupyter:
#   jupytext:
#     text_representation:
#       extension: .py
#       format_name: light
#       format_version: '1.5'
#       jupytext_version: 1.15.2
#   kernelspec:
#     display_name: Python 3 (ipykernel)
#     language: python
#     name: python3
# ---

# # Project Git Metrics for Landscape Analysis
#
# Project git metrics for software landscape analysis related to Cytomining ecosystem.
#
# ## Setup
#
# Set an environment variable named `LANDSCAPE_ANALYSIS_GH_TOKEN` to a [GitHub access token](https://docs.github.com/en/authentication/keeping-your-account-and-data-secure/managing-your-personal-access-tokens). E.g.: `export LANDSCAPE_ANALYSIS_GH_TOKEN=token_here`

# +
import os
from datetime import datetime

import pandas as pd
import pytz
from box import Box
from github import Auth, Github

# set github authorization and client
github_client = Github(
    auth=Auth.Token(os.environ.get("LANDSCAPE_ANALYSIS_GH_TOKEN")), per_page=100
)
# get the current datetime
tz = pytz.timezone("UTC")
current_datetime = datetime.now(tz)

# +
# gather projects data
projects = Box.from_yaml(filename="data/projects.yaml").projects

# check the number of projects
print("number of projects: ", len(projects))
# -

# show the keys available for the projects
projects[0].keys()

def try_to_detect_license(repo):
    """
    Tries to detect the license from GitHub API
    """

    try:
        return repo.get_license().license.spdx_id
    except:
        return None

def try_to_gather_commit_count(repo):
    """
    Tries to detect commit count of repo from GitHub API
    """

    try:
        return len(list(repo.get_commits()))
    except:
        return 0

def try_to_gather_most_recent_commit_date(repo):
    """
    Tries to detect most recent commit date of repo from GitHub API
    """

    try:
        return repo.pushed_at.replace(tzinfo=pytz.UTC)
    except:
        return None

# +
df_projects = pd.DataFrame(
    # create a list of repo data records for a dataframe
    [
        {
            "Project Name": repo.name,
            "GitHub Repository ID": repo.id,
            "Project Homepage": repo.homepage,
            "Project Repo URL": repo.html_url,
            "Project Landscape Category": project.category,
            "GitHub Stars": repo.stargazers_count,
            "GitHub Forks": repo.forks_count,
            "GitHub Subscribers": repo.subscribers_count,
            "GitHub Open Issues": repo.get_issues(state="open").totalCount,
            "GitHub Contributors": repo.get_contributors().totalCount,
            "GitHub License Type": try_to_detect_license(repo),
            "GitHub Description": repo.description,
            "GitHub Topics": repo.topics,
            # gather org name if it exists
            "GitHub Organization": repo.organization.login
            if repo.organization
            else None,
            "GitHub Network Count": repo.network_count,
            "GitHub Detected Languages": repo.get_languages(),
            "Date Created": repo.created_at.replace(tzinfo=pytz.UTC),
            "Date Most Recent Commit": try_to_gather_most_recent_commit_date(repo),
            # placeholders for later datetime calculations
            "Duration Created to Most Recent Commit": "",
            "Duration Created to Now": "",
            "Duration Most Recent Commit to Now": "",
            "Repository Size (KB)": repo.size,
            "GitHub Repo Archived": repo.archived,
        }
        # make a request for github repo data with pygithub
        for project, repo in [
            (
                project,
                github_client.get_repo(
                    project.repo_url.replace("https://github.com/", "")
                ),
            )
            for project in projects
        ]
    ]
)

# show the result
df_projects

# +
# calculate time deltas
df_projects["Duration Created to Most Recent Commit"] = (
    df_projects["Date Most Recent Commit"] - df_projects["Date Created"]
)
df_projects["Duration Created to Now"] = current_datetime - df_projects["Date Created"]
df_projects["Duration Most Recent Commit to Now"] = (
    current_datetime - df_projects["Date Most Recent Commit"]
)

# create a years count for project time duration
df_projects["Duration Created to Now in Years"] = (
    df_projects["Duration Created to Now"].dt.days / 365
)

# show the result
df_projects
# -

# filter the results
df_projects = df_projects[
    # filter projects which are < 50 KB
    df_projects["Repository Size (KB)"]
    >= 50
    # filter projects which have been archived
    & ~df_projects["GitHub Repo Archived"]
][  # filter projects which have no detected programming languages
    df_projects["GitHub Detected Languages"].str.len()
    > 0
    # Drop duplicates based on github repository id
].drop_duplicates(
    subset="GitHub Repository ID"
)
df_projects.tail()

# negate this duration value for sorting descendingly,
# with projects that have been more recently changed sorting to the top
df_projects["Negative Duration Most Recent Commit to Now"] = -df_projects[
    "Duration Most Recent Commit to Now"
]
df_projects = df_projects.sort_values(
    by=[
        "GitHub Stars",
        "GitHub Subscribers",
        "GitHub Contributors",
        "GitHub Forks",
        "GitHub Open Issues",
        "Negative Duration Most Recent Commit to Now",
        "Duration Created to Most Recent Commit",
    ],
    ascending=False,
)
df_projects

# export to parquet for later use
df_projects.to_parquet("data/project-github-metrics.parquet")


import random
from enum import Enum

class Orientation(Enum):
    Right = 0
    Down = 1
    Left = 2
    Up = 3

    def turn(self, clockwise):
        orientations = list(Orientation)
        index = (self.value + (1 if clockwise else -1)) % len(orientations)
        return orientations[index]

class Cell:
    def __init__(self, row, col):
        self.row = row
        self.col = col
        self.color = 0 if random.random() < 0.5 else 1
        # next cell based on orientation order: right, down, left, up
        self.direction = [(0, 1), (1, 0), (0, -1), (-1, 0)]

    def flip(self):
        self.color = 1 - self.color

    def iswhite(self):
        return self.color == 0

    def get_loc(self):
        return (self.row, self.col)

    def next_loc(self, orientation):
        r, c = self.direction[orientation.value]
        return (self.row + r, self.col + c)

    def __str__(self):
        return f"({self.row}, {self.col}) {self.color}"

class Ant:
    def __init__(self):
        self.cell = Cell(0, 0)
        self.orientation = Orientation.Right
        self.traces = {}
        self.traces[self.cell.get_loc()] = self.cell
        self.bounds = [0, 0, 0, 0]      # top, bottom, left, right

    def move(self):
        self.turn_orientation()
        print(self.cell, self.orientation.name)
        self.update_cell()

    def turn_orientation(self):
        clockwise = self.cell.iswhite()
        self.orientation = self.orientation.turn(clockwise)

    def update_cell(self):
        self.cell.flip()
        loc = self.cell.next_loc(self.orientation)
        if loc not in self.traces:
            self.traces[loc] = Cell(loc[0], loc[1])
        self.cell = self.traces[loc]
        self.update_bounds(loc)

    def update_bounds(self, loc):
        r, c = loc
        if r < self.bounds[0]:
            self.bounds[0] = r
        elif r > self.bounds[1]:
            self.bounds[1] = r
        if c < self.bounds[2]:
            self.bounds[2] = c
        elif c > self.bounds[3]:
            self.bounds[3] = c

    def print_board(self):
        top, bottom, left, right = self.bounds
        board = []
        for i in range(top, bottom + 1):
            row = []
            for j in range(left, right + 1):
                cell = self.traces.get((i, j), Cell(i, j))
                row.append(str(cell.color))
            board.append(' '.join(row))
        print('\n'.join(board))

def langtons_ant(k):
    ant = Ant()
    for _ in range(k):
        ant.move()
    print(ant.cell)
    ant.print_board()

langtons_ant(6)


def parse(filepath, recursion=False):
    with open(filepath, 'r') as f:
        lines = f.read().splitlines()

        grid = dict()
        portals = dict()

        for y in range(len(lines)):
            for x in range(len(lines[y])):
                char = lines[y][x]
                if(char == '.'):
                    grid[(x,y)] = []
                    neighboors = get_neighboors((x,y))
                    for x2,y2 in neighboors:
                        nb = lines[y2][x2]
                        if(nb == '.'):
                            grid[(x,y)].append((x2,y2,0))
                        elif('A' <= nb <= 'Z'):
                            second = lines[y2*2-y][x2*2-x]
                            portal = nb + second if x2 > x or y2 > y else second + nb
                            jump = portals.get(portal, None)
                            if (jump):
                                grid[(x,y)].append(jump)
                                grid[(jump[0], jump[1])].append((x,y, jump[2]*-1))
                            else:
                                if(recursion):
                                    if(portal == 'AA' or portal == 'ZZ'):
                                        portals[portal] = (x,y,0)
                                    elif(x2 == 1 or y2 == 1 or x2 == len(lines[y])-2 or y2 == len(lines)-2):
                                        portals[portal] = (x,y,1)
                                    else:
                                        portals[portal] = (x,y,-1)
                                else:
                                    portals[portal] = (x,y, 0)
    return grid, portals['AA'], portals['ZZ']

def get_neighboors(position):
    x,y = position
    return [(x-1,y), (x+1, y), (x, y-1), (x,y+1)]

def maze():
    grid, src, dst = parse("input/day20.data")
    bfs(grid, src, dst)

def bfs(board, src, dst):
    queue = list()
    queue.append((0, src))
    visited = set()

    while(src != dst):
        steps, src = queue.pop(0)
        if (src not in visited):
            visited.add(src)
            sx,sy,sz = src
            for nx,ny,nz in board[(sx,sy)]:
                if(nz+sz >= 0):
                    queue.append((steps + 1, (nx,ny,nz+sz)))
    print(steps)

def recursion():
    grid, src, dst = parse("input/day20.data", True)
    bfs(grid, src, dst)

if __name__ == "__main__":
    maze()
    recursion()


def user_ip(nums):
    if len(nums) == 4:
        for num in nums:
            if not num.isdigit():
                print(f'{num} - это не целое число')
                return False
            if int(num) > 255:
                print(f'{num} превышает 255.')
                return False
            elif int(num) < 0:
                print(f'{num} меньше 0.')
                return False
    else:
        print('Адрес — это четыре числа, разделённые точками.')
        return False
    return True

input_ip = input('Введите IP:').split('.')
ip_status = user_ip(input_ip)
if ip_status:
    print('IP-адрес корректен')