# -*- coding: utf-8 -*-
import os
import logging
import json
import time

import click
import dotenv
import googlemaps

import pandas as pd

from biom import load_table
from utils import biom_summarize_table

@click.command()
@click.option('--min-counts', default=1, type=int)
def main(min_counts):
    """
    Runs data processing scripts to turn raw data (from data/raw)
    into cleaned data ready to be analyzed (saved in data/processed).
    """
    logger = logging.getLogger(__name__)
    logger.info('making final data set from raw data')

    # Process population per state
    print("Processing population file")
    raw_pop_fp = os.path.join(raw_dir, 'PEP_2016_PEPANNRES.csv')
    pop = pd.read_csv(raw_pop_fp, dtype={'GEO.id2': str})
    pop.set_index('GEO.id2', drop=True, inplace=True)
    geo_ids = ['{:02d}'.format(i+1) for i in range(56)]  # states ids range 01 to 56
    geo_ids = list(set(geo_ids).intersection(set(pop.index)))  # remove missing vals
    geo_ids.sort()
    pop = pop.loc[geo_ids]
    new_cols = {'respop7{}'.format(year) : str(year) for year in range(2010, 2017)}
    new_cols['GEO.display-label'] = 'state'
    pop.rename(columns=new_cols, inplace=True)
    new_cols = list(new_cols.values())
    new_cols.sort()
    pop = pop[new_cols]
    pop.set_index('state', drop=True, inplace=True)
    processed_pop_fp = os.path.join(processed_dir, 'state-pop-2010-2016.csv')
    pop.to_csv(processed_pop_fp)

    # Build interim metadata
    print("Building interim metadata file")
    raw_metadata_fp = os.path.join(raw_dir, 'Master_dataset_20Dec13.csv')
    df = pd.read_csv(raw_metadata_fp, dtype={'Conf_code': str},
            usecols=['Conf_code', 'latitude', 'longitude'])
    new_cols = {
            'Conf_code': '#SampleID',  # necessary for biom add-metadata to work
            'latitude': 'lat',
            'longitude': 'lon'
            }
    df.rename(columns=new_cols, inplace=True)
    df.set_index('#SampleID', drop=True, inplace=True)
    df = df[~df.index.duplicated(keep='first')]  # remove duplicate ids
    df.dropna(inplace=True)  # remove samples with missing lat or lon

    # Query Google Maps API for reverse geocoding: use a point's lat, lon to find
    # address which includes country, state, county, city, postal_code, ...

    # First we retrieve the Google Maps API Key stored in .env in project_dir
    # You must edit the .env file to include your own Google API key! More info:
    # https://developers.google.com/maps/documentation/geocoding/get-api-key
    dotenv.load_dotenv(os.path.join(project_dir, '.env'))
    gmaps = googlemaps.Client(key=os.environ.get('GOOGLE_API_KEY'))

    # Next we process the results array returned by Google Maps into usable
    # pieces of the address, specifically, all names in area_names
    area_names = [
            'country', 'administrative_area_level_1',
            'administrative_area_level_2', 'locality'
            ]
    areas = pd.DataFrame(index=df.index, columns=area_names, dtype=str)
    area_names = set(area_names)
    print("Querying Google Maps API for city, county, state of each point")
    for id_, lat, lon in df.itertuples():
        print("Retrieving areas for sample point w/ id: {}".format(id_))
        time.sleep(0.15)  # 10 queries per second (Google Maps API requires <50 qps)
        response = gmaps.reverse_geocode((lat, lon))
        result = response[0]  # extract areas from top result
        for address_component in result['address_components']:
            area_name = set(address_component['types']).intersection(area_names)
            if area_name:
                areas.set_value(id_, area_name, address_component['long_name'])

    # Finish by replacing some of the names with aliases specific to USA data
    # and concatenate
    area_alias = {
            'administrative_area_level_1': 'state',
            'administrative_area_level_2': 'county',
            'locality': 'city'
            }
    areas.rename(columns=area_alias, inplace=True)

    df = pd.concat([df, areas], axis=1)

    interim_metadata_fp = os.path.join(interim_dir, 'metadata.txt')
    df.to_csv(interim_metadata_fp, sep='\t')

    # Split each biom on location of sample collection: outdoor vs. indoor
    md = df.to_dict(orient='index')
    biom_src = {
            'ITS': 'ITS_otu_table_wTax.biom',
            '16S': '16S_otu_table_wTax.biom'
        }
    loc_name = {
            'O': 'outdoor',
            'I': 'indoor'
        }
    is_not_control = lambda values, id_, md: any([id_.endswith('.' + loc) for loc in loc_name.keys()])
    group_by_loc = lambda id_, md: id_[-1]
    biom_files = []

    print("Processing raw BIOM files to interim files")
    for barcode_sequence, biom_file in list(biom_src.items()):
        raw_biom_fp = os.path.join(raw_dir, biom_file)
        summary_file = barcode_sequence + '-summary.txt'
        biom_summarize_table(raw_biom_fp, os.path.join(raw_dir, summary_file))

        table = load_table(raw_biom_fp)
        table.filter(is_not_control, axis='sample', inplace=True)
        loc_tables = table.partition(group_by_loc, axis='sample')

        for loc, loc_table in loc_tables:
            interim_biom_file = '{0}-{1}.biom'.format(barcode_sequence, loc_name[loc])
            biom_files.append(interim_biom_file)

            # Remove location tags from home ID and add sample metadata
            sample_ids = loc_table.ids(axis='sample')
            for i, id_ in enumerate(sample_ids):
                sample_ids[i] = id_.partition('.')[0]
            loc_table.add_metadata(md, axis='sample')

            interim_biom_fp = os.path.join(interim_dir, interim_biom_file)
            generated_by = "Transformation of {0} applied by {1}".format(raw_biom_fp, __file__)
            with open(interim_biom_fp, 'w') as f:
                loc_table.to_json(generated_by=generated_by, direct_io=f)

            # Also produce biom summary text file
            summary_file = interim_biom_file.partition('.')[0] + '-summary.txt'
            biom_summarize_table(interim_biom_fp, os.path.join(interim_dir, summary_file))

    # Make processed biom data (interim biom data filtered by a few conditions)

    # If we examine the interim summary files we notice there are many
    # samples with very few counts. Let's filter by samples with a
    # minimum number of sequence reads, given by the min_count option
    at_or_exceeds_min_count = lambda values, id_, md: sum(values) >= min_counts

    # We also remove any samples that do not belong to the continental US.
    # In other words, remove samples from Alaska and Hawaii.
    in_continental_usa = lambda values, id_, md: md['state'] not in ['Alaska', 'Hawaii']

    print("Processing interim BIOM files to final files")
    for biom_file in biom_files:
        interim_biom_fp = os.path.join(interim_dir, biom_file)
        table = load_table(interim_biom_fp)
        table.filter(at_or_exceeds_min_count, axis='sample', inplace=True)
        table.filter(in_continental_usa, axis='sample', inplace=True)

        processed_biom_fp = os.path.join(processed_dir, biom_file)
        generated_by = "Transformation of {0} applied by {1}".format(interim_biom_fp, __file__)
        with open(processed_biom_fp, 'w') as f:
            table.to_json(generated_by=generated_by, direct_io=f)

        # Also produce biom summary text files
        summary_file = biom_file.partition('.')[0] + '-summary.txt'
        biom_summarize_table(processed_biom_fp, os.path.join(processed_dir, summary_file))

    print("Done.")

if __name__ == '__main__':
    log_fmt = '%(asctime)s - %(name)s - %(levelname)s - %(message)s'
    logging.basicConfig(level=logging.INFO, format=log_fmt)

    # Define paths to various data directories
    project_dir = os.path.join(os.path.dirname(__file__), os.pardir, os.pardir)
    data_dir = os.path.join(project_dir, 'data')
    raw_dir = os.path.join(data_dir, 'raw', 'national')
    interim_dir = os.path.join(data_dir, 'interim', 'national')
    processed_dir = os.path.join(data_dir, 'processed', 'national')

    main()


import os
import math
import mainWindow
import numpy as np
import pandas as pd
import data_read

class mptime():
    def __init__(self, frequency, poseNum, numbers, threshold):
        self.frequency = frequency
        self.poseNum = poseNum
        self.numbers = numbers
        self.threshold = threshold
        self.dataPath = r'.\fileSelect.txt'
        self.refreshPath = r'.\refreshd.txt'
        self.pathResult = r'.\result.txt'
    def calculate(self):
        with open(self.dataPath, 'r') as dic:
            path = dic.read()
        absPath = {}
        #读取目录下的所有需要文件
        #寻找测试数据的目录
        for i in range(self.numbers):
            filename = str(i+1)+'.txt'
            for fileName in os.listdir(path):
                if fileName == filename:
                    absPath[i] = os.path.join(path, fileName)
        ls = {}
        #将测量结果存入字典
        for i in range(self.numbers):
            dataTest = data_read.dataRead(absPath[i])
            dataTest.txtRead()
            ls[i] = dataTest.data
        #计算速度
        velocity = {}
        for i in range(self.numbers):
            velocity[i] = []
            for j in range(len(ls[i])-1):
                velocity[i].append(np.linalg.norm(ls[i][j+1]-ls[i][j])*self.frequency/1000)
        #计算加速度
        acceleration = {}
        for i in range(self.numbers):
            acceleration[i] = []
            for j in range(len(velocity[i])-5):
                acceleration[i].append((velocity[i][j+5] - velocity[i][j])*self.frequency)

        #根据速度和加速度将点位分割
        poses = []
        for i in range(self.numbers):
            pStart = 0
            pStop = 0
            posei = {}
            for j in range(self.poseNum):
                signStart = 0    #标志位
                signStop = 0
                for k in range(pStop, len(velocity[i])):
                    if velocity[i][k] > 0.04 and acceleration[i][k+1]+acceleration[i][k] > 0 and signStart == 0:
                        pStart = k
                        signStart = 1
                    if signStop == 0 and signStart == 1 and velocity[i][k] < 0.04:
                        pStop = k+1000
                        signStop = 1
                posei[j] = [pStart, pStop]
            poses.append(posei)
        #分别计算位置稳定时间
        pTime = []
        for i in range(self.numbers):
            pTimei = []
            for j in range(self.poseNum):
                for k in range(poses[i][j][1], poses[i][j][0], -1):
                   if np.linalg.norm(ls[i][k]-ls[i][poses[i][j][1]]) > self.threshold:
                       tm = (k - poses[i][j][0]  + 1) / self.frequency
                       pTimei.append(tm)
                       break
            pTime.append(pTimei)
        pTimeAve = []
        for i in range(self.poseNum):
            tmm = 0
            for j in range(self.numbers):
                tmm += pTime[j][i]
            pTimeAve.append(tmm/self.numbers)
        #将结果写入文件
        r = open(self.pathResult, 'a+')
        r.truncate(0)
        r.write('***最小定位时间***\n')
        for i in range(self.poseNum):
            r.write('点位：P1+%d的最小定位时间为：%.4fs；\n'
                    % (i+1, pTimeAve[i]))
        r.flush()
        r.close()
        ref = open(self.refreshPath, 'a+')
        ref.truncate(0)
        ref.write('1')
        ref.flush()
        ref.close()


# Advent of code Year 2020 Day 11 solution
# Author = ?
# Date = December 2020
import copy

with open((__file__.rstrip("code.py") + "input.txt"), 'r') as input_file:
    input = input_file.read()

grid = input.split('\n')
grid = [list(line) for line in grid]
grid_rows = len(grid)
grid_cols = len(grid[0])
directions = [(i, j) for i in [-1, 0, 1] for j in [-1, 0, 1]]
directions.remove((0, 0))
FLOOR = '.'
EMPTY = 'L'
OCCUPIED = '#'

def print_grid(_grid):
    for r in range(len(_grid)):
        for c in range(len(_grid[0])):
            print(_grid[r][c], end='')
        print()

def is_valid_indexing(r, c):
    return 0 <= r < grid_rows and 0 <= c < grid_cols

def get_neighbours(_grid, _row, _col):
    neighbours = [_grid[_row + row][_col + col]
                  if is_valid_indexing(_row + row, _col + col)
                  else None
                  for (row, col) in directions]
    neighbours = list(filter(lambda x: x is not None, neighbours))
    return neighbours

def get_visible_seats(_grid, _row, _col):
    visible_seats = []
    for (r, c) in directions:
        m = 1
        while is_valid_indexing(_row + r * m, _col + c * m):
            seat = _grid[_row + r * m][_col + c * m]
            if seat == EMPTY:
                visible_seats.append(EMPTY)
                break
            if seat == OCCUPIED:
                visible_seats.append(OCCUPIED)
                break
            m += 1
    return visible_seats

def count_occupied_seats(_grid, neighbours_count_func, neighbours_limit):
    changes = 1
    while changes > 0:
        grid_copy = copy.deepcopy(_grid)
        changes = 0
        for _row in range(len(grid_copy)):
            for _col in range(len(grid_copy[0])):
                neighbours = neighbours_count_func(grid_copy, _row, _col)
                seat = grid_copy[_row][_col]
                if seat == EMPTY:
                    if neighbours.count(OCCUPIED) == 0:
                        _grid[_row][_col] = OCCUPIED
                        changes += 1
                elif seat == OCCUPIED:
                    if neighbours.count(OCCUPIED) >= neighbours_limit:
                        _grid[_row][_col] = EMPTY
                        changes += 1
    return [elem for line in _grid for elem in line].count(OCCUPIED)

def z1():
    global grid
    grid_copy = copy.deepcopy(grid)
    return count_occupied_seats(grid_copy, get_neighbours, 4)

def z2():
    global grid
    grid_copy = copy.deepcopy(grid)
    return count_occupied_seats(grid_copy, get_visible_seats, 5)

print("Part One : " + str(z1()))

print("Part Two : " + str(z2()))


'''
Created on Feb 4, 2011

@author: rca
'''

import multiprocessing
import os

class MontySolrTarget(object):
    """Simple class that represents the target that is registered
    by handlers

    It has a str id, which is made of <sender>:<recipient>
        eg. SolrRequestHandler:answer_query

        sender = the Java side class (usually)
        recipient = the Python side function name (always)

    Where sender may be empty, which means it can be any sender
        eg *:answer_query

    """
    def __init__(self, recipient, callable, sender='*'):
        self._recipient = recipient
        self._sender = sender
        self._target = callable
    def getTarget(self):
        return self._target
    def getMessageId(self):
        return '%s:%s' % (self._sender, self._recipient)

def make_targets(*args, **kwargs):
    """Creates a list of targets, the keys are the
    recipient names and the value the callable that
    implements them"""
    targets = []
    assert len(args) % 2 == 0
    i = 0
    while i < len(args):
        name = args[i]
        sender = None
        if ':' in name:
            sender, name = name.split(':')
        if sender:
            targets.append(MontySolrTarget(name, args[i+1], sender=sender))
        else:
            targets.append(MontySolrTarget(name, args[i+1]))
        i += 2

    for k,v in kwargs.items():
        targets.append(MontySolrTarget(k, v))
    return targets

def get_numcpus():
    from montysolr import config
    num_cpus = 0
    global api_calls
    # start multiprocessing with that many processes in the pool
    if str(config.MONTYSOLR_MAX_WORKERS) == '-1':
        try:
            num_cpus = multiprocessing.cpu_count()
        except:
            num_cpus = 1
    elif int(config.MONTYSOLR_MAX_WORKERS) > 1:
        num_cpus = int(config.MONTYSOLR_MAX_WORKERS)
    return num_cpus

def multiprocess_aware(original_func):
    def new_func(func_name, *args, **kwargs):
        kwargs['__remote_call'] = True
        return original_func(func_name, *args, **kwargs)
    return new_func


import collections
class Solution(object):
    def intersect(self, nums1, nums2):
        """
        :type nums1: List[int]
        :type nums2: List[int]
        :rtype: List[int]
        """
        if len(nums2) > len(nums1): return self.intersect(nums2, nums1)

        c1 = collections.Counter(nums1)
        c2 = collections.Counter(nums2)

        res = []
        for key,value in c2.iteritems():
            if key in c1:
                minC = min(value, c1[key])
                res += [key]*minC

        return res


from rich.progress import Progress, BarColumn, TextColumn
from textual.widgets import Static
# > Typing
from typing import Optional
# > Local Import's
from ..functions import get_bar_status

class IndeterminateProgress(Static):
    def __init__(self, getfunc=get_bar_status, fps: int=15):
        super().__init__("", classes="indeterminate-progress-bar")
        self._bar = Progress(BarColumn(), TextColumn("{task.description}"))
        self._task_id = self._bar.add_task("", total=None)
        self._fps = fps
        self._getfunc = getfunc

    def on_mount(self) -> None:
        self.update_render = self.set_interval(1/self._fps, self.update_progress_bar)

    async def upgrade_task(self, description: str="", completed: Optional[float]=None, total: Optional[float]=None) -> None:
        self._bar.update(self._task_id, total=total, completed=completed, description=description)

    async def update_progress_bar(self) -> None:
        d, c, t = await self._getfunc()
        if self._bar.columns[0].bar_width != (self.size[0]-len(d)-1):
            self._bar.columns[0].bar_width = self.size[0]-len(d)-1

        await self.upgrade_task(completed=c, total=t, description=d)
        self.update(self._bar)


from collections import defaultdict
class Solution:
    def commonChars(self, words: List[str]) -> List[str]:

        commonDict = defaultdict(int)
        size = len(words)

        for letter in words[0]:
            commonDict[letter] += 1

        for i in range(1,size):
            tempDict = defaultdict(int)

            for letter in words[i]:
                tempDict[letter] += 1

            keys = list(commonDict.keys())

            for key in keys:
                if key not in tempDict:
                    commonDict.pop(key)
                elif tempDict[key] < commonDict[key]:
                    commonDict[key] = tempDict[key]

        result = []
        for key,value in commonDict.items():
            for i in range(value):
                result.append(key)
        return result


# encoding: utf-8

from marrow.mongo.core import Document, Field

class Example(Document):
	name = Field()
	age = Field()

EXAMPLE = Example("Alice", 27)

TRUTHY_CASES = [
		# Comparison

		# $eq
		(EXAMPLE.name == "Alice"),
		(EXAMPLE.age == 27),

		# $gt
		(EXAMPLE.name > "Aa"),
		(EXAMPLE.age > 18),

		# $gte
		# $lt
		# $lte
		# $ne
		# $in
		# $nin

		# Logical

		# $or
		# $and
		# $not
		# $nor

		# Element

		# $exists
		# $type

		# Evaluation

		# $mod
		# $regex
		# $text
		# $where

		# Geospatial

		# $geoWithin
		# $geoIntersects
		# $near
		# $nearSphere

		# Array

		# $all
		# $elemMatch
		# $size

		# Bitwise

		# $bitsAllSet
		# $bitsAnySet
		# $bitsAllClear
		# $bitsAnyClear

		# Comments

		# $comment

	]

FALSY_CASES = [
	]


'''Author: Anandita Ashwath
    Description:
        Read raw data from multiple CSV files, then pre-processing the data
        and finally store the data to file to re-use the data for exploring
        and clustering. Adapted from the code written by Tam M Pham.
'''

import os
import glob
import numpy as np
import pandas as pd
import time

def count_check_in(diff):
    if (diff > 0):
        return diff
    return 0

def count_check_out(diff):
    if (diff < 0):
        return abs(diff)
    return 0

def refine_min(min):
    if min < 10: return "00"
    elif min < 20: return "10"
    elif min < 30: return "20"
    elif min < 40: return "30"
    elif min < 50: return "40"
    elif min < 60: return "50"
    else:
        return np.nan

start = time.time()
#Reading all the csv files from the folder using glob moduleand then merging into one folder
os.chdir("/Users/TEMP.ANANDITA.000/Desktop/Dublinbikes")
extension = 'csv'
all_filenames = [i for i in glob.glob('*.{}'.format(extension))]
df = pd.concat([pd.read_csv(f) for f in all_filenames ])
os.chdir("/Users/TEMP.ANANDITA.000/Desktop/Dublinbikes")
print("Change back to root directory -> {0}".format(os.getcwd()))
df = df.loc[:, ~df.columns.str.contains('^Unnamed')]
df = df.dropna()
df = df.drop_duplicates(subset=["number", "last_update", "available_bike_stands"], keep='first')
df = df.reset_index(drop=True)
df["last_update"] = pd.to_datetime(df["last_update"], unit='ms', utc=True)
df["date"] = df["last_update"].dt.strftime('%Y-%m-%d')
df["time"] = df["last_update"].apply(lambda x: "%s:%s:00" % (x.strftime('%H'), refine_min(x.minute)))
df["weekday"] = df["last_update"].dt.strftime("%a")
df.sort_values(by=["number", "date", "time"], inplace=True)
df["last_available_stands"] = df.groupby(["number", "name", "address"])["available_bike_stands"].shift(1)
df["last_available_stands"] = df.apply(
    lambda row: row["available_bike_stands"] if np.isnan(row["last_available_stands"]) else row["last_available_stands"],
    axis=1
)
df["number"] = df.number.astype(np.int64)
df["bike_stands"] = df.bike_stands.astype(np.int64)
df["available_bike_stands"] = df.available_bike_stands.astype(np.int64)
df["last_available_stands"] = df.last_available_stands.astype(np.int64)
df["diff"] = df.available_bike_stands - df.last_available_stands
df["check_in"] = df["diff"].apply(lambda x: count_check_in(x))
df["check_out"] = df["diff"].apply(lambda x: count_check_out(x))
df = df.groupby(["number", "name", "address", "date", "time", "weekday"]).agg({"bike_stands": "min",
        "diff": "sum", "available_bike_stands": "last", "check_in": "sum", "check_out": "sum"}).reset_index()
df = df.rename(columns={"number": "Number", "name": "Name", "address": "Address", "date": "Date", "time": "Time", "weekday": "Weekday", "bike_stands": "Bike Stands", "diff": "Diff", "available_bike_stands": "Available Stands", "check_in": "Check In", "check_out": "Check Out"})

df.to_csv( "df.csv", index=False, encoding='utf-8-sig')
end = time.time()
print("Done preparation after {} seconds".format((end - start)))


import matplotlib.pyplot as plt
from sklearn import datasets
from sklearn.model_selection import train_test_split
import numpy as np

# Pone una pausa hasta que se pulse una tecla
def espera():
    input("-------------Pulsa cualquier tecla para continuar.---------------")
    plt.close()

# Parte 1:
# - Lee la base de datos de iris que hay en scikit-learn
# - Obtiene las caracterı́sticas (datos de entrada X) y la clase (y)
# - Se queda con las dos últimas caracterı́sticas (2 últimas columnas de X)
# - Visuliza con un Scatter Plot los datos, coloreando cada clase
# con un color diferente (con rojo, verde y azul), e indicando con
# una leyenda la clase a la que corresponde cada color.
def ej1():
    # Importamos la base de datos Iris
    iris = datasets.load_iris()

    # Mostramos característica y clases
    print("Características: ")
    print(iris.feature_names)

    print("Clases:")
    print(iris.target_names)

    # Nos quedamos con las dos últimas características
    X = iris.data[:, -2:]
    y = iris.target

    colores = {0: 'red', 1: 'green', 2: 'blue'}

    # Visualizar los datos en un scatter plot
    _, ax = plt.subplots()

    # Para cada clase:
    for clase, nombre in enumerate(iris.target_names):
        # Obten los miembros de la clase
        miembros = X[iris.target == clase]

        # Representa en scatter plot
        ax.scatter(miembros[:, 0], miembros[:, 1], c=colores[clase], label=nombre)
        # Añadimos la leyenda

    ax.legend()

    # Visualizamos la gráfica
    plt.show()

# Parte 2:
# - Separa en training (80 % de los datos) y test (20 %) aleatoriamente
# conservando la proporción de elementos en cada clase tanto en
# training como en test.
def ej2():
    # Importamos la base de datos Iris
    iris = datasets.load_iris()
    # Cargamos los datos
    X = iris.data
    y = iris.target

    # Separamos en 80% training y 20% test aleatoriamente
    # stratify = y hace que se mantenga la proporcion de elementos en cada clase
    X_train, X_test, y_train, y_test = train_test_split(X, y, train_size = 0.8, shuffle = True, stratify = y)

    # Mostramos el número de elementos de cada conjunto para comprobar
    # que se ha separado correctamente los conjuntos
    print("Número de ejemplos en la base de datos Iris: ")
    print(X.shape[0])
    print("Número de elementos en el conjunto de entrenamiento: ")
    print(X_train.shape[0])
    print("Número de elementos en el conjunto de test: ")
    print(X_test.shape[0])

    # Comprobamos que las proporciones de elementos de cada clase se mantiene
    for clase, nombre in enumerate(iris.target_names):
        proporcion = len(y[y == clase]) / y.shape[0]
        train_prop = len(y_train[y_train == clase]) / y_train.shape[0]
        test_prop = len(y_test[y_test == clase]) / y_test.shape[0]

        print("Proporción de la clase", nombre)
        print("Base de datos Iris", proporcion)
        print("Conjunto training", train_prop)
        print("Conjunto test", test_prop)

# Parte 3:
# - Obtiene 100 valores equiespaciados entre 0 y 2pi
# - Obtiene el valor de sin(x), cos(x) y sin(x)+cos(x) para los 100 valores anteriores
# - Visualiza las tres curvas anteriores con lineas discontinuas en negro, azul y rojo
def ej3():
    # Obtenemos 100 valores equiespaciados entre 0 y 2pi
    x = np.linspace(0, 2 * np.pi, 100)

    # Obtenemos el valor de sin(x) y cos(x) para posteriormente construir las tres funciones
    seno = np.sin(x)
    coseno = np.cos(x)

    # Construimos la gráfica de las tres funciones con los requisitos pedidos
    plt.plot(x, seno, 'k', linestyle = "--", label = "sin(x)")
    plt.plot(x, coseno, 'b', linestyle = "--", label = "cos(x)")
    plt.plot(x, seno + coseno, 'r', linestyle = "--", label = "sin(x) + cos(x)")
    plt.legend()
    plt.show()

# Función principal que ejecuta todos los ejercicios
def main():
    ej1()
    espera()
    ej2()
    espera()
    ej3()
    espera()

main()


#!/usr/bin/env python

import logging
import quopri

logger = logging.getLogger(__name__)

def get_message_content(message):
	"""
	Get message content from an email.

	Uses `is_multipart()` and `get_payload()` to recursively call this
	function and build the message content from the parts.

	Parameters
	----------

	message : email.message.Message
		https://docs.python.org/3.4/library/email.message.html#email.message.Message

	Returns
	-------

	str
		Raw content of the message that needs to be decoded.
	"""

	if not message.is_multipart():
		return message.get_payload()

	parts = [
		get_message_content(payload)
		for payload in message.get_payload()
	]

	return ''.join(parts)

def get_message_text(message):
	"""
	Get text content from an email message.

	Uses `get_message_content()` to get the raw mail content.

	Parameters
	----------

	message : email.message.Message
		https://docs.python.org/3.4/library/email.message.html#email.message.Message
	"""

	logger.debug('Start getting message content.')

	raw_content = get_message_content(message)

	logger.debug('Decoding message content to bytes.')

	content_bytes = quopri.decodestring(raw_content, False)

	logger.debug('Decoding message bytes to text.')

	return content_bytes.decode('utf-8')


from __future__ import annotations

from typing import ClassVar, Optional

from pydantic import Field, validator

from pyatlan.model.fields.atlan_fields import (
    BooleanField,
    KeywordField,
    NumericField,
    RelationField,
    TextField,
)

from .asset40 import Sigma

class SigmaWorkbook(Sigma):
    """Description"""

    type_name: str = Field("SigmaWorkbook", allow_mutation=False)

    @validator("type_name")
    def validate_type_name(cls, v):
        if v != "SigmaWorkbook":
            raise ValueError("must be SigmaWorkbook")
        return v

    def __setattr__(self, name, value):
        if name in SigmaWorkbook._convenience_properties:
            return object.__setattr__(self, name, value)
        super().__setattr__(name, value)

    SIGMA_PAGE_COUNT: ClassVar[NumericField] = NumericField(
        "sigmaPageCount", "sigmaPageCount"
    )
    """
    TBC
    """

    SIGMA_PAGES: ClassVar[RelationField] = RelationField("sigmaPages")
    """
    TBC
    """

    _convenience_properties: ClassVar[list[str]] = [
        "sigma_page_count",
        "sigma_pages",
    ]

    @property
    def sigma_page_count(self) -> Optional[int]:
        return None if self.attributes is None else self.attributes.sigma_page_count

    @sigma_page_count.setter
    def sigma_page_count(self, sigma_page_count: Optional[int]):
        if self.attributes is None:
            self.attributes = self.Attributes()
        self.attributes.sigma_page_count = sigma_page_count

    @property
    def sigma_pages(self) -> Optional[list[SigmaPage]]:
        return None if self.attributes is None else self.attributes.sigma_pages

    @sigma_pages.setter
    def sigma_pages(self, sigma_pages: Optional[list[SigmaPage]]):
        if self.attributes is None:
            self.attributes = self.Attributes()
        self.attributes.sigma_pages = sigma_pages

    class Attributes(Sigma.Attributes):
        sigma_page_count: Optional[int] = Field(
            None, description="", alias="sigmaPageCount"
        )
        sigma_pages: Optional[list[SigmaPage]] = Field(
            None, description="", alias="sigmaPages"
        )  # relationship

    attributes: "SigmaWorkbook.Attributes" = Field(
        default_factory=lambda: SigmaWorkbook.Attributes(),
        description="Map of attributes in the instance and their values. The specific keys of this map will vary by "
        "type, so are described in the sub-types of this schema.\n",
    )

class SigmaDataElementField(Sigma):
    """Description"""

    type_name: str = Field("SigmaDataElementField", allow_mutation=False)

    @validator("type_name")
    def validate_type_name(cls, v):
        if v != "SigmaDataElementField":
            raise ValueError("must be SigmaDataElementField")
        return v

    def __setattr__(self, name, value):
        if name in SigmaDataElementField._convenience_properties:
            return object.__setattr__(self, name, value)
        super().__setattr__(name, value)

    SIGMA_DATA_ELEMENT_FIELD_IS_HIDDEN: ClassVar[BooleanField] = BooleanField(
        "sigmaDataElementFieldIsHidden", "sigmaDataElementFieldIsHidden"
    )
    """
    TBC
    """
    SIGMA_DATA_ELEMENT_FIELD_FORMULA: ClassVar[TextField] = TextField(
        "sigmaDataElementFieldFormula", "sigmaDataElementFieldFormula"
    )
    """
    TBC
    """

    SIGMA_DATA_ELEMENT: ClassVar[RelationField] = RelationField("sigmaDataElement")
    """
    TBC
    """

    _convenience_properties: ClassVar[list[str]] = [
        "sigma_data_element_field_is_hidden",
        "sigma_data_element_field_formula",
        "sigma_data_element",
    ]

    @property
    def sigma_data_element_field_is_hidden(self) -> Optional[bool]:
        return (
            None
            if self.attributes is None
            else self.attributes.sigma_data_element_field_is_hidden
        )

    @sigma_data_element_field_is_hidden.setter
    def sigma_data_element_field_is_hidden(
        self, sigma_data_element_field_is_hidden: Optional[bool]
    ):
        if self.attributes is None:
            self.attributes = self.Attributes()
        self.attributes.sigma_data_element_field_is_hidden = (
            sigma_data_element_field_is_hidden
        )

    @property
    def sigma_data_element_field_formula(self) -> Optional[str]:
        return (
            None
            if self.attributes is None
            else self.attributes.sigma_data_element_field_formula
        )

    @sigma_data_element_field_formula.setter
    def sigma_data_element_field_formula(
        self, sigma_data_element_field_formula: Optional[str]
    ):
        if self.attributes is None:
            self.attributes = self.Attributes()
        self.attributes.sigma_data_element_field_formula = (
            sigma_data_element_field_formula
        )

    @property
    def sigma_data_element(self) -> Optional[SigmaDataElement]:
        return None if self.attributes is None else self.attributes.sigma_data_element

    @sigma_data_element.setter
    def sigma_data_element(self, sigma_data_element: Optional[SigmaDataElement]):
        if self.attributes is None:
            self.attributes = self.Attributes()
        self.attributes.sigma_data_element = sigma_data_element

    class Attributes(Sigma.Attributes):
        sigma_data_element_field_is_hidden: Optional[bool] = Field(
            None, description="", alias="sigmaDataElementFieldIsHidden"
        )
        sigma_data_element_field_formula: Optional[str] = Field(
            None, description="", alias="sigmaDataElementFieldFormula"
        )
        sigma_data_element: Optional[SigmaDataElement] = Field(
            None, description="", alias="sigmaDataElement"
        )  # relationship

    attributes: "SigmaDataElementField.Attributes" = Field(
        default_factory=lambda: SigmaDataElementField.Attributes(),
        description="Map of attributes in the instance and their values. The specific keys of this map will vary by "
        "type, so are described in the sub-types of this schema.\n",
    )

class SigmaPage(Sigma):
    """Description"""

    type_name: str = Field("SigmaPage", allow_mutation=False)

    @validator("type_name")
    def validate_type_name(cls, v):
        if v != "SigmaPage":
            raise ValueError("must be SigmaPage")
        return v

    def __setattr__(self, name, value):
        if name in SigmaPage._convenience_properties:
            return object.__setattr__(self, name, value)
        super().__setattr__(name, value)

    SIGMA_DATA_ELEMENT_COUNT: ClassVar[NumericField] = NumericField(
        "sigmaDataElementCount", "sigmaDataElementCount"
    )
    """
    TBC
    """

    SIGMA_DATA_ELEMENTS: ClassVar[RelationField] = RelationField("sigmaDataElements")
    """
    TBC
    """
    SIGMA_WORKBOOK: ClassVar[RelationField] = RelationField("sigmaWorkbook")
    """
    TBC
    """

    _convenience_properties: ClassVar[list[str]] = [
        "sigma_data_element_count",
        "sigma_data_elements",
        "sigma_workbook",
    ]

    @property
    def sigma_data_element_count(self) -> Optional[int]:
        return (
            None
            if self.attributes is None
            else self.attributes.sigma_data_element_count
        )

    @sigma_data_element_count.setter
    def sigma_data_element_count(self, sigma_data_element_count: Optional[int]):
        if self.attributes is None:
            self.attributes = self.Attributes()
        self.attributes.sigma_data_element_count = sigma_data_element_count

    @property
    def sigma_data_elements(self) -> Optional[list[SigmaDataElement]]:
        return None if self.attributes is None else self.attributes.sigma_data_elements

    @sigma_data_elements.setter
    def sigma_data_elements(
        self, sigma_data_elements: Optional[list[SigmaDataElement]]
    ):
        if self.attributes is None:
            self.attributes = self.Attributes()
        self.attributes.sigma_data_elements = sigma_data_elements

    @property
    def sigma_workbook(self) -> Optional[SigmaWorkbook]:
        return None if self.attributes is None else self.attributes.sigma_workbook

    @sigma_workbook.setter
    def sigma_workbook(self, sigma_workbook: Optional[SigmaWorkbook]):
        if self.attributes is None:
            self.attributes = self.Attributes()
        self.attributes.sigma_workbook = sigma_workbook

    class Attributes(Sigma.Attributes):
        sigma_data_element_count: Optional[int] = Field(
            None, description="", alias="sigmaDataElementCount"
        )
        sigma_data_elements: Optional[list[SigmaDataElement]] = Field(
            None, description="", alias="sigmaDataElements"
        )  # relationship
        sigma_workbook: Optional[SigmaWorkbook] = Field(
            None, description="", alias="sigmaWorkbook"
        )  # relationship

    attributes: "SigmaPage.Attributes" = Field(
        default_factory=lambda: SigmaPage.Attributes(),
        description="Map of attributes in the instance and their values. The specific keys of this map will vary by "
        "type, so are described in the sub-types of this schema.\n",
    )

class SigmaDataElement(Sigma):
    """Description"""

    type_name: str = Field("SigmaDataElement", allow_mutation=False)

    @validator("type_name")
    def validate_type_name(cls, v):
        if v != "SigmaDataElement":
            raise ValueError("must be SigmaDataElement")
        return v

    def __setattr__(self, name, value):
        if name in SigmaDataElement._convenience_properties:
            return object.__setattr__(self, name, value)
        super().__setattr__(name, value)

    SIGMA_DATA_ELEMENT_QUERY: ClassVar[KeywordField] = KeywordField(
        "sigmaDataElementQuery", "sigmaDataElementQuery"
    )
    """
    TBC
    """
    SIGMA_DATA_ELEMENT_TYPE: ClassVar[KeywordField] = KeywordField(
        "sigmaDataElementType", "sigmaDataElementType"
    )
    """
    TBC
    """
    SIGMA_DATA_ELEMENT_FIELD_COUNT: ClassVar[NumericField] = NumericField(
        "sigmaDataElementFieldCount", "sigmaDataElementFieldCount"
    )
    """
    TBC
    """

    SIGMA_PAGE: ClassVar[RelationField] = RelationField("sigmaPage")
    """
    TBC
    """
    SIGMA_DATA_ELEMENT_FIELDS: ClassVar[RelationField] = RelationField(
        "sigmaDataElementFields"
    )
    """
    TBC
    """

    _convenience_properties: ClassVar[list[str]] = [
        "sigma_data_element_query",
        "sigma_data_element_type",
        "sigma_data_element_field_count",
        "sigma_page",
        "sigma_data_element_fields",
    ]

    @property
    def sigma_data_element_query(self) -> Optional[str]:
        return (
            None
            if self.attributes is None
            else self.attributes.sigma_data_element_query
        )

    @sigma_data_element_query.setter
    def sigma_data_element_query(self, sigma_data_element_query: Optional[str]):
        if self.attributes is None:
            self.attributes = self.Attributes()
        self.attributes.sigma_data_element_query = sigma_data_element_query

    @property
    def sigma_data_element_type(self) -> Optional[str]:
        return (
            None if self.attributes is None else self.attributes.sigma_data_element_type
        )

    @sigma_data_element_type.setter
    def sigma_data_element_type(self, sigma_data_element_type: Optional[str]):
        if self.attributes is None:
            self.attributes = self.Attributes()
        self.attributes.sigma_data_element_type = sigma_data_element_type

    @property
    def sigma_data_element_field_count(self) -> Optional[int]:
        return (
            None
            if self.attributes is None
            else self.attributes.sigma_data_element_field_count
        )

    @sigma_data_element_field_count.setter
    def sigma_data_element_field_count(
        self, sigma_data_element_field_count: Optional[int]
    ):
        if self.attributes is None:
            self.attributes = self.Attributes()
        self.attributes.sigma_data_element_field_count = sigma_data_element_field_count

    @property
    def sigma_page(self) -> Optional[SigmaPage]:
        return None if self.attributes is None else self.attributes.sigma_page

    @sigma_page.setter
    def sigma_page(self, sigma_page: Optional[SigmaPage]):
        if self.attributes is None:
            self.attributes = self.Attributes()
        self.attributes.sigma_page = sigma_page

    @property
    def sigma_data_element_fields(self) -> Optional[list[SigmaDataElementField]]:
        return (
            None
            if self.attributes is None
            else self.attributes.sigma_data_element_fields
        )

    @sigma_data_element_fields.setter
    def sigma_data_element_fields(
        self, sigma_data_element_fields: Optional[list[SigmaDataElementField]]
    ):
        if self.attributes is None:
            self.attributes = self.Attributes()
        self.attributes.sigma_data_element_fields = sigma_data_element_fields

    class Attributes(Sigma.Attributes):
        sigma_data_element_query: Optional[str] = Field(
            None, description="", alias="sigmaDataElementQuery"
        )
        sigma_data_element_type: Optional[str] = Field(
            None, description="", alias="sigmaDataElementType"
        )
        sigma_data_element_field_count: Optional[int] = Field(
            None, description="", alias="sigmaDataElementFieldCount"
        )
        sigma_page: Optional[SigmaPage] = Field(
            None, description="", alias="sigmaPage"
        )  # relationship
        sigma_data_element_fields: Optional[list[SigmaDataElementField]] = Field(
            None, description="", alias="sigmaDataElementFields"
        )  # relationship

    attributes: "SigmaDataElement.Attributes" = Field(
        default_factory=lambda: SigmaDataElement.Attributes(),
        description="Map of attributes in the instance and their values. The specific keys of this map will vary by "
        "type, so are described in the sub-types of this schema.\n",
    )

SigmaWorkbook.Attributes.update_forward_refs()

SigmaDataElementField.Attributes.update_forward_refs()

SigmaPage.Attributes.update_forward_refs()

SigmaDataElement.Attributes.update_forward_refs()


if __name__ == "__main__":
    f = open("rosalind_ba1c.txt","r")
    dna = f.readline()

    ans = ""

    for i in reversed(range(len(dna))):
        if dna[i] == 'A':
            ans = ans + 'T'
        elif dna[i] == 'T':
            ans = ans + 'A'
        elif dna[i] == 'C':
            ans = ans + 'G'
        elif dna[i] == 'G':
            ans = ans + 'C'

    print(ans)


from ulib.util import blink_pico_led, toggle_pico_led
from ulib.util import Log
from ulib.micropyGPS import MicropyGPS

from utime import sleep_ms
from time import time
from time import sleep
from machine import Pin
from machine import UART
import _thread

log = Log()
log.debug('%s import begin' % __name__)

class GPS():
    def __init__(self, uart=0, baudrate=4800, tx_pin=16, rx_pin=17):
        blink_pico_led()
        sleep_ms(500)
        toggle_pico_led()
        log.debug('%s __init__(uart=%s, baudrate=%s, tx_pin=%s, rx_pin=%s)' % (__name__, uart, baudrate, tx_pin, rx_pin))
        self.gps_uart   = UART(uart, baudrate=baudrate, tx=Pin(tx_pin), rx=Pin(rx_pin))
        self.mGPS       = MicropyGPS()
        print('Aquiring GPS Satellite')
        self._get_data()
        sleep_ms(1000)
        self._get_data()
        self.thread = _thread.start_new_thread(self.thread_loop, ())

    def _get_data(self):
        for i in range(4):
            sentence = self.gps_uart.readline()
            if sentence:
                for char in sentence:
                    try:
                        self.mGPS.update(str(char))
                    except Exception as e:
                        #log.debug(e)
                        pass

    def thread_loop(self):
        self.data()
        sleep_ms(500)

    def data(self):
        print('Getting GPS data')
        self._get_data()
        data = {
            #'active_segment': self.mGPS.active_segment,
            'altitude': self.mGPS.altitude,

            #'clean_sentences': self.mGPS.clean_sentences,
            'compass_direction': self.mGPS.compass_direction(),
            #'char_count': self.mGPS.char_count,
            #'crc_fails': self.mGPS.crc_fails,
            #'crc_xor': self.mGPS.crc_xor,
            #'coord_format': self.mGPS.coord_format,
            #'course': self.mGPS.course,

            ##'fix_stat': self.mGPS.fix_stat,
            ##'fix_time': self.mGPS.fix_time,
            ##'fix_type': self.mGPS.fix_type,

            #'geoid_height': self.mGPS.geoid_height,

            'latitude': self.mGPS.latitude,
            'longitude': self.mGPS.longitude,
            ##'log_en': self.mGPS.log_en,
            ##'log_handle': self.mGPS.log_handle,
            #'local_offset': self.mGPS.local_offset,

            #'process_crc': self.mGPS.process_crc,
            #'gps_segments': self.mGPS.gps_segments,
            #'parsed_sentences': self.mGPS.parsed_sentences,
            #'timestamp': self.mGPS.timestamp,
            'date': self.mGPS.date,

            'satellite_data_updated': self.mGPS.satellite_data_updated(),
            'speed': self.mGPS.speed,
            #'sentence_active': self.mGPS.sentence_active,

            #'satellites_in_view': self.mGPS.satellites_in_view,
            #'satellites_in_use': self.mGPS.satellites_in_use,
            #'satellites_used': self.mGPS.satellites_used,

            #'last_sv_sentence': self.mGPS.last_sv_sentence,
            #'total_sv_sentences': self.mGPS.total_sv_sentences,
            ##'satellite_data': self.mGPS.satellite_data,
            #'hdop': self.mGPS.hdop,
            #'pdop': self.mGPS.pdop,
            #'vdop': self.mGPS.vdop,
            #'valid': self.mGPS.valid,
            #'start_logging': self.mGPS.start_logging,
            #'stop_logging': self.mGPS.stop_logging,
            #'write_log': self.mGPS.write_log,
            #'gprmc': self.mGPS.gprmc,
            'date_string': self.mGPS.date_string(),
            #'new_fix_time': self.mGPS.new_fix_time,
            #'gpgll': self.mGPS.gpgll,
            #'gpvtg': self.mGPS.gpvtg,
            #'gpgga': self.mGPS.gpgga,
            #'gpgsa': self.mGPS.gpgsa,
            #'gpgsv': self.mGPS.gpgsv,
            #'new_sentence': self.mGPS.new_sentence,
            #'supported_sentences': self.mGPS.supported_sentences,
            ##'satellite_data_updated': self.mGPS.satellite_data_updated(),
            #'unset_satellite_data_updated': self.mGPS.unset_satellite_data_updated,
            ##'satellites_visible': self.mGPS.satellites_visible,
            ##'time_since_fix': self.mGPS.time_since_fix(),
            #'latitude_string': self.mGPS.latitude_string,
            #'longitude_string': self.mGPS.longitude_string,
            'speed_string': self.mGPS.speed_string()
        }
        return data

    #function to convert raw Latitude and Longitude
    #to actual Latitude and Longitude
    def convertToDigree(self, RawDegrees):
        RawAsFloat = float(RawDegrees)
        firstdigits = int(RawAsFloat/100) #degrees
        nexttwodigits = RawAsFloat - float(firstdigits*100) #minutes
        Converted = float(firstdigits + nexttwodigits/60.0)
        Converted = '{0:.6f}'.format(Converted) # to 6 decimal places
        return str(Converted)

log.debug('%s import end' % __name__, device='I2C:OLED:128:32')

if __name__ == '__main__':
    gps = GPS()
    #sleep_ms(2000)
    #while True:
    #    print(gps.data())
    #    sleep_ms(1000)


from dataclasses import dataclass, field
from typing import Optional

from .area_rando_types import AreaDoor
from .connection_data import SunkenNestL, area_doors
from .game import Game
from .item_data import Items
from .loadout import Loadout
from .location_data import Location, spacePortLocs
from .logic_goal import can_win
from .logic_shortcut_data import can_fall_from_spaceport
from .logic_updater import updateLogic
from .trick import Trick
from .trick_data import Tricks

@dataclass
class Sphere:
    fallen: bool
    pickups: dict[str, str] = field(default_factory=dict)
    new_doors: list[str] = field(default_factory=list)

@dataclass
class PlayThrough:
    spheres: list[Sphere] = field(default_factory=list)

def solve(game: Game,
          starting_items: Optional[Loadout] = None,
          excluded_door: Optional[AreaDoor] = None) -> tuple[bool, PlayThrough, list[Location]]:
    """ returns (whether completable, play through, accessible locations) """
    for loc in game.all_locations.values():
        loc['inlogic'] = False

    unused_locations: list[Location] = list(game.all_locations.values())
    used_locs: set[str] = set()
    doors_accessed: set[AreaDoor] = set()

    loadout = Loadout(game, starting_items)

    play_through = PlayThrough()

    def check_for_new_area_doors() -> None:
        new_area_doors: list[str] = []
        for thing in loadout:
            if isinstance(thing, AreaDoor) and thing not in doors_accessed:
                new_area_doors.append(thing.name)
                doors_accessed.add(thing)
        if len(new_area_doors):
            # print(new_area_doors)
            if len(play_through.spheres) == 0:
                play_through.spheres.append(Sphere(False))
            play_through.spheres[-1].new_doors.extend(new_area_doors)

    # this loop just for spaceport
    stuck = False
    while not stuck:
        prev_loadout_count = len(loadout)
        updateLogic(unused_locations, loadout, excluded_door)
        check_for_new_area_doors()
        play_through.spheres.append(Sphere(False))
        for loc in unused_locations:
            if loc['inlogic']:
                loc_name = loc['fullitemname']
                if loc_name not in spacePortLocs:
                    # debug
                    # print(f"found {loc_name} in logic while still in spaceport")
                    continue
                item = loc['item']
                if item:
                    loadout.append(item)
                    play_through.spheres[-1].pickups[loc_name] = item[0]
                used_locs.add(loc_name)
        # remove used locations
        unused_locations = [loc for loc in unused_locations if loc['fullitemname'] not in used_locs]
        stuck = len(loadout) == prev_loadout_count

    while (
        len(play_through.spheres) > 0 and
        len(play_through.spheres[-1].new_doors) + len(play_through.spheres[-1].pickups) == 0
    ):
        play_through.spheres.pop()

    if can_fall_from_spaceport not in loadout:
        # print("solver: couldn't get out of spaceport")
        # for loc in unused_locations:
        #     if loc['inlogic'] and loc['fullitemname'] not in spacePortLocs:
        #         print("solver: found another way out of spaceport besides Ridley")
        #         print(loadout)
        #         print("but logic doesn't support that yet")
        return False, play_through, [loc for loc in game.all_locations.values() if loc["fullitemname"] in used_locs]
    loadout.append(Items.spaceDrop)
    loadout.append(SunkenNestL)  # assuming this is where we land

    stuck = False
    while not stuck:
        prev_loadout_count = len(loadout)
        updateLogic(unused_locations, loadout, excluded_door)
        check_for_new_area_doors()
        play_through.spheres.append(Sphere(True))
        for loc in unused_locations:

            # special case: major/minor can put missiles or grav boots in sandy cache even though it's not in logic
            # old major minor code obsolete, but it doesn't hurt
            if game.options.fill_choice == "MM" and loc['fullitemname'] == "Sandy Cache" and loc['item'] in {
                Items.GravityBoots, Items.Missile
            }:
                loc['inlogic'] = True

            if loc['inlogic']:
                loc_name = loc['fullitemname']
                item = loc['item']
                if item:
                    loadout.append(item)
                    play_through.spheres[-1].pickups[loc_name] = item[0]
                used_locs.add(loc_name)
        # remove used locations
        unused_locations = [loc for loc in unused_locations if loc['fullitemname'] not in used_locs]
        stuck = len(loadout) == prev_loadout_count

    while (
        len(play_through.spheres) > 0 and
        len(play_through.spheres[-1].new_doors) + len(play_through.spheres[-1].pickups) == 0
    ):
        play_through.spheres.pop()

    # note: the reason for making a new list from all_locations rather than used_locs,
    # is that used_locs is a `set`, so iterating through it is not deterministic, so seeds wouldn't be reproducible
    return (
        (can_win in loadout),
        # len(unused_locations) == 0,
        play_through,
        [loc for loc in game.all_locations.values() if loc["fullitemname"] in used_locs]
    )

def spoil_play_through(play_through: PlayThrough) -> list[str]:
    items_to_display = {
        "Missile": 999,
        "Morph Ball": 999,
        "Gravity Boots": 999,
        "Super Missile": 999,
        "Grapple Beam": 999,
        "Power Bomb": 999,
        "Speed Ball": 999,
        "Bombs": 999,
        "HiJump": 999,
        "Aqua Suit": 999,
        "Dark Visor": 999,
        "Wave Beam": 999,
        "Speed Booster": 999,
        "Spazer": 999,
        "Varia Suit": 999,
        "Ice Beam": 999,
        "Metroid Suit": 999,
        "Plasma Beam": 999,
        "Screw Attack": 999,
        "Space Jump": 999,
        "Charge Beam": 999,
        "Hypercharge": 999,
        "X-Ray Scope": 999,
        "Energy Tank": 5,
        "Small Ammo": 4,
        "Large Ammo": 6,
        "Space Jump Boost": 1,
        "Damage Amp": 1,
        "Accel Charge": 1,
        "Refuel Tank": 0,
    }

    seen_fallen = False
    log_lines = [" - spaceport -"]
    for sphere in play_through.spheres:
        if sphere.fallen and not seen_fallen:
            log_lines.append(" - fall from spaceport -")
            seen_fallen = True

        log_lines.append("sphere:")
        for loc_name, item in sphere.pickups.items():
            if items_to_display[item] > 0:  # TODO: or hard required
                log_lines.append(f"    get {item} from {loc_name}")
                items_to_display[item] -= 1
        # TODO: if didn't display any pickups in sphere, display all pickups in sphere (unless last sphere)
        if len(sphere.new_doors):
            log_lines.append(f"  new area doors: {', '.join(sphere.new_doors)}")

    # TODO: delete "sphere:" from end
    return log_lines

def _locations_in_prog_order(play_through: PlayThrough) -> dict[str, int]:
    """
    { location name: sphere number }

    0 sphere means not in log lines

    If locations aren't in the solve log lines, they're at the end of this list.
    """
    locations: dict[str, int] = {}

    for sphere_i, sphere in enumerate(play_through.spheres):
        for loc_name in sphere.pickups:
            locations[loc_name] = sphere_i

    return locations

def hard_required_locations(game: Game) -> tuple[dict[str, int], PlayThrough]:
    """ list of names of hard required locations in progression order """
    completable, play_through, _ = solve(game)
    if not completable:
        # not sure what I want to do with this function if I pass a game that isn't completable
        # maybe exception
        return {}, play_through

    locations = _locations_in_prog_order(play_through)

    req_locs: dict[str, int] = {}
    for excluded_loc_name in locations:
        excluded_loc = game.all_locations[excluded_loc_name]
        saved_item = excluded_loc['item']
        excluded_loc['item'] = None
        completable, _, _ = solve(game)
        if not completable:
            req_locs[excluded_loc_name] = locations[excluded_loc_name]
        excluded_loc['item'] = saved_item

    return req_locs, play_through

def _excluded_tricks(t: Trick) -> set[Trick]:
    """
    all of the tricks that should be excluded to exclude this trick

    "If you can't do the easier one, then you can't do the harder one."
    """
    data = {
        Tricks.hell_run_easy:
            {Tricks.hell_run_easy, Tricks.hell_run_medium, Tricks.hell_run_hard},
        Tricks.hell_run_medium:
            {Tricks.hell_run_medium, Tricks.hell_run_hard},

        Tricks.dark_easy:
            {Tricks.dark_easy, Tricks.dark_medium, Tricks.dark_hard},
        Tricks.dark_medium:
            {Tricks.dark_medium, Tricks.dark_hard},

        Tricks.movement_moderate:
            {Tricks.movement_moderate, Tricks.movement_zoast},

        Tricks.sbj_underwater_w_hjb:
            {Tricks.sbj_underwater_w_hjb, Tricks.sbj_underwater_no_hjb},

        Tricks.wall_jump_precise:
            {Tricks.wall_jump_precise, Tricks.wall_jump_delayed},

        Tricks.morph_jump_4_tile:
            {Tricks.morph_jump_4_tile, Tricks.morph_jump_3_tile},

        Tricks.crouch_or_downgrab:
            {Tricks.crouch_or_downgrab, Tricks.crouch_precise},

        Tricks.short_charge_2:
            {Tricks.short_charge_2, Tricks.short_charge_3, Tricks.short_charge_4},

        Tricks.uwu_2_tile:
            {Tricks.uwu_2_tile, Tricks.uwu_2_tile_surface}
    }
    if t in data:
        return data[t]
    return {t}

def obsoletes(t: str) -> set[str]:
    data = {
        "hell_run_hard": {"hell_run_medium", "hell_run_easy"},
        "hell_run_medium": {"hell_run_easy"},
        "dark_hard": {"dark_medium", "dark_easy"},
        "dark_medium": {"dark_easy"},
        "movement_zoast": {"movement_moderate"},
    }
    if t in data:
        return data[t]
    return set()

def required_tricks(game: Game) -> tuple[list[str], list[str]]:
    """ lists of names of (tricks required to win, tricks required to get all locations) """
    completable, _, _ = solve(game)
    if not completable:
        # not sure what I want to do with this function if I pass a game that isn't completable
        # maybe exception
        return [], []

    req_for_win: list[str] = []
    req_for_locs: list[str] = []
    all_tricks = {t: n for n, t in vars(Tricks).items() if isinstance(t, Trick)}
    tricks_allowed = game.options.logic
    for excluded_trick in tricks_allowed:
        game.options.logic = tricks_allowed - _excluded_tricks(excluded_trick)
        completable, _, locs = solve(game)
        if not completable:
            req_for_win.append(all_tricks[excluded_trick])
        if len(locs) != 122:
            req_for_locs.append(all_tricks[excluded_trick])
    game.options.logic = tricks_allowed

    obsoleted: set[str] = set()
    for trick_name in req_for_win:
        obsoleted.update(obsoletes(trick_name))
    req_for_win = [trick_name for trick_name in req_for_win if trick_name not in obsoleted]

    obsoleted = set()
    for trick_name in req_for_locs:
        obsoleted.update(obsoletes(trick_name))
    req_for_locs = [trick_name for trick_name in req_for_locs if trick_name not in obsoleted]

    return req_for_win, req_for_locs

def required_doors(loadout: Loadout, loc_name: str) -> list[str]:
    """ what doors are required to get to this location with this loadout """
    temp_loadout = Loadout(loadout.game, loadout)
    _, play_through, acc_locs = solve(temp_loadout.game, temp_loadout)

    assert temp_loadout.game.all_locations[loc_name] in acc_locs, f"{loc_name} not in logic"

    doors: list[str] = []
    for sphere in play_through.spheres:
        for door_name in sphere.new_doors:
            doors.append(door_name)
            temp_loadout.contents[area_doors[door_name]] = 0

    tr: list[str] = []
    for excluded_door in doors:
        # empty doors from loadout
        for thing in temp_loadout:
            if isinstance(thing, AreaDoor):
                temp_loadout.contents[thing] = 0

        _, _, acc_locs = solve(temp_loadout.game, temp_loadout, area_doors[excluded_door])
        if temp_loadout.game.all_locations[loc_name] not in acc_locs:
            tr.append(excluded_door)

    return tr


import dash
import dash_ace
import dashvis.stylesheets
from dash import State
from dash import dcc
from dash import html
from dash.dependencies import Input
from dash.dependencies import Output
from dashvis import DashNetwork
from _common import str_to_dict, dict_to_str

from usage_examples._common import default_options_

app = dash.Dash(__name__, external_stylesheets=[dashvis.stylesheets.VIS_NETWORK_STYLESHEET],
                suppress_callback_exceptions=True)

network = DashNetwork(
    id='network',
    style={'height': '400px'},
    options=default_options_,
    enableHciEvents=False,
    enablePhysicsEvents=False,
    enableOtherEvents=False
)

app.layout = html.Div([
    html.Header(
        "This demo shows how one can control network manipulation using Dash callbacks."),
    network,
    html.Br(),
    html.Div([
        html.H4("Manipulation methods:"),
        html.Button("Enabled Edit Mode", id="enableEditMode_button"),
        html.Button("Disable Edit Mode", id="disableEditMode_button"),
        html.Button("Add Mode Mode", id="addNodeMode_button"),
        html.Button("Edit Node", id="editNode_button"),
        html.Button("Add Edge Mode", id="addEdgeMode_button"),
        html.Button("Edit Edge Mode", id="editEdgeMode_button"),
        html.Button("Delete Selected", id="deleteSelected_button")
    ])
])

callback_ouputs = {
    'enableEditMode': Output('network', 'enableEditMode'),
    'disableEditMode': Output('network', 'disableEditMode'),
    'addNodeMode': Output('network', 'addNodeMode'),
    'editNode': Output('network', 'editNode'),
    'addEdgeMode': Output('network', 'addEdgeMode'),
    'editEdgeMode': Output('network', 'editEdgeMode'),
    'deleteSelected': Output('network', 'deleteSelected'),
}

# noinspection PyUnusedLocal
@app.callback(
    output=callback_ouputs,
    inputs=dict(
        inputs={
            'enableEditMode_button': Input('enableEditMode_button', 'n_clicks'),
            'disableEditMode_button': Input('disableEditMode_button', 'n_clicks'),
            'addNodeMode_button': Input('addNodeMode_button', 'n_clicks'),
            'editNode_button': Input('editNode_button', 'n_clicks'),
            'addEdgeMode_button': Input('addEdgeMode_button', 'n_clicks'),
            'editEdgeMode_button': Input('editEdgeMode_button', 'n_clicks'),
            'deleteSelected_button': Input('deleteSelected_button', 'n_clicks'),
        }
    ),
    prevent_initial_callbacks=True
)
def handle_manipulation_methods(inputs):
    # Get the button id
    ctx = dash.callback_context
    button_id = None
    if not ctx.triggered_id:
        raise dash.exceptions.PreventUpdate
    else:
        button_id = ctx.triggered_id

    outputs = {key: False for key in callback_ouputs.keys()}
    outputs[button_id.replace('_button', '')] = True

    return outputs

server = app.server

if __name__ == '__main__':
    app.run_server(debug=True)


import click
from dataclasses import dataclass, field
import joblib
import json
import logging
import os
import xarray as xr

# current has import error and does not recognize XarrayBatchLoader as importable
from .datasets_handler import XarrayLoaderSklearn
from uwnet.thermo import sec_in_day

# test with rf regressor first

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger('train_sklearn_model')

@dataclass
class ModelTrainingConfig:
    model_params: dict
    model_type: str

    data: str = "data/processed/reshaped/noBlur.zarr"
    existing_data_file: str = "data/processed/generic_sklearn_format/"
    predict_radiation: bool = True
    seed: int = 1234
    vertical_grid_size: int = 34
    num_samples: int = 20000
    num_samples_validation: int = 10000
    batch_size: int = 256
    num_batches_for_training: int = 5
    prognostics: list = field(default_factory=lambda: ['QT', 'SLI'])
    targets: list = field(default_factory=lambda: ['Q1', 'Q2'])

    def __post_init__(self):
        self.training_slices = slice(0, self.num_samples)
        self.validation_slices = slice(self.num_samples, self.num_samples + self.num_samples_validation)
        self.output_path = f"sklearn_models/{self.model_type}.pkl"

def get_model_training_config(model_config_path):
    with open(model_config_path, 'r') as f:
        config_dict = json.load(f)
    model_config = ModelTrainingConfig(**config_dict)
    return model_config

def get_dataset(config):
    logger.info(f"Opening xarray dataset {config.data}")
    try:
        dataset = xr.open_zarr(config.data)
    except ValueError:
        dataset = xr.open_dataset(config.data)

    if not config.predict_radiation:
        dataset['FSLI'] = dataset['FSLI'] + dataset['QRAD'] / sec_in_day

    try:
        return dataset.isel(step=0).drop('step').drop('p')
    except:
        return dataset

def get_data_loader(
        data: xr.Dataset,
        config,
        train
):
    if train:
        slices = config.training_slices
    else:
        slices = config.validation_slices
    data = data.isel(x=slices)

    # List needed variables
    variables = config.prognostics + ['SST', 'SOLIN', 'QRAD']
    for variable in config.prognostics:
        forcing_key = 'F' + variable
        variables.append(forcing_key)
    train_data = XarrayLoaderSklearn(
        dataset=data,
        batch_size=config.batch_size,
        variables=variables)
    return train_data

def get_regressor_model(model_config):
    if 'rf' in model_config.model_type or 'random_forest' in model_config.model_type:
        from sklearn.ensemble import RandomForestRegressor
        regressor = RandomForestRegressor(**model_config.model_params)
        # temporarily set n_estimators to 0, will add estimators for each batch in iteration
        regressor.n_estimators = 0
    elif 'xgb' in model_config.model_type and 'tree' in model_config.model_type:
        # TODO: add other options?
        #from xgboost.sklearn_generic import XGBRegressor
        pass
    else:
        logger.error('model_type {self.model_type} provided in config file is not a valid model type.')

    return regressor

@click.command()
@click.option(
    '-cf',
    '--model-config-file',
    type=click.Path(),
    help='Location of config for model training.')
@click.option(
    '-op',
    '--model-output-path',
    type=click.Path(),
    default=None,
    help='Output the trained model to this path.')
def main(
        model_output_path,
        model_config_file,
):
    model_training_config = get_model_training_config(model_config_file)
    if not model_output_path:
        model_output_path = model_training_config.output_path
    dataset = get_dataset(model_training_config)
    train_loader = get_data_loader(dataset, model_training_config, train=True)
    regressor = get_regressor_model(model_training_config)

    for batch_num, training_batch in enumerate(train_loader):
        if batch_num >= model_training_config.num_batches_for_training:
            break
        train_X, train_y = training_batch
        if model_training_config.num_samples:
            train_X = train_X[:model_training_config.num_samples]
            train_y = train_y[:model_training_config.num_samples]
        logger.info(('training batch {0} / {1}'.format(batch_num, model_training_config.num_batches_for_training)))
        if 'rf' in model_training_config.model_type or 'random_forest' in model_training_config.model_type:
            regressor.n_estimators += model_training_config.model_params['n_estimators']

        regressor.fit(train_X, train_y)
    model_save_filename = os.path.join(
        model_output_path, f'{model_training_config.model_type}.pkl')
    joblib.dump(regressor, model_save_filename)

if __name__ == '__main__':
    main()


#! /usr/bin/env python3

import hashlib
import os
import numpy as np
import pandas as pd

class Housing():
    """
    This class is being used to try out the housing examples in Hands On Machine Learning
    with Sci-kit and Tensorflow
    """

    def __init__(self, path=".", csvFile="housing.csv"):
        """
        Constructor
        """
        self.csvFile = os.path.join(path, csvFile)
        self.dataFrame=None
        self.testingData = None
        self.trainingData = None
        self.testSet = None
        self.trainSet = None
        return

    def downloadData(self):
        """
        Download data from github
        """
        return

    def load_housing_data(self):
        """
        In a very unsafe manner load the house csv file into a pandas data frame
        """
        self.dataFrame = pd.read_csv(self.csvFile)
        return

    def split_train_test(self, test_ratio):
        """
        split up our data into testing and training
        """

        shuffled_indices = np.random.permutation(len(self.dataFrame))
        test_set_size = int(len(self.dataFrame) * test_ratio)
        test_indices = shuffled_indices[:test_set_size]
        train_indices = shuffled_indices[test_set_size:]
        self.trainingData = self.dataFrame.iloc[train_indices]
        self.testingData = self.dataFrame.iloc[test_indices]
        return

    def add_id_column(self):
        self.dataFrame.reset_index()
        return

    def test_set_check(self, identifier=None, test_ratio=None, hash=None):
        return hash(np.int64(identifier)).digest()[-1] < 256 * test_ratio

    def split_train_test_by_id(self, test_ratio=None, id_column=None):
        ids = self.dataFrame[id_column]
        in_test_set = ids.apply(lambda id_: self.test_self_check(id_,
                                                                 test_ratio, hashlib.md5))
        self.testSet = self.dataFrame.loc[in_test_set]
        self.trainSet = self.dataFrame.loc[~in_test_set]
        return


from django.urls import path
from . import views

urlpatterns= [
    path('', views.ApiOverview, name='home'),
    path('create/', views.add_items, name='add-items'),
    path('all/', views.view_items, name='view_items'),
    path('update/<int:pk>/', views.update_items, name='update-items'),
    path('item/<int:pk>/delete/', views.delete_items, name='delete-items'),
]