import json
from time import time
from typing import Any, ClassVar, Dict, List, Optional, Type, Union

# Import twisted libraries
from twisted.internet.defer import inlineCallbacks

# Import Yombo libraries
from yombo.core.exceptions import YomboWarning
from yombo.core.entity import Entity
from yombo.core.library import YomboLibrary
from yombo.core.log import get_logger
from yombo.core.schemas import DiscoverySchema
from yombo.mixins.library_db_child_mixin import LibraryDBChildMixin
from yombo.mixins.library_db_parent_mixin import LibraryDBParentMixin
from yombo.mixins.library_search_mixin import LibrarySearchMixin
from yombo.utils import random_string

logger = get_logger("library.discovery")

class DiscoveredDevice(Entity, LibraryDBChildMixin):
    """
    A single discovered device.
    """
    _Entity_type: ClassVar[str] = "Discovered device"
    _Entity_label_attribute: ClassVar[str] = "discovery_id"

    def load_attribute_values_pre_process(self, incoming):
        if "yombo_device" in incoming:
            self.yombo_device = incoming["yombo_device"]
        else:
            self.yombo_device = None

    def enable(self):
        """ Enable displaying of this discovered device. """
        self. update({"status": 1})

    def disable(self):
        """ Disable displaying of this discovered device. """
        self. update({"status": 0})

    def delete(self):
        """ Delete this discovered device. This sets the status to 0, where it will eventually be cleaned up. """
        self. update({"status": 2})

    def touch(self):
        self. update({"last_seen_at": int(time())})

    def __str__(self):
        return f"Discovered: {self.label} - {self.description}"

    @property
    def create_yombo_device_details(self):
        """
        Used to create a new device.
        :return:
        """
        out_variables = {}
        counter = 90
        for variable_name, variables in self.variables.items():
            if variable_name not in out_variables:
                out_variables[variable_name] = {}
            if isinstance(variables, list):
                for variable in variables:
                    out_variables[variable_name][f"new_{counter}"] = variable
                    counter += 1
            else:
                out_variables[variable_name][f"new_{counter}"] = variables
                counter += 1
        return json.dumps({
            "label": self.label,
            "machine_label": self.machine_label,
            "description": self.description,
            "device_type_id": self.device_type.device_type_id,
            "vars": out_variables,
        })

    # def asdict(self):
    #     """
    #     Display all the various details about the discovered device.
    #     :return:
    #     """
    #     out_variables = {}
    #     counter = 90
    #     for variable_name, variables in self.variables.items():
    #         if variable_name not in out_variables:
    #             out_variables[variable_name] = {}
    #         if isinstance(variables, list):
    #             for variable in variables:
    #                 out_variables[variable_name][f"new_{counter}"] = variable
    #                 counter += 1
    #         else:
    #             out_variables[variable_name][f"new_{counter}"] = variables
    #             counter += 1
    #     if self.yombo_device is not None:
    #         yombo_device_id = self.yombo_device.device_id
    #         yombo_device_label = self.yombo_device.full_label
    #     else:
    #         yombo_device_id = None
    #         yombo_device_label = ""
    #
    #     return {
    #         "label": self.label,
    #         "machine_label": self.machine_label,
    #         "description": self.description,
    #         "source": self.source,
    #         "device_type_id": self.device_type.device_type_id,
    #         "device_type_machine_label": self.device_type.machine_label,
    #         "yombo_device_id": yombo_device_id,
    #         "yombo_device_label": yombo_device_label,
    #         "model": self.model,
    #         "serial": self.serial,
    #         "vars": out_variables,
    #     }

class Discovery(YomboLibrary, LibraryDBParentMixin, LibrarySearchMixin):
    """
    A one-stop location to track discovered devices. This allows the user to quickly find auto-discovered devices
    and add them as a Yombo controlled device.
    """
    discovery: ClassVar[dict] = {}

    # The remaining attributes are used by various mixins.
    _storage_primary_field_name: ClassVar[str] = "discovery_id"
    _storage_attribute_name: ClassVar[str] = "discovery"
    _storage_pickled_fields: ClassVar[Dict[str, str]] = {"variables": "msgpack_zip"}
    _storage_label_name: ClassVar[str] = "discovery"
    _storage_class_reference: ClassVar = DiscoveredDevice
    _storage_schema: ClassVar = DiscoverySchema()
    _storage_search_fields: ClassVar[str] = [
        "discovery_id", "machine_label", "description"
    ]
    _storage_attribute_sort_key: ClassVar[str] = "machine_label"

    @inlineCallbacks
    def _init_(self, **kwargs):
        """
        Loads previously found devices from the database.
        """
        yield self.load_from_database()

    @inlineCallbacks
    def new(self, discover_id: str, mfr: str, model: str, serial: str, label: str, machine_label: str,
            description: str, request_context: str, device_type: Optional = None, device_type_id: Optional[str] = None,
            gateway_id: Optional[str] = None, variables: Optional[dict] = None, yombo_device: Optional = None,
            discovered_at: Optional[Union[float, int]] = None, last_seen_at: Optional[Union[float, int]] = None,
            created_at: Optional[Union[float, int]] = None, updated_at: Optional[Union[float, int]] = None,
            load_source: Optional[str] = None, notification: Optional[dict] = None):
        """
        Creates a new auto-discovered device.

        Note:
          * Either discovery source or load_source must be supplied.
          * Either device type or device type id must be supplied.

        :param discover_id: A unique id to reference this discovered device. No need to worry about conflicts from other modules.
        :param device_type: A device type to associate this device with.
        :param device_type_id: A device type id to associate this device with.
        :param discovered_at: When this device was first discovered.
        :param last_seen_at: When this device was last scene at.
        :param mfr: Who makes this device.
        :param model: Model of this device.
        :param serial: Serial number.
        :param label: A human friendly label.
        :param machine_label: A machine friendly label.
        :param description: A description about this device.
        :param yombo_device: Attach an already created yombo device to the discovered device.
        :param request_context: A reference to the module / library, or a string to store.
        :param variables: A dictionary of variables which is used when creating the device.
        :param created_at: A float/int when this device was created.
        :param updated_at: A float/int when this device was last updated.
        :param load_source: Where this information if coming from.
        :param notification: Notification details.
        :return:
        """
        logger.debug("new discovered device: {discover_id}", discover_id=discover_id)

        if load_source is None and request_context is None:
            raise YomboWarning(f"Device discovery must include either a load_source or request_context:"
                               f" {machine_label} - {label}")

        if load_source == "database":
            discovery_source_string = request_context
        elif request_context is None:
            raise YomboWarning(f"If load_souce is not database, request_context must be a string."
                               f" {machine_label} - {label}")
        else:
            if isinstance(request_context, str) is False:
                request_context = request_context._FullName

        machine_label = self._Validate.slugify(machine_label)
        if discover_id is None:
            discovered_id = random_string()

        if gateway_id is None:
            gateway_id = self._gateway_id

        discover_id = self.get_device_hash(discover_id, request_context)

        if device_type is None and device_type_id is None:
            raise YomboWarning(f"Either device_type or device_type_id must be supplied."
                               f" {machine_label} - {label}")
        if device_type is not None:
            device_type_id = device_type.device_type_id
            device_type = None
        else:
            device_type_id = self._DeviceTypes.get(device_type_id).device_type_id

        device_data = {
            "id": discover_id,
            "gateway_id": gateway_id,
            "device_type_id": device_type_id,
            "discovered_at": discovered_at,
            "last_seen_at": last_seen_at,
            "mfr": mfr,
            "model": model,
            "serial": serial,
            "label": label,
            "machine_label": machine_label,
            "description": description,
            "yombo_device": yombo_device,
            "request_context": request_context,
            "variables": variables,
            "created_at": created_at,
            "updated_at": updated_at,
        }
        if discover_id in self.discovery:
            filtered = {k: v for k, v in device_data.items() if v is not None}
            self.discovery[discover_id].update(filtered)
            self.discovery[discover_id].enable()
            self.discovery[discover_id].touch()
            return self.discovery[discover_id]

        # print(f"discovered device2: {device_data}")
        yield self.load_an_item_to_memory(device_data, load_source=load_source)

        if load_source != "database":  # TODO: review. Probably not the correct check to display notificaiton.
            if notification is None:
                notification = {}

            if "notification_title" in notification:
                notification_title = notification["notification_title"]
            else:
                notification_title = f"New {request_context} device found."

            if "notification_message" in notification:
                notification_message = notification["notification_message"]
            else:
                notification_message = f"
New {{source._FullName}} device found:

Description: {device_data['notification_description']}
"
                if mfr != "":
                    notification_message += f"
Manufacturer: {mfr}
"
                if model != "":
                    notification_message += f"
Model: {model}
"
                if serial != "":
                    notification_message += f"
Serial: {serial}
"

            yield self._Notifications.new(title=notification_title,
                                          message=notification_message,
                                          request_context=request_context,
                                          persist=True,
                                          priority="high",
                                          always_show=True,
                                          always_show_allow_clear=True,
            )
        return self.discovery[discover_id]

    def update(self, discover_id, data, source=None):
        discover_id = self.get_device_hash(discover_id, source)
        self.discovery[discover_id].update(data)

    def touch(self, discover_id, source):
        discover_id = self.get_device_hash(discover_id, source)
        self.discovery[discover_id].touch()

    def set_yombo_device(self, discover_id, yombo_device, request_context):
        discover_id = self.get_device_hash(discover_id, request_context)
        self.discovery[discover_id].yombo_device = yombo_device
        return self.discovery[discover_id]

    def get_device_hash(self, discover_id, source=None):
        if discover_id in self.discovery:
            return discover_id

        if source is None:
            raise YomboWarning("Discovery device updates requires a reference from the caller as 'source'.")

        if isinstance(source, str):
            return self._Hash.sha224_compact(str(source + discover_id).encode("utf-8"))

        return self._Hash.sha224_compact(str(source._FullName + discover_id).encode("utf-8"))

    def disable(self, discovered_id):
        if discovered_id in self.discovery:
            discovery = self.discovery[discovered_id]
            discovery.disable()
            return True
        return False

    def enable(self, discovered_id):
        if discovered_id in self.discovery:
            discovery = self.discovery[discovered_id]
            discovery.disable()
            return True
        return False

    def delete(self, discovered_id):
        if discovered_id in self.discovery:
            del self.discovery[discovered_id]
            return True
        return False


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sat Dec 12 18:28:03 2020

@author: iansharff
"""

with open('output.txt', 'r') as testfile:
    count = 0
    for line in testfile:
        count += len(line)
        print(len(line), end = ',')
    else:
        print('\n')
    print(f"Final count = {count}")


#!/usr/bin/python3

import os
import time
import random
import numpy as np

table_for_display = np.array(np.full(9, '[   ]').reshape((3, 3)))
signs = ['X', 'O']
numeric = np.array(np.full(9, 0).reshape((3, 3)))

print(f'\n\tCurrent game: Human VS Computer.\n')

def lines(number_of_lines):
    i = 0
    while i < number_of_lines:
        print(f'-', end='')
        i += 1
    print()

def display_board(giving_board):
    for i in giving_board:
        for j in i:
            print(f'{j}', end=' ')
        print()

def printing_board():
    print(f'Playing board:')
    lines(18)
    display_board(table_for_display)
    lines(18)

def register_player():
    print(f'\n*We need the name of only one player. The game is human vs computer.')
    return input('\t*Please enter your name in order to be registered: ').capitalize()

def choose_rounds(name):
    return int(input(f'\n*{name} who goes first, you or the computer ?\n\t-Human: 0\n\t-Computer: 1\n\t-Answer: '))

def print_present_order(players_order, player_name):
    print(f'\n*Present order:')

    if players_order == 0:
        print(f'\t-{player_name} will choose first and then the computer.')
    elif players_order == 1:
        print(f'\t-Computer is moving first.')

    time.sleep(1.5)
    os.system('clear')

def collect_possible_moves(table):
    available_options = []
    options_to_print = []

    length_table = len(table)
    for row in range(length_table):
        for column in range(len(table[row])):
            if np.any(table[row][column] != '[ X ]' and table[row][column] != '[ O ]'):
                options_to_print.append((row, column))
                available_options.append((row, column))

    return options_to_print, available_options

def print_possible_moves(options_to_print):
    print(f'\n*Computer is choosing now the row and column to put an {signs[1]}.', end=' ')
    print(f'{len(options_to_print)} options available: ', end='\n  ')

    for row, column in options_to_print:
        print(f'({row}, {column})', end=' ')
    print()

    time.sleep(1)

def print_first_diag(table):
    length_table = len(table)
    for i in range(length_table):
        for j in range(len(table[i])):
            if j == i:
                print(f'\033[31m{table[i][j]}\033[0m', end=' ')
            else:
                print(f'{table[i][j]}', end=' ')
        print()

def print_second_diag(table):
    length_table = len(table)
    for i in range(length_table):
        for j in range(len(table[i])):
            if i == length_table - 1 - j:
                print(f'\033[31m{table[i][j]}\033[0m', end=' ')
            else:
                print(f'{table[i][j]}', end=' ')
        print()

def pretty_print_rows_col(table, given_opt, location):
    length_table = len(table)
    for i in range(length_table):
        for j in range(len(table[i])):
            if location == 0 and i == given_opt:
                print(f'\033[31m{table[i][j]}\033[0m', end=' ')
            elif location == 1 and j == given_opt:
                print(f'\033[32m{table[i][j]}\033[0m', end=' ')
            else:
                print(f'{table[i][j]}', end=' ')
        print()

def colorized_winner_rows_col(table, given_opt, is_row):

    if is_row == 0:
        print(f'\nEnding...')
        lines(18)
        pretty_print_rows_col(table, given_opt, 0)
    elif is_row == 1:
        print(f'\nEnding...')
        lines(18)
        pretty_print_rows_col(table, given_opt, 1)

    lines(18)
    exit()

def colorized_winner_diags(diag, table, given_name):

    if diag == 1:
        print(f'\nWINNER WINNER CHICKEN DINNER !!\nDiag with same values, {given_name} is the winner.')
        print(f'\nEnding...')
        lines(18)
        print_first_diag(table)
    elif diag == 2:
        print(f'\nWINNER WINNER CHICKEN DINNER !!\nDiag with same values, {given_name} is the winner.')
        print(f'\nEnding...')
        lines(18)
        print_second_diag(table)

    lines(18)
    exit()

def checking_list(list_check, given_name, diag, table):
    if list_check.count(1) == 3:
        colorized_winner_diags(diag, table, given_name)
    elif list_check.count(2) == 3:
        colorized_winner_diags(diag, table, 'Computer')

def check_diagonals(numeric, given_name, table):
    list_check = []
    first_diag = 0
    second_diag = 0

    length_numeric = len(numeric)
    for i in range(length_numeric):
        for j in range(len(numeric[i])):
            if j == i:
                list_check.append(numeric[i][j])
                first_diag = 1

    checking_list(list_check, given_name, first_diag, table)

    list_check.clear()

    for i in range(length_numeric - 1, -1, -1):
        for j in range(len(numeric[i])):
            if j == (length_numeric - 1 - i):
                list_check.append(numeric[i][j])
                second_diag = 2

    checking_list(list_check, given_name, second_diag, table)

def check_winner(*args):
    table, given_name, numeric = args

    def select_winner(i, given_name, table, numeric):
        given_dict = {
            'list(numeric[i, :].flatten()).count(1)': ['colorized_winner_rows_col(table, i, 0)',
                                                       f"\nWINNER WINNER CHICKEN DINNER !!\n Row number {i}, "
                                                       f"{given_name} is the winner."],
            'list(numeric[i, :].flatten()).count(2)': ['colorized_winner_rows_col(table, i, 0)',
                                                       f"\nWINNER WINNER CHICKEN DINNER !!\n Row number {i},"
                                                       f" Computer is the winner."],
            'list(numeric[:, i].flatten()).count(1)': ['colorized_winner_rows_col(table, i, 1)', f"\nWINNER WINNER CHICKEN DINNER !!\n "
                                                       f"Column number {i}, {given_name} is the winner."],
            'list(numeric[:, i].flatten()).count(2)': ['colorized_winner_rows_col(table, i, 1)', f"\nWINNER WINNER CHICKEN DINNER !!\n "
                                                       f"Column number {i}, Computer is the winner."]
        }

        given_dict_items = given_dict.items()
        for j, k in given_dict_items:
            if eval(j) == 3:
                print(k[1])
                return eval(k[0])
            else:
                check_diagonals(numeric, given_name, table)

    table_length = len(table)
    for i in range(table_length):
        select_winner(i, given_name, table, numeric)

def human_player_check(*args):
    p1, reps, given_name, table, numeric = args

    printing_board()
    print(f'*{given_name} -> please specify row and column to put an {signs[0]} - >')
    player_row = int(input(f'\t-Row: '))
    player_column = int(input(f'\t-Column: '))

    if np.any(table[player_row, player_column] == '[ X ]' or table[player_row, player_column] == '[ O ]'):
        print(f'\nERROR - location already contains a given sign, please try again\n')
    else:
        table[player_row, player_column] = '[ X ]'
        numeric[player_row, player_column] = 1
        check_winner(table, given_name, numeric)
        reps += 1
        p1 += 1

    return p1, reps, table, numeric

def pc_player_check(*args):
    pc, reps, table, available_moves, moves_to_print, given_name, numeric = args
    print()
    printing_board()
    print_possible_moves(moves_to_print)

    random.shuffle(available_moves)
    choosen_row, choosen_column = available_moves[0]

    table[choosen_row, choosen_column] = '[ O ]'
    numeric[choosen_row, choosen_column] = 2
    print(f'\n*Computer has chosen {available_moves[0]}\n')
    check_winner(table, given_name, numeric)
    time.sleep(1)
    pc += 1
    reps += 1

    return pc, reps, table, numeric

def human_first(*args):
    p1, pc, reps, given_name, table, numeric = args

    while True:
        if p1 == 0:
            p1, reps, table, numeric = human_player_check(p1, reps, given_name, table, numeric)
        elif pc == 0:
            moves_to_print, available_moves = collect_possible_moves(table)
            pc, reps, table, numeric = pc_player_check(pc, reps, table, available_moves, moves_to_print, given_name, numeric)
        else:
            break

    return reps, given_name, table, numeric

def pc_first(*args):
    p1, pc, reps, given_name, table, numeric = args

    while True:
        if pc == 0 and reps <= 8:
            moves_to_print, available_moves = collect_possible_moves(table)
            pc, reps, table, numeric = pc_player_check(pc, reps, table, available_moves, moves_to_print, given_name, numeric)
        elif p1 == 0 and reps <= 8:
            p1, reps, table, numeric = human_player_check(p1, reps, given_name, table, numeric)
        else:
            break

    return reps, given_name, table, numeric

def fill_columns_rows(*args):
    p1 = 0
    pc = 0
    given_name, given_order, reps, table, numeric = args

    if given_order == 0:
        os.system('clear')
        reps, given_name, table, numeric = human_first(p1, pc, reps, given_name, table, numeric)
    elif given_order == 1:
        os.system('clear')
        reps, given_name, table, numeric = pc_first(p1, pc, reps, given_name, table, numeric)

    return reps

def main():
    i = 0
    repetitions = 0
    printing_board()
    player_name = register_player()
    players_order = choose_rounds(player_name)
    print_present_order(players_order, player_name)

    while i < 9:
        repetitions = fill_columns_rows(player_name, players_order, repetitions, table_for_display, numeric)
        i += 1

    print()
    printing_board()
    print('\n*We have a draw, nobody win.')

main()


from datasets import *
import matplotlib.pyplot as plt
import librosa.display
import numpy as np

title = "Základní frekvence"

def fundamental(D_db, sr, n_fft=512, fmin=65, fmax=2093):
    maxima = []
    for i,column in enumerate(D_db.T):
        column_maxima = column[0]
        maxima_index = 0
        for j, value in enumerate(column):
            if value > column[0]+9: # pokud je hodnota vetsi jak nejnizsi frekv. +30dB
                if value < column_maxima and column[j+1] < column_maxima and column[j+2] < column_maxima: # pak hledej maximum
                    maxima_index = j-1
                    break
                column_maxima = value
        if maxima_index != 0 and maxima_index*sr//n_fft<=fmax and maxima_index*sr//n_fft>=fmin:
            maxima.append(maxima_index*sr//n_fft)
    maxima = np.array(maxima)
    return maxima

# nacteni nahravky
sample = load_ravdess_dataset()[14]
data, sr = librosa.load(sample[0], sr=None)

# generovani grafu
fig, (a0, a1) = plt.subplots(2, 1, gridspec_kw={'height_ratios': [1, 3]}, figsize=(10, 10))

# prvni osa
librosa.display.waveplot(data, sr=sr, ax=a0)
a0.set_title('Časová oblast')
a0.set_xlabel("Čas [s]")
a0.set_ylabel("Amplituda")

# generovani spektrogramu
stft = librosa.stft(data, n_fft=512)
D = librosa.amplitude_to_db(np.abs(stft), ref=np.max)
img = librosa.display.specshow(D, sr=sr, y_axis='linear', x_axis='time', ax=a1, hop_length=128)

# pyin
f0, voiced_flag, voiced_probs = librosa.pyin(data, fmin=65, fmax=2093, sr=sr)
times = librosa.times_like(f0, sr=sr)
a1.plot(times, f0, label='Probabilistic YIN (mean: 477 Hz, std: 95 Hz)', color='blue', linewidth=2)

# muj algoritmus
maxima = []
m = []
for i,column in enumerate(D.T):
    column_maxima = column[0]
    maxima_index = 0
    for j, value in enumerate(column):
        if value > column[0]+9: # pokud je hodnota vetsi jak nejnizsi frekv. +9 dB
            if value < column_maxima and column[j+1] < column_maxima and column[j+2] < column_maxima: # pak hledej maximum
                maxima_index = j-1
                break
            column_maxima = value
    if maxima_index == 0 or maxima_index*sr//512>=2093 or maxima_index*sr//512<=65:
        maxima_index = -1
    else:
        m.append(maxima_index*sr//512)
    maxima.append(maxima_index*sr//512)
maxima = np.array(maxima)

times = librosa.times_like(maxima, sr=sr, hop_length=128)
a1.scatter(times, maxima, c='lime', label='Vlastní algoritmus (mean: 435 Hz, std: 196 Hz)', s=5)

# druha osa
a1.set_title(title)
a1.legend(loc='upper left', framealpha=1)
a1.set_xlabel("Čas [s]")
a1.set_ylabel("Frekvence [Hz]")

# ulozeni obrazku
fig.suptitle("Nahrávka hněvu (RAVDESS)", fontsize=16)
fig.colorbar(img, ax=a1, format="%+2.0f dB", location="bottom", shrink=0.5)
fig.tight_layout()
fig.savefig("images/" + title + ".pdf", dpi=300)
fig.show()


import json

def process(x):
    '''
    '''
    debug_mode = (execute('GET', 'config:debug_mode') == '1')
    hash_ttl = int(execute('GET', 'config:hash_ttl') or 0)

    if debug_mode:
        log(f"stream:{x['key']} id: {x['id']} payload:'{x['value']['payload']}'")

    hash_key = f'car:{x["id"]}'
    hash_dict = json.loads(x['value']['payload'])
    execute('HMSET', hash_key, *sum([[k,v] for k,v in hash_dict.items()],[]))

    if hash_ttl > 0:
        execute('EXPIRE', hash_key, hash_ttl)

gb = GearsBuilder('StreamReader')
gb.foreach(process)
# gb.register('sensor:1')
gb.register(prefix='sensor:*', trimStream=False)


# External Packages
import matplotlib.pyplot as plt

# Custom Packages
from tools import load

def cornu_plot(C, S):
    plt.figure()
    plt.plot(C, S)
    plt.xlabel('C')
    plt.ylabel('S')
    plt.title('Cornu Spiral')
    plt.savefig("cornu.png")

def main():
    U, C, S = load('cornu.dat')
    cornu_plot(C, S)

main()


"""
    Meter class for recording data for training and validation dataset:
    To avoid computing data in a whole batch, we update data in each batch with "update" method,
    After completing one epoch, we log the metric for one epoch, at the same time, we delete batch data
    and update epoch data with "epoch_log" method
"""

import os
import pdb
import numpy as np

import torch

class Meter(object):
    """

    """
    def __init__(self, phase, threshold = 0.5):
        self.phase = phase
        self.base_threshold = threshold
        self.base_dice_scores = []
        self.dice_neg_scores = []
        self.dice_pos_scores = []
        self.iou_scores = []
        self.batch_dice_scores = []
        self.batch_dice_neg_scores = []
        self.batch_dice_pos_scores = []
        self.batch_iou_scores = []

    def update(self, outputs, targets):
        pdb.set_trace()
        probs = torch.sigmoid(outputs)
        dice, dice_neg, dice_pos, _, _ = self._cal_metric(probs, targets, self.base_threshold)
        self.base_dice_scores.append(dice)
        self.dice_pos_scores.append(dice_pos)
        self.dice_neg_scores.append(dice_neg)
        preds = self._get_prediction(probs, self.base_threshold)
        iou = self._cal_iou(preds, targets.numpy(), classes=[1])
        self.iou_scores.append(iou)

    def epoch_log(self, epoch, loss, time):
        pdb.set_trace()
        batch_dice_score, batch_dice_neg, batch_dice_pos, batch_iou_score = \
            self._cal_epoch_avg(self.base_dice_scores, self.dice_neg_scores,
                                self.dice_pos_scores, self.iou_scores)

        self.batch_dice_scores.append(batch_dice_score)
        self.batch_dice_neg_scores.append(batch_dice_neg)
        self.batch_dice_pos_scores.append(batch_dice_pos)
        self.batch_iou_scores.append(batch_iou_score)

        del self.base_dice_scores[:]
        del self.dice_neg_scores[:]
        del self.dice_pos_scores[:]
        del self.iou_scores[:]
        print(f"Phase : {self.phase}, Epoch: {epoch}, Time : {time}")
        print(f"Loss: {loss} | dice_pos_score: {batch_dice_pos} | dice_neg_score: {batch_dice_neg} | "
              f"dice_score: {batch_dice_score} |  iou: {batch_iou_score}")

    def _cal_epoch_avg(self, dice_score, dice_neg, dice_pos, iou_score):
        pdb.set_trace()
        batch_dice_score = sum(dice_score) / len(dice_score)
        batch_dice_neg = sum(dice_neg) / len(dice_neg)
        batch_dice_pos = sum(dice_pos) / len(dice_pos)
        iou_score = np.array(iou_score)
        batch_iou_score = np.nanmean(iou_score, axis=0)

        return batch_dice_score, batch_dice_neg, batch_dice_pos, batch_iou_score

    def _cal_metric(self, probs, targets, threshold = 0.5, reductiom = "none"):
        pdb.set_trace()
        batch_size = targets.shape[0]
        probability = probs.view(batch_size, -1)
        truth = targets.view(batch_size, -1)
        assert (probability.shape == truth.shape), "outputs and targets shape don't match"

        p = (probability > threshold).float()
        t = (truth > threshold).float()
        p_sum = torch.sum(p, dim=-1)
        t_sum = torch.sum(t, dim=-1)
        neg_index = torch.nonzero(t_sum == 0)
        pos_index = torch.nonzero(t_sum >= 1)

        dice_neg = (p_sum == 0).float()
        dice_pos = 2 * (p * t).sum(dim=-1) / ((p + t).sum(-1))
        dice_neg = dice_neg[neg_index]
        dice_pos = dice_pos[pos_index]
        dice = torch.cat([dice_pos, dice_neg])

        dice_neg = np.nan_to_num(dice_neg.mean().item(), 0)
        dice_pos = np.nan_to_num(dice_pos.mean().item(), 0)
        dice = dice.mean().item()

        num_neg = len(neg_index)
        num_pos = len(pos_index)

        return dice, dice_neg, dice_pos, num_neg, num_pos

    def _get_prediction(self, probs, threshold):
        pdb.set_trace()
        preds = (probs > threshold).float()
        return preds

    def _cal_iou(self, outputs, labels, classes, only_present = True):
        pdb.set_trace()
        ious = []
        for c in classes:
            label_c = labels == c
            if only_present and np.sum(label_c) == 0:
                ious.append(np.nan)
                continue
            pred_c = outputs == c
            intersection = np.logical_and(pred_c, label_c).sum()
            union = np.logical_or(pred_c, label_c).sum()
            if union != 0:
                ious.append(intersection / union)

        return ious if ious else [1]


#!/usr/bin/python
#coding=utf-8
import random

class SeqDB():
    def __init__(self, attribute_num=20, cus_num=40, object_attribute_rate=0.3):
        self.attribute_list = ['a_%d' % att for att in range(attribute_num)]
        #self.cus_list = ['o_%d' % obj for obj in range(cus_num)]
        self.object_list = []
        self.attribute_weight = {}
        for i in range(attribute_num):
            self.attribute_weight[i] = random.randint(0, 10)
        self.Seq_DB = {}

        #createRandomDB
        num = int(attribute_num * object_attribute_rate)
        for i in range(cus_num):       # all customer number
            self.Seq_DB[i] = []
            times = random.randint(1, 5)    #one custom has times sequence
            for j in range(times):          #随机函数产生不同也不同
                oneline = []
                for k in range(attribute_num):
                    oneline.append(0)
                random_index = [random.randint(0, attribute_num-1) for one in range(num)]
                for k in range(num):
                    oneline[random_index[k]] = 1
                tp = [ k for k in range(attribute_num) if oneline[k] == 1 ]
                self.Seq_DB[i].append(tp)
                #random_num = random.randint(1, num)
                #for k in range(random_num):
                #    index = random.randint(0, attribute_num-1)
                    #if not self.att_info[self.att_list[index]] in oneline:
                    #    oneline.append(self.att_info[self.att_list[index]])'a_%d' %
                #    if not index in oneline:
                #        oneline.append(index)

                #random_index = [random.randint(0, self.att_num-1) for one in range(num)]
                #for k in random_index:
                    #if not self.att_list[k] in oneline:
                        #oneline.append(self.att_list[k])
                    #if not self.att_info[self.att_list[k]] in oneline:
                    #    oneline.append(self.att_info[self.att_list[k]])#这边可以省略att_list
                #self.object_list.append('obj_%d_%d' % (i, j))
                self.object_list.append('obj_%d' % i)
                #self.Seq_DB[i].append(oneline)

    def __str__(self):
        str = 'the Sequence DB is:\n'
        for i in self.Seq_DB:
            str += 'cid is %d:\n----his sequence\n' % i
            for j in self.Seq_DB[i]:
                str += '%s\n' % j
        return str


from __future__ import division, print_function, unicode_literals

from pysped.xml_sped import *
from pysped.nfse.versao_100 import ESQUEMA_ATUAL
import os

DIRNAME = os.path.dirname(__file__)

class ChaveNFe(XMLNFe):
    def __init__(self):
        super(ChaveNFe, self).__init__()
        self.InscricaoPrestador   = TagCaracter(nome='InscricaoPrestador'  , tamanho=[ 6,  11]   , raiz='//*/ChaveNFe')
        self.NumeroNFe            = TagInteiro(nome='NumeroNFe'            , tamanho=[ 1,  12, 1], raiz='//*/ChaveNFe')
        self.CodigoVerificacao    = TagCaracter(nome='CodigoVerificacao'   , tamanho=[ 1, 255]   , raiz='//*/ChaveNFe')
        self.RazaoSocialPrestador = TagCaracter(nome='RazaoSocialPrestador', tamanho=[ 1, 120]   , raiz='//*/ChaveNFe')

    def get_xml(self):
        if self.InscricaoPrestador.valor.strip() == '':
            return ''

        xml = XMLNFe.get_xml(self)
        xml += '<ChaveNFe>'
        xml += self.InscricaoPrestador.xml
        xml += self.NumeroNFe.xml
        xml += self.CodigoVerificacao.xml
        xml += self.RazaoSocialPrestador.xml
        xml += '</ChaveNFe>'
        return xml

    def set_xml(self, arquivo):
        if self._le_xml(arquivo):
            self.InscricaoPrestador.xml   = arquivo
            self.NumeroNFe.xml            = arquivo
            self.CodigoVerificacao.xml       = arquivo
            self.RazaoSocialPrestador.xml = arquivo

    xml = property(get_xml, set_xml)

class ChaveRPS(XMLNFe):
    def __init__(self):
        super(ChaveRPS, self).__init__()
        self.InscricaoPrestador   = TagCaracter(nome='InscricaoPrestador'  , tamanho=[ 6,  11]   , raiz='//*/ChaveRPS')
        self.SerieRPS             = TagCaracter(nome='SerieRPS'            , tamanho=[ 2,   2]   , raiz='//*/ChaveRPS', valor='NF')
        self.NumeroRPS            = TagInteiro(nome='NumeroRPS'            , tamanho=[ 1,  12, 1], raiz='//*/ChaveRPS')
        self.DataEmissaoRPS       = TagDataHora(nome='DataEmissaoRPS'                            , raiz='//*/ChaveRPS')
        self.RazaoSocialPrestador = TagCaracter(nome='RazaoSocialPrestador', tamanho=[ 1, 120]   , raiz='//*/ChaveRPS')

    def get_xml(self):
        if self.InscricaoPrestador.valor.strip() == '':
            return ''

        xml = XMLNFe.get_xml(self)
        xml += '<ChaveRPS>'
        xml += self.InscricaoPrestador.xml
        xml += self.SerieRPS.xml
        xml += self.NumeroRPS.xml
        xml += self.DataEmissaoRPS.xml
        xml += self.RazaoSocialPrestador.xml
        xml += '</ChaveRPS>'
        return xml

    def set_xml(self, arquivo):
        if self._le_xml(arquivo):
            self.InscricaoPrestador.xml   = arquivo
            self.SerieRPS.xml             = arquivo
            self.NumeroRPS.xml            = arquivo
            self.DataEmissaoRPS.xml       = arquivo
            self.RazaoSocialPrestador.xml = arquivo

    xml = property(get_xml, set_xml)

class Alerta(XMLNFe):
    def __init__(self):
        super(Alerta, self).__init__()
        self.Codigo    = TagInteiro(nome='Codigo'    , tamanho=[3, 4, 3], raiz='//Alerta')
        self.Descricao = TagCaracter(nome='Descricao', tamanho=[0, 300] , raiz='//Alerta')
        self.ChaveRPS = ChaveRPS()
        self.ChaveNFe = ChaveNFe()

    def get_xml(self):
        xml = XMLNFe.get_xml(self)
        xml += '<Alerta>'
        xml += self.Codigo.xml
        xml += self.Descricao.xml
        xml += self.ChaveRPS.xml
        xml += self.ChaveNFe.xml
        xml += '</Alerta>'
        return xml

    def set_xml(self, arquivo):
        if self._le_xml(arquivo):
            self.Codigo.xml    = arquivo
            self.Descricao.xml = arquivo
            self.ChaveRPS.xml  = arquivo
            self.ChaveNFe.xml  = arquivo

    xml = property(get_xml, set_xml)

class Erro(XMLNFe):
    def __init__(self):
        super(Erro, self).__init__()
        self.Codigo    = TagInteiro(nome='Codigo'    , tamanho=[3, 4, 3], raiz='//Erro')
        self.Descricao = TagCaracter(nome='Descricao', tamanho=[0, 300] , raiz='//Erro')
        self.ChaveRPS = ChaveRPS()
        self.ChaveNFe = ChaveNFe()

    def get_xml(self):
        xml = XMLNFe.get_xml(self)
        xml += '<Erro>'
        xml += self.Codigo.xml
        xml += self.Descricao.xml
        xml += self.ChaveRPS.xml
        xml += self.ChaveNFe.xml
        xml += '</Erro>'
        return xml

    def set_xml(self, arquivo):
        if self._le_xml(arquivo):
            self.Codigo.xml    = arquivo
            self.Descricao.xml = arquivo
            self.ChaveRPS.xml  = arquivo
            self.ChaveNFe.xml  = arquivo

    xml = property(get_xml, set_xml)


import kivy
import math

kivy.require("1.11.1")

from kivy.core.window import Window
from kivy.app import App
from kivy.uix.gridlayout import GridLayout
from kivy.uix.button import Button
from kivy.lang import Builder
from fractions import Fraction

class CalcGridLayout(GridLayout):
    Window.size = (320, 500)

    def fraction(self, j):
        if "=" in j:
            s = j.split("\n=")
            j = (str(eval(s[1])))
            if "." in j:
                self.display.text = s[0] + "\n=" + str(Fraction(float(j)).limit_denominator(1000))
            elif "/" in j:
                self.display.text = j + "\n=" + str(eval(j))

        else:
            self.display.text = j + "\n=" + str(eval(j))

    def sign(self, input):
        if input:
            c = []
            if "=" in input:
                c = input.split("\n=")
            else:
                c.append(0)
                c.append(input)
            try:
                if c[1][0] == "-":
                    self.display.text = c[1][1:]
                else:
                    self.display.text = "-" + c[1]
            except Exception:
                pass

    def calculate(self, calculation):
        g = calculation
        if calculation:
            try:
                if "%" in calculation:
                    c = calculation.split("%")
                    calculation = "/100".join(c)
                if "\u03C0" in calculation:
                    c = calculation.split("\u03C0")
                    calculation = "(22/7)".join(c)
                if "^" in calculation:
                    c = calculation.split("^")
                    calculation = "**".join(c)
                if "\u00B2" in calculation:
                    c = calculation.split("\u00B2")
                    calculation = "**2".join(c)
                if "=" in calculation:
                    s = calculation.split("\n=")
                    self.display.text = (str(eval(s[1])))
                if "=" not in calculation:
                    self.display.text = g + "\n=" + str(eval(calculation))

            except Exception:
                self.display.text = "Error"

class CalculatorApp(App):
    def build(self):
        return CalcGridLayout()

CalcApp = CalculatorApp()
CalcApp.run()


#!/usr/bin/python3
# -*- coding: utf8 -*-
"""
说明: 环境变量名`KXDAO_COOKIE`
cron: 25 7 * * *
new Env('科学刀-签到');
"""
import requests
import re
import os
from sendNotify import send
import time

h = requests.Session()
List = []

def main(cookie):
    h.headers.update({
        'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/92.0.4515.107 Safari/537.36'})
    hash_url = 'https://www.kxdao.net/space-uid-74943.html'
    hash_headers = {
        'Host': 'www.kxdao.net',
        'Referer': 'https://www.kxdao.net/plugin.php',
        'Accept-Encoding': 'gzip, deflate, br',
        'Accept-Language': 'zh-CN,zh;q=0.9',
        'Cookie': cookie
    }
    hash_r = h.get(url=hash_url, headers=hash_headers)
    try:
        formhash = re.findall('name="formhash" value="(.*?)" />', hash_r.text)[0]
    except Exception as e:
        List.append(f'{str(e)}')
        return

    check_url = 'https://www.kxdao.net/plugin.php'
    # https://www.kxdao.net/plugin.php?id=dsu_amupper&ppersubmit=true&formhash=formhash&infloat=yes&handlekey=dsu_amupper&inajax=1&ajaxtarget=fwin_content_dsu_amupper
    check_params = dict(
        id='dsu_amupper',
        ppersubmit='true',
        formhash=formhash,
        infloat='yes',
        handlekey='dsu_amupper',
        inajax='1',
        ajaxtarget='fwin_content_dsu_amupper'
    )
    check_headers = {
        'referer': 'https://www.kxdao.net/',
        'accept-encoding': 'gzip, deflate, br',
        'accept-language': 'zh-CN,zh;q=0.9',
        'Cookie': cookie
    }
    check_r = h.get(url=check_url, headers=check_headers, params=check_params).text
    try:
        qd = re.findall('
(.*?)
', check_r)[0]
        List.append(f'签到结果：{qd}')
    except Exception as e:
        List.append(f'{str(e)}')
        return
    i_url = 'https://www.kxdao.net/home.php?mod=spacecp&ac=credit&showcredit=1'
    i_headers = {
        'Host': 'www.kxdao.net',
        'referer': 'https://www.kxdao.net/',
        'Cookie': cookie
    }
    i_r = h.get(url=i_url, headers=i_headers).text

    try:
        db = re.findall('class="xi1 cl"> DB: (.*?)&nbsp', i_r)[0]
        jf = re.findall('
积分: (.*?)', i_r)[0]
        List.append(f'用户DB：{db[:-2]}，积分{jf}')
    except Exception as e:
        List.append(f'{str(e)}')

if __name__ == '__main__':
    i = 0
    if 'KXDAO_COOKIE' in os.environ:
        users = os.environ['KXDAO_COOKIE'].split('&')
        for x in users:
            i += 1
            List.append(f'===> [账号{str(i)}]Start <===')
            main(x)
            List.append(f'===> [账号{str(i)}]End <===\n')
            time.sleep(1)
        tt = '\n'.join(List)
        print(tt)
        send('科学刀', tt)
    else:
        print('未配置环境变量')
        send('科学刀', '未配置环境变量')


# Databricks notebook source
# MAGIC %md
# MAGIC ## Token Recommendation
# MAGIC

# MAGIC

# MAGIC     Your application should allow a specific wallet address to be entered via a widget in your application notebook.  Each time a new wallet address is entered, a new recommendation of the top tokens for consideration should be made.
 **Bonus** (3 points): include links to the Token contract on the blockchain or etherscan.io for further investigation.

# MAGIC

# COMMAND ----------

# MAGIC %run ./includes/utilities

# COMMAND ----------

# MAGIC %run ./includes/configuration

# COMMAND ----------

# Grab the global variables
wallet_address,start_date = Utils.create_widgets()
print(wallet_address,start_date)

# COMMAND ----------

# MAGIC %md
# MAGIC ## Your code starts here...

# COMMAND ----------

import mlflow
from pyspark.sql import functions as F
import pandas as pd
class ALS_prediction():

    def __init__(self, ALS_model):
        self.als = ALS_model
        self.triplet_subset = spark.table("g10_db.silver_tokenmatrix")
        self.token_meta = spark.table("g10_db.silvertokenmetadata")

    def preprocess_input(self, userID):
        '''return pre-processed model_input'''
        used_tokens_list = []
        print(userID)
        # generate dataframe of unlistened songs
        unused_tokens = self.triplet_subset.select(col('token_id').alias("tokenID")).withColumn('userID', F.lit(userID)).distinct()

        return unused_tokens

    def postprocess_result(self,processed_input, results):

        results = results.filter(results.prediction != float('nan'))
        results = results.withColumn("prediction", F.abs(F.round(results["prediction"],0)))
        print(results.printSchema())
        print('Predicted Tokens:')
        #processed_input.select(col('tokenID').alias("token_id"),"userID","prediction")
        return results.join(self.token_meta, results.tokenID==self.token_meta.token_id) \
                 .select("*") \
                 .orderBy('prediction', ascending = False)

    def prediction(self, model_input):
        processed_model_input = self.preprocess_input(model_input)
        display(processed_model_input)
        results = self.als.transform(processed_model_input)
        return self.postprocess_result(processed_model_input,results)

# COMMAND ----------

user_id_mapping = spark.table("g10_db.silver_userid_mapping")
user_id_mapping.show(5)

# COMMAND ----------

user_id_mapping.count()

# COMMAND ----------

user_id_mapping.select("from_address").toPandas().iloc[0]

# COMMAND ----------

e = user_id_mapping.select("user_id").where(col("from_address")==wallet_address)
e = e.toPandas()
user_id_exist = 0
if e.shape[0]>0:
    u_id = e.toPandas().user_id.iloc[0]
    user_id_exist = 1

# COMMAND ----------

from mlflow.tracking import MlflowClient
client = MlflowClient()
model_versions = []
modelName = 'G10_model'

# COMMAND ----------

prod_model = mlflow.spark.load_model('models:/'+modelName+'/Production')
prod_model

# COMMAND ----------

if user_id_exist==1:
    prod_object = ALS_prediction(prod_model)
    recommendaton_out = prod_object.prediction(model_input = int(u_id))

# COMMAND ----------

if user_id_exist==1:
    body_text = "
Recommend Tokens for User address

"+wallet_address+"
"

    comp_table_text = "
 "
    reco_out = recommendaton_out.toPandas()
    for i in range(5):
        img = reco_out["image"].iloc[i]
        print(img)
        token_name = reco_out["name"].iloc[i]
        token_link = reco_out["links"].iloc[i]
        token_address = reco_out["token_address"].iloc[i]
        ether_link = "https://etherscan.io/token/"+token_address
        table_text = "
 	 "+ token_name+"	 Link
"
        comp_table_text = comp_table_text + table_text

    comp_table_text = comp_table_text + "
"
else:
    body_text = "
Recommend Tokens for User address

"+wallet_address+"
"
    comp_table_text= "
Wallet Address does not exist in a time range
"
html_text = body_text + " "+ comp_table_text

print(html_text)

displayHTML(html_text)

# COMMAND ----------

# COMMAND ----------

# Return Success
dbutils.notebook.exit(json.dumps({"exit_code": "OK"}))


class Solution:

    # @classmethod
    # def fibo(cls, n):
    #     if n == 0:
    #         return 0
    #     elif n == 1 or n == 2:
    #         return 1
    #     else:
    #         return Solution.fibo(n - 1) + Solution.fibo(n - 2)

    @classmethod
    def fibo(cls, n):
        res = [0, 1, 1]
        if n <= 2:
            return res[n]
        else:
            for i in range(3, n + 1):
                res[1], res[2] = res[2], res[1] + res[2]
            return res[2]

    def Fibonacci(self, n):
        return Solution.fibo(n)

if __name__ == '__main__':
    print(Solution().Fibonacci(0))
    print(Solution().Fibonacci(8))


import unittest
from unittest.mock import patch, DEFAULT
from trollmoves.mirror import parse_args, MoveItMirror
from tempfile import NamedTemporaryFile
import pytest

class TestMirrorDeleter(unittest.TestCase):
    """Test the deleter."""

    def test_empty_init_arguments_does_not_crash(self):
        """Test that no arguments to init works."""
        from trollmoves.mirror import MirrorDeleter
        MirrorDeleter()  # noqa

    def test_calling_delete_with_just_filename_does_not_crash(self):
        """Test that calling delete with just the filename does not crash."""
        from trollmoves.mirror import MirrorDeleter
        deleter = MirrorDeleter()
        deleter.delete("some_filename")

class TestMirrorRequestManager(unittest.TestCase):
    """Test the MRM."""

    def test_deleter_gets_attrs(self):
        """Test that the deleter gets the right info on init."""
        from trollmoves.mirror import MirrorRequestManager
        attrs = {'origin': 'here'}

        with patch("trollmoves.mirror.MirrorDeleter", autospec=True) as md:
            with patch.multiple("trollmoves.server", Poller=DEFAULT, get_context=DEFAULT):
                MirrorRequestManager("some_port", attrs)  # noqa
                assert md.call_args[0][0] == attrs

config_file = b"""
[eumetcast-hrit-0deg]
origin = /local_disk/tellicast/received/MSGHRIT/H-000-{nominal_time:%Y%m%d%H%M}-{compressed:_<2s}
request_port = 9094
publisher_port = 9010
info = sensor=seviri;variant=0DEG
topic = /1b/hrit-segment/0deg
delete = False
"""

class TestMoveItMirror:
    """Test the move it mirror."""

    def test_reloads_config_crashes_when_config_file_does_not_exist(self):
        """Test that reloading a non existing config file crashes."""
        cmd_args = parse_args(["--port", "9999", "somefile99999.cfg"])
        mirror = MoveItMirror(cmd_args)
        with pytest.raises(FileNotFoundError):
            mirror.reload_cfg_file(cmd_args.config_file)

    @patch("trollmoves.move_it_base.Publisher")
    def test_reloads_config_on_example_config(self, fake_publisher):
        """Test that config can be reloaded with basic example."""
        with NamedTemporaryFile() as temporary_config_file:
            temporary_config_file.write(config_file)
            config_filename = temporary_config_file.name
            cmd_args = parse_args(["--port", "9999", config_filename])
            mirror = MoveItMirror(cmd_args)
            mirror.reload_cfg_file(cmd_args.config_file)

    @patch("trollmoves.move_it_base.Publisher")
    @patch("trollmoves.mirror.MoveItMirror.reload_config")
    def test_reloads_config_calls_reload_config(self, mock_reload_config, mock_publisher):
        """Test that config file can be reloaded."""
        with NamedTemporaryFile() as temporary_config_file:
            temporary_config_file.write(config_file)
            config_filename = temporary_config_file.name
            cmd_args = parse_args(["--port", "9999", config_filename])
            mirror = MoveItMirror(cmd_args)
            mirror.reload_cfg_file(cmd_args.config_file)
            mock_reload_config.assert_called_once()

    @patch("trollmoves.move_it_base.Publisher")
    @patch("trollmoves.mirror.MoveItMirror.reload_config")
    def test_signal_reloads_config_calls_reload_config(self, mock_reload_config, mock_publisher):
        """Test that config file can be reloaded through signal."""
        with NamedTemporaryFile() as temporary_config_file:
            temporary_config_file.write(config_file)
            config_filename = temporary_config_file.name
            cmd_args = parse_args([config_filename])
            client = MoveItMirror(cmd_args)
            client.signal_reload_cfg_file()
            mock_reload_config.assert_called_once()


import onnx

from gui import utils
from onnx import numpy_helper

from model.onxx_dataflow.graph_dims import GraphDims
from model.onxx_dataflow.graph_properties import Node

class Graph:
    def __init__(self, path):
        self.path = path
        self.model = None
        self.onnx_nodes = []

    def identify_model_graph(self):
        # Reset node ids for every model
        Node.type_id = {}

        # Note: Different versions or missing operators are beyond our scope
        model = onnx.load(self.path)
        onnx.checker.check_model(model)

        # Extract model parameters
        onnx_initializers = {}
        for initializer in model.graph.initializer:
            w = numpy_helper.to_array(initializer)
            onnx_initializers[initializer.name] = w

        # Extract model layers
        onnx_nodes_inputs = {}
        onnx_nodes_outputs = {}
        for i, node_data in enumerate(model.graph.node):
            self.onnx_nodes.append(Node(node_data))
            onnx_nodes_inputs[self.onnx_nodes[i].name] = node_data.input
            onnx_nodes_outputs[self.onnx_nodes[i].name] = node_data.output

        # Create a parallel model to identify the output of every layer
        graph_outputs = GraphDims(self.path, onnx_nodes_outputs)

        # Assuming that the model will have a single input/output
        self.onnx_nodes[0].inputs[0] = "MODEL_INPUT " + graph_outputs.identify_node_dim()
        self.onnx_nodes[-1].output[0] = graph_outputs.identify_node_dim(self.onnx_nodes[-1].name) + " MODEL_OUTPUT"

        # Connect model layers and parameters
        for node in self.onnx_nodes:
            node.identify_node_inputs(onnx_nodes_outputs, graph_outputs.identify_node_dim)
            node.identify_node_output(onnx_nodes_inputs, graph_outputs.identify_node_dim)
            node.identify_node_parameters(onnx_initializers)

        # Update graph nodes types to match the extracted names
        # so that netron defaults will give a desired outcome
        for node in self.onnx_nodes:
            node.update_graph_node_name()

        # Make sure the replica model is in the output dir
        self.model = model
        self.path = self.path[self.path.rfind('/') + 1:]

        return self.path

    def save(self):
        selected_path = utils.choose_folder_dialog('Choose output folder')
        if not selected_path:
            return None

        dir_path = selected_path + "/output"
        utils.delete_folder(dir_path)
        utils.create_folder(dir_path)

        onnx.save(self.model, dir_path + '/' + self.path)

        for node in self.onnx_nodes:
            node.save(dir_path)

        return dir_path


from os import system, name
import random

def limpa_tela():
    if name == 'nt':
        _ = system('cls')

    else:
        _ = system('clear')

def game():

    limpa_tela()

    print('\nBem-vindo ao jogo da forca!\n\nAdivinhe a palavra abaixo:\n')

    palavras = ['banana', 'uva', 'morango', 'laranja']

    palavra = random.choice(palavras)

    letras_descobertas = ['_' for letra in palavra]

    chances = 6

    letras_erradas = []

    while chances > 0:
        limpa_tela()
        print(' '.join(letras_descobertas))
        print('\nChances restantes: ',chances)
        print('Letras erradas: ',' '.join(letras_erradas))

        tentativa = input('\nDigite uma letra: ').lower()

        if tentativa in palavra:
            index = 0

            for letra in palavra:
                if tentativa == letra:
                    letras_descobertas[index] = letra
                index+= 1

        else:
            chances -= 1
            letras_erradas.append(tentativa)

        if '_' not in letras_descobertas:
            print('\nVocê venceu, a palavra era: ',palavra)
            break

    if '_' in letras_descobertas:
        print('\nVocê perdeu, a palavra era: ',palavra)

if __name__ == '__main__':
    game()


import os.path

import torch
import numpy as np
from os import path as osp
import tqdm

from human_body_prior.tools.omni_tools import copy2cpu as c2c
from human_body_prior.body_model.body_model import BodyModel

# Not used here
# Joint order conversion will be handled in the downstream code

# h36m_regressor_reorder = [6, 5, 4,  # right leg
#                           1, 2, 3,  # left leg]
#                           0,  # root
#                           8, 7,  # neck, thorax
#                           9, 10,  # head
#                           16, 15, 14,  # right arm
#                           11, 12, 13,  # left arm
#                           ]

def batch_slice_indices(total, batch_size):
    starts = list(range(0, total, batch_size))
    ends = starts[1:]
    ends.append(total)
    indices = list(zip(starts, ends))
    return indices

def resample_to_lower_framerate(pose_sequence, src_frame_rate, target_frame_rate):
    assert target_frame_rate <= src_frame_rate
    T = 1 / src_frame_rate
    T_new = 1 / target_frame_rate
    duration = pose_sequence.shape[0] * T
    resampled_length = np.floor(duration / T_new)

    # Timestamps where to sample
    t = np.arange(resampled_length).astype(np.float64) * T_new
    # Fractional indices into old timestamps
    ts = t / T
    t_floor, t_ceil = np.floor(ts), np.ceil(ts)
    assert np.all(t_ceil < pose_sequence.shape[0])
    # Weighting for next pose, zero
    w2 = ts - t_floor
    # Weighting for previous pose
    w1 = 1. - w2
    # Generate resampled poses via weighted sum
    resampled_poses = (pose_sequence[t_floor.astype(np.int)] * w1[:, np.newaxis, np.newaxis]) + (
                pose_sequence[t_ceil.astype(np.int)] * w2[:, np.newaxis, np.newaxis])
    return resampled_poses

def convert_amass_to_3dkeypoint_sequence(path, body_models, joint_regressor_path, batch_size, use_dmpls=True,
                                         verbose=False):
    assert os.path.exists(path)
    required_fields = ['trans', 'gender', 'mocap_framerate', 'betas', 'poses']
    if use_dmpls:
        required_fields.append("dmpls")
    # Choose the device to run the body model on.
    comp_device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    bdata = np.load(path)
    complete = [k in bdata.keys() for k in required_fields]
    if not complete:
        print(f"{path} incomplete. Skipping ...")
        return None

    frame_rate = bdata["mocap_framerate"].item()

    subject_gender = bdata['gender']
    if "U" not in str(subject_gender.dtype):
        subject_gender = np.char.decode(bdata["gender"], encoding="utf-8")
    subject_gender = str(subject_gender)

    if verbose:
        print('Data keys available:%s' % list(bdata.keys()))
        print('The subject of the mocap sequence is  {}.'.format(subject_gender))
        print(f'The mocap sequence has {bdata["poses"].shape[0]} frames with framerate of {bdata["mocap_framerate"]}')

    with torch.no_grad():
        bm = body_models[subject_gender]
        regressor = np.load(joint_regressor_path)
        torch_regressor = torch.Tensor(regressor).to(comp_device)
        time_length = len(bdata['trans'])
        batch_slices = batch_slice_indices(total=time_length, batch_size=batch_size)
        # Output array
        keypoint_sequence = np.zeros((time_length, regressor.shape[0], 3), dtype=np.float32)

        # Process in fixed batches
        for start, end in batch_slices:
            # Frame-specific params
            body_parms = {
                'root_orient': torch.Tensor(bdata['poses'][start: end, :3]).to(comp_device),
                # controls the global root orientation
                'pose_body':   torch.Tensor(bdata['poses'][start: end, 3:66]).to(comp_device),  # controls the body
                'pose_hand':   torch.Tensor(bdata['poses'][start: end, 66:]).to(comp_device),
                # controls the finger articulation
                'betas':       torch.Tensor(
                    np.repeat(bdata['betas'][:num_betas][np.newaxis], repeats=(end - start), axis=0)).to(
                    comp_device),  # controls the body shape. Body shape is static
                'trans':       torch.Tensor(bdata['trans'][start:end]).to(comp_device),
                # controls the global body position
            }
            if use_dmpls:
                body_parms['dmpls'] = torch.Tensor(bdata['dmpls'][start: end, :num_dmpls]).to(
                    comp_device)  # controls soft tissue dynamics]

            if verbose:
                print('Body parameter vector shapes: \n{}'.format(
                    ' \n'.join(['{}: {}'.format(k, v.shape) for k, v in body_parms.items()])))

            # Create body model, shape it based on params in batch mode
            shaped_body_model = bm(return_dict=True, **{k: v for k, v in body_parms.items()})

            vertices = shaped_body_model["v"]
            keypoint_batch = torch.einsum('bik,ji->bjk', [vertices, torch_regressor])
            keypoint_batch = c2c(keypoint_batch)
            keypoint_sequence[start:end] = keypoint_batch
            del (shaped_body_model)

    return keypoint_sequence, frame_rate

def mkdirs(path):
    if not os.path.exists(path):
        os.makedirs(path)

def expandpath(path):
    x = os.path.expanduser(path)
    x = os.path.realpath(x)
    x = os.path.abspath(x)
    return x

if __name__ == '__main__':
    import argparse

    # Parse command line arguments
    parser = argparse.ArgumentParser(
        description='Convert AMASS to H36m compatible sequences')
    parser.add_argument('--amass_dir', required=True,
                        metavar="/path/to/amass",
                        help='Directory of the AMASS datasets')
    parser.add_argument('--out_dir', required=True,
                        metavar="/path/to/output",
                        help='Output directory')
    parser.add_argument("--joint_regressor", required=True,
                        metavar="/path/to/joint_regressor.npy",
                        help='Joint regressor')
    parser.add_argument('--r', required=False,
                        metavar="framerate",
                        default=None,
                        help='Target frame rate for pose sequence resampling. If empty, retains the original frame rate for each pose sequence.',
                        type=float)
    parser.add_argument('--gpu_id', required=False,
                        default=None,
                        metavar="gpu_id",
                        help='GPU ID. If empty, use CPU',
                        type=str)
    parser.add_argument('--batch_size', required=False,
                        default=2048,
                        metavar="batchsize",
                        help='Batchsize for processing SMPL meshes in parallel.',
                        type=int)

    args = parser.parse_args()

    os.environ["CUDA_DEVICE_ORDER"] = "PCI_BUS_ID"
    # os.environ["CUDA_VISIBLE_DEVICES"] = "0"
    os.environ["CUDA_VISIBLE_DEVICES"] = "" if args.gpu_id is None else str(args.gpu_id)
    # print(torch.cuda.device_count())

    USE_DMPLS = True
    SUPPORT_DIR = expandpath(os.path.join("..", "support_data"))
    # Choose the device to run the body model on.
    comp_device = torch.device("cuda" if torch.cuda.is_available() else "cpu")

    args.amass_dir = expandpath(args.amass_dir)
    args.out_dir = expandpath(args.out_dir)
    mkdirs(args.out_dir)
    args.joint_regressor = expandpath(args.joint_regressor)

    num_betas = 16  # number of body parameters
    num_dmpls = 8 if USE_DMPLS is True else None  # number of DMPL parameters
    body_models = {}
    # Generate Body odels
    for gender in ["male", "female", "neutral"]:
        bm_fname = osp.join(SUPPORT_DIR, 'body_models/smplh/{}/model.npz'.format(gender))
        dmpl_fname = osp.join(SUPPORT_DIR, 'body_models/dmpls/{}/model.npz'.format(gender))
        if USE_DMPLS is False:
            dmpl_fname = None
        bm = BodyModel(bm_fname=bm_fname, num_betas=num_betas, num_dmpls=num_dmpls, dmpl_fname=dmpl_fname).to(
            comp_device)
        bm.eval()
        body_models[gender] = bm

    def list_sorted_dirs(path):
        return [d for d in sorted(os.listdir(path)) if os.path.isdir(os.path.join(path, d))]

    def list_sorted_files(path):
        return [d for d in sorted(os.listdir(path)) if os.path.isfile(os.path.join(path, d))]

    datasets = list_sorted_dirs(args.amass_dir)

    for dataset in datasets:
        print(dataset)
        dataset_path = os.path.join(args.amass_dir, dataset)

        # Check for inner directory
        content = list_sorted_dirs(dataset_path)
        if len(content) == 1:
            subjects_dir = os.path.join(dataset_path, content[0])
        else:
            subjects_dir = dataset_path

        out_path = os.path.join(args.out_dir, f"{dataset}.npz")
        # if os.path.exists(out_path):
        #     continue
        output_dir = {}

        # Loop through subject dirs
        subjects = list_sorted_dirs(subjects_dir)
        with tqdm.tqdm(subjects) as t_subjects:
            for subject in t_subjects:
                t_subjects.set_description(subject, refresh=True)
                output_dir[subject] = {}
                subject_path = os.path.join(subjects_dir, subject)

                # Filter out shape files
                # Loop through sequences
                sequences = [s for s in list_sorted_files(subject_path) if s != "shape.npz"]
                for sequence in sequences:
                    sequence_path = os.path.join(subject_path, sequence)

                    # Convert sequence
                    converted, frame_rate = convert_amass_to_3dkeypoint_sequence(path=sequence_path,
                                                                                body_models=body_models,
                                                                                joint_regressor_path=args.joint_regressor,
                                                                                batch_size=args.batch_size,
                                                                                use_dmpls=True)
                    if args.r is not None:
                        converted = resample_to_lower_framerate(converted, src_frame_rate=frame_rate,
                                                                target_frame_rate=args.r)
                        frame_rate = args.r

                    if converted is not None:
                        output_dir[subject][os.path.splitext(sequence)[0]] = {"positions_3d": converted,
                                                                              "frame_rate":   frame_rate}

        print(f'Saving to {out_path} ...')
        np.savez_compressed(out_path, positions_3d=output_dir)
        print('... done.')


import os
import pandas as pd
import matplotlib.pyplot as plt
import matplotlib.patches as mpatches
from matplotlib.ticker import MultipleLocator

home = os.getcwd()

try:
    os.mkdir('visualizations/')
except FileExistsError:
    print(f'Directory already Exists')
    print(f'')

    # collect inputs on the start and stop year for data visualizations,
    # and if use wants the files to be saved
save = input('Save Graphs as PNG y or n? ')
print()
start_year = input('Enter starting year for data visualizations. ').strip()
print()
end_year = input('Enter ending year for data visualizations. ').strip()

start_year = int(start_year)
end_year = int(end_year)

def files_to_lists(file_folder):
    '''    finds files in folder specified by directory

           return list of file_names and list of file_paths respectively

       :param: file_folder - dtype:string -  the name / file path from current working directory to directory for
       collecting filenames/filepaths

       :return: separate lists of both file_name and file_path

    '''
    # assign directory
    directory = f'compiled_data/{file_folder}'
    file_name_list = []
    file_path_list = []

    # iterate over files in
    # that directory
    for filename in os.listdir(directory):
        file_path = os.path.join(directory, filename)
        # checking if it is a file
        if os.path.isfile(file_path):
            # if true: frop file name and path into list as string
            file_name_list.append(filename)
            file_path_list.append(file_path)
    return file_name_list, file_path_list

def week_to_year_dataframes():

    directory = os.getcwd()
    directory_file_list = os.listdir(f'{directory}/compiled_data/')

    # this will remove all names from the list than cannot be made into a number
    # while also converting all strings into integers
    for i,name in enumerate(directory_file_list):
        try:
            directory_file_list[i] = int(name)
        except ValueError:
            directory_file_list.remove(name)
            continue

    # create a dictionary to hold all file names and paths separated by the year
    master_file_dict = {}
    master_path_dict = {}
    # start_year, end_year = take_input()
    for folder in directory_file_list:
        file_name_list, file_path_list = files_to_lists(f'{folder}/')
        master_file_dict[f'{folder}'] = file_name_list
        master_path_dict[f'{folder}'] = file_path_list

    # create a dictionary of all dataframes with keys for year then individual dataframes from the years.
    week_to_year_dataframes = {}
    for year in list(range(2014,2023)):
        week_to_year_dataframes[f'{year}'] = {}
        for i,file_path in enumerate(master_path_dict[f'{year}']):
            dataframe = pd.read_csv(file_path)
            string_slice = master_path_dict[f'{year}'][i][24:-4]
            week_to_year_dataframes[f'{year}'][f'{string_slice}'] = dataframe
    return week_to_year_dataframes

def all_years_data_dictionary():
    '''
    the all_years_sales_data folder is navigated to and a list is made of all files within.

    the list is iterated through and a full file path is generated

    the file is checked to see if it is actually a file.

    if true, file is read using pd.read_csv(), then stored in a dictionary using the sliced file name as a key

    dictionary containing all files read as dataframes is returned

    '''

    current_directory = os.getcwd()
    directory_file_list = os.listdir(f'{current_directory}\\compiled_data\\all_years_sales_data\\')

    all_years_data_dictionary = {}
    for file in directory_file_list:
        file_path = f'{current_directory}\\compiled_data\\all_years_sales_data\\{file}'

        if os.path.isfile(file_path):
            file_name = file[:-4]
            dataframe = pd.read_csv(file_path)
            all_years_data_dictionary[f'{file_name}'] = dataframe
        else:
            continue

    return all_years_data_dictionary

################################# Create the dictionaries to use for visualizations ##################################
all_years_data_dictionary = all_years_data_dictionary()
week_to_year_dataframes = week_to_year_dataframes()
######################################################################################################################

title = f'Average Sales per Shift, per Year'

# for year in years
# make dataframe, add shifts AM and PM to make one entry for each
# create df from agg values, plot df
# get lines as list and aply labels to lines, then set mets data and save the plot
for year in range(start_year,end_year+1):

    df = week_to_year_dataframes[f'{year}'][f'shift_sales_summary']

    df = df.drop(columns=['Royalty Sales'])

    Wed = df['Shift - 1 Wed AM'] + df['Shift - 2 Wed PM']
    Thu = df['Shift - 3 Thu AM'] + df['Shift - 4 Thu PM']
    Fri = df['Shift - 5 Fri AM'] + df['Shift - 6 Fri PM']
    Sat = df['Shift - 7 Sat AM'] + df['Shift - 8 Sat PM']
    Sun = df['Shift - 9 Sun AM'] + df['Shift - 10 Sun PM']
    Mon = df['Shift - 11 Mon AM'] + df['Shift - 12 Mon PM']
    Tue = df['Shift - 13 Tue AM'] + df['Shift - 14 Tue PM']

    agg_values = {
        'Wed':Wed,
        'Thu':Thu,
        'Fri':Fri,
        'Sat':Sat,
        'Sun':Sun,
        'Mon':Mon,
        'Tue':Tue,
    }

    # create df from summed columns
    agg_df = pd.DataFrame(agg_values)

    # create axis from aggregated dataframe, set graph params
    ax = agg_df.mean().plot(kind='line',legend=False, figsize=(19.20,10.80))

    # make a list of all lines fro assigning custom labels
    lines = ax.get_lines()

# for each line, set the label as the start year + loop # to track the years
for i,line in enumerate(lines):
    line.set_label(start_year+i)

plt.xlabel('Day of Week')
plt.ylabel('Sales Amount USD')
plt.title(f'{title}')

plt.grid()
plt.legend()

if save == 'y':
    plt.savefig(f'visualizations/{title}.png')

plt.close()
########################################### Max Sales per Shift, per Year #############################################

title = f'Max Sales per Shift, per Year'

# for year in years
# make dataframe, add shifts AM and PM to make one entry for each
# create df from agg values, plot df
# get lines as list and aply labels to lines, then set mets data and save the plot

for year in range(start_year,end_year+1):

    df = week_to_year_dataframes[f'{year}'][f'shift_sales_summary']

    df = df.drop(columns=['Royalty Sales'])

    Wed = df['Shift - 1 Wed AM'] + df['Shift - 2 Wed PM']
    Thu = df['Shift - 3 Thu AM'] + df['Shift - 4 Thu PM']
    Fri = df['Shift - 5 Fri AM'] + df['Shift - 6 Fri PM']
    Sat = df['Shift - 7 Sat AM'] + df['Shift - 8 Sat PM']
    Sun = df['Shift - 9 Sun AM'] + df['Shift - 10 Sun PM']
    Mon = df['Shift - 11 Mon AM'] + df['Shift - 12 Mon PM']
    Tue = df['Shift - 13 Tue AM'] + df['Shift - 14 Tue PM']

    agg_values = {
        'Wed':Wed,
        'Thu':Thu,
        'Fri':Fri,
        'Sat':Sat,
        'Sun':Sun,
        'Mon':Mon,
        'Tue':Tue,
    }

    agg_df = pd.DataFrame(agg_values)

    ax = agg_df.max().plot(kind='line',legend=False, figsize=(19.20,10.80))

    lines = ax.get_lines()

for i,line in enumerate(lines):
    line.set_label(start_year+i)

plt.xlabel('Day of Week')
plt.ylabel('Sales Amount USD')
plt.title(f'{title}')

plt.grid()
plt.legend()

if save == 'y':
    plt.savefig(f'visualizations/{title}.png')

plt.close()

########################################### Sum of Sales per Shift, per Year #############################################

title = f'Sum of Sales per Shift, per Year'
# for year in years
# make dataframe, add shifts AM and PM to make one entry for each
# create df from agg values, plot df
# get lines as list and aply labels to lines, then set mets data and save the plot
for year in range(start_year,end_year+1):

    df = week_to_year_dataframes[f'{year}'][f'shift_sales_summary']

    df = df.drop(columns=['Royalty Sales'])

    Wed = df['Shift - 1 Wed AM'] + df['Shift - 2 Wed PM']
    Thu = df['Shift - 3 Thu AM'] + df['Shift - 4 Thu PM']
    Fri = df['Shift - 5 Fri AM'] + df['Shift - 6 Fri PM']
    Sat = df['Shift - 7 Sat AM'] + df['Shift - 8 Sat PM']
    Sun = df['Shift - 9 Sun AM'] + df['Shift - 10 Sun PM']
    Mon = df['Shift - 11 Mon AM'] + df['Shift - 12 Mon PM']
    Tue = df['Shift - 13 Tue AM'] + df['Shift - 14 Tue PM']

    agg_values = {
        'Wed':Wed,
        'Thu':Thu,
        'Fri':Fri,
        'Sat':Sat,
        'Sun':Sun,
        'Mon':Mon,
        'Tue':Tue,
    }

    agg_df = pd.DataFrame(agg_values)

    ax = agg_df.sum().plot(kind='line',legend=False, figsize=(19.20,10.80))

    lines = ax.get_lines()

for i,line in enumerate(lines):
    line.set_label(start_year+i)

plt.xlabel('Day of Week')
plt.ylabel('Sales Amount USD')
plt.title(f'{title}')

plt.grid()
plt.legend()
if save == 'y':
    plt.savefig(f'visualizations/{title}.png')

plt.close()

########################################### Shift Earnings Variance per Shift, per Year #############################################

title = f'Variance percentage of Sales per Shift, per Year'
# for year in years
# make dataframe, add shifts AM and PM to make one entry for each
# create df from agg values, plot df
# get lines as list and aply labels to lines, then set mets data and save the plot
for year in range(start_year,end_year+1):

    df = week_to_year_dataframes[f'{year}'][f'shift_sales_summary']

    df = df.drop(columns=['Royalty Sales'])

    Wed = df['Shift - 1 Wed AM'] + df['Shift - 2 Wed PM']
    Thu = df['Shift - 3 Thu AM'] + df['Shift - 4 Thu PM']
    Fri = df['Shift - 5 Fri AM'] + df['Shift - 6 Fri PM']
    Sat = df['Shift - 7 Sat AM'] + df['Shift - 8 Sat PM']
    Sun = df['Shift - 9 Sun AM'] + df['Shift - 10 Sun PM']
    Mon = df['Shift - 11 Mon AM'] + df['Shift - 12 Mon PM']
    Tue = df['Shift - 13 Tue AM'] + df['Shift - 14 Tue PM']

    agg_values = {
        'Wed':Wed,
        'Thu':Thu,
        'Fri':Fri,
        'Sat':Sat,
        'Sun':Sun,
        'Mon':Mon,
        'Tue':Tue,
    }

    agg_df = pd.DataFrame(agg_values)

    ax = agg_df.var().plot(kind='line',legend=False, figsize=(19.20,10.80))

    lines = ax.get_lines()

for i,line in enumerate(lines):
    line.set_label(start_year+i)

plt.xlabel('Day of Week')
plt.ylabel('Variance Percentage')
plt.title(f'{title}')

plt.grid()
plt.legend()
if save == 'y':
    plt.savefig(f'visualizations/{title}.png')

plt.close()

########################################### Royalty Sales per Shift, per Year #############################################

title = f'Royalty Sales per Shift, per Year'

# set the figure and axis
fig, ax = plt.subplots(figsize = (38.4,10.80), dpi = 200)

# for each year:
#    set the df == year, load x and y, plot, color and label before saving
for year in range(start_year,end_year+1):

    df = week_to_year_dataframes[f'{year}'][f'shift_sales_summary']

    y = df['Royalty Sales']
    x = df['week_ending_date']

    plt.plot(x, y)

    lines = ax.get_lines()

# after all lines are plotted,  set labels == the year through simple math
for i,line in enumerate(lines):
    line.set_label(2014+i)

# for each label not div by zero:
    # set the visibility to false so it doesnt clutter the x axis
every_nth = 12
for n, label in enumerate(ax.xaxis.get_ticklabels()):
    if n % every_nth != 0:
        label.set_visible(False)

# set the spacing for the grid
spacing = 505
# assign the locator to spacing value for even distribution of grid lines
minorlocator = MultipleLocator(spacing)

ax.xaxis.set_minor_locator(minorlocator)
ax.yaxis.set_minor_locator(minorlocator)

ax.grid(which='minor')

# set meta data
plt.xticks(rotation = 45)
plt.xlabel('Week of Sales')
plt.ylabel('Royalty Sales Amount USD')
plt.title(f'{title}')

plt.legend()

if save == 'y':
    plt.savefig(f'visualizations/{title}.png')

plt.close()
############################################ 'Royalty Sales per Shift, per Year - stacked' ############################################
title = f'Royalty Sales per Shift, per Year - stacked'

# set the figure and axis
fig, ax = plt.subplots(figsize = (38.4,10.80), dpi = 200)

# for each year:
#    set the df == year, load x and y, plot, color and label before saving
for year in range(start_year,end_year+1):

    df = week_to_year_dataframes[f'{year}'][f'shift_sales_summary']

    y = df['Royalty Sales']
    x = list(range(0,len(df.index)))

    plt.plot(x, y)

    lines = ax.get_lines()

# after all lines are plotted,  set labels == the year through simple math
for i,line in enumerate(lines):
    line.set_label(2014+i)

# for each label not div by zero:
    # set the visibility to false so it doesnt clutter the x axis
every_nth = 12
for n, label in enumerate(ax.xaxis.get_ticklabels()):
    if n % every_nth != 0:
        label.set_visible(False)

# set the spacing for the grid
spacing = 505
# assign the locator to spacing value for even distribution of grid lines
minorlocator = MultipleLocator(spacing)

ax.xaxis.set_minor_locator(minorlocator)
ax.yaxis.set_minor_locator(minorlocator)

ax.grid(which='minor')

# set meta data
plt.xticks(list(range(0,53)))
plt.xlabel('Week in Year')
plt.ylabel('Royalty Sales Amount USD')
plt.title(f'{title}')

plt.legend()

if save == 'y':
    plt.savefig(f'visualizations/{title}.png')

plt.close()
# plt.show()

############################################ AM/PM Sales dispersion ################################################################

# for each year, make a plt displaying the year of sales per shift as Blue(AM) & Red(PM).
# then save

for year in range(start_year,end_year+1):

    # est. figure
    fig = plt.figure(figsize = (19.20,10.80))

    df = week_to_year_dataframes[f'{year}'][f'shift_sales_summary']

    # royalty sales is not needed for this comparison. Drop it.
    df = df.drop(columns='Royalty Sales')

    # set columns
    cols = df.columns.to_list()
    # remove 'year' from the cols list
    cols = cols[1:]

    # for each column (14 total - 7 AM, 7 PM)
    # make a line for each AM & PM then color Blue/Red

    for col in cols[::2]:
        plt.plot(df[df.columns[0]],df[col], label = 'AM_shift', color = 'b')

    for col in cols[1::2]:
        plt.plot(df[df.columns[0]],df[col], label = 'PM_shift', color = 'r')

    # Rotate the x-ticks for legibility
    plt.xticks(rotation = 45)

    # make grid
    plt.grid()

    # set graph meta data
    plt.xlabel('Week of Sales')
    plt.ylabel('Amount of Sales, USD')
    plt.title(f'{year} Sales Dispersion Am/Pm')

    # estabilish patches, 'artists' that can be called in list format using the .legend function
    blue_patch = mpatches.Patch(color='blue', label='AM Shifts')
    red_patch = mpatches.Patch(color='red', label='PM Shifts')

    plt.legend(handles=[blue_patch,red_patch])

    if save == 'y':
        plt.savefig(f'visualizations/{year}_Sales_Dispersion_AM_PM.png')

    plt.close()

####################################################################################################################################

# set title
title = f'Total Promo_Freebies per Year'

# define figure and axis
fig, ax = plt.subplots(figsize = (19.20,10.80), dpi = 200)

# estabilish Dataframe information
df = all_years_data_dictionary['master_promo_freebies']

# remove dataframe 'TOTAL' and 'year:2022' Rows
df = df.iloc[:-2]

# make list of columns for setting Legend names
cols = df.columns.to_list()
#remove 'year' from column list
cols = cols[1:]

# set x values
x = df['year']
# set y values
y = df.drop(columns=['year'])

# create plot
plt.plot(x,y)

# make list of all lines for passing to legend
lines= ax.get_lines()

# for line in lines, name line after corresponding location in column list
for i,line in enumerate(lines):
    # set the name of each line
    line.set_label(cols[i])

# set labels for the axes
plt.xlabel('Year')
plt.ylabel('Amount USD')
plt.title(f'{title}')

plt.grid()

plt.legend()

if save == 'y':
    plt.savefig(f'visualizations/{title}.png')

plt.close()


def is_empty(board):
    for y in range(len(board)):
        for x in range(len(board[y])):
            if board[y][x] != " ":
                return False
    return True

def is_bounded(board, y_end, x_end, length, d_y, d_x):
    front = False
    back = False
    tempYfront = y_end + d_y
    tempXfront = x_end + d_x
    tempYback = y_end - d_y*length
    tempXback = x_end - d_x*length
    if (tempYfront>= 0 and tempYfront<=len(board)-1) and (tempXfront>= 0 and tempXfront<=len(board)-1):
        if board[tempYfront][tempXfront] == " ":
            front = True
    if (tempYback>= 0 and tempYback<=len(board)-1) and (tempXback>= 0 and tempXback<=len(board)-1):
        if board[tempYback][tempXback] == " ":
            back = True
    if back == True and front == True:
        return "OPEN"
    elif back == False and front == False:
        return "CLOSED"
    else:
        return "SEMIOPEN"

def is_sequence_complete(board, col, y_start, x_start, length, d_y, d_x):
    for i in range(length):
        if board[y_start+i*d_y][x_start+i*d_x] != col:
            return False
    return True

def detect_row(board, col, y_start, x_start, length, d_y, d_x):
    open_seq_count = 0
    semi_open_seq_count = 0
    rowlength = 0
    y = y_start
    x = x_start
    while (x>=0 and x<=len(board)-1) and (y>=0 and y<=len(board)-1):
        rowlength +=1
        y += d_y
        x += d_x
    for i in range(rowlength):
        if board[y_start][x_start] != col:
            y_start+=d_y
            x_start+=d_x
            continue
        x_end = x_start+d_x*length-1*d_x
        y_end = y_start+d_y*length-1*d_y
        if (y_end>=0 and y_end<=len(board)-1) and (x_end>=0 and x_end<=len(board)-1):
            temp = True
            for j in range(length):
                if board[y_start+j*d_y][x_start+j*d_x] != col:
                    temp = False
                    break
            if temp == False:
                y_start+=d_y
                x_start+=d_x
                continue
        else:
            y_start+=d_y
            x_start+=d_x
            continue
        if (y_end+d_y)>=0 and (y_end+d_y)<=len(board)-1 and (x_end+d_x)>=0 and (x_end+d_x)<=len(board)-1:
            if board[y_end+d_y][x_end+d_x] == col:
                y_start+=d_y
                x_start+=d_x
                continue
        if (y_start-d_y)>=0 and (y_start-d_y)<=len(board)-1 and (x_start-d_x)>=0 and (x_start-d_x)<=len(board)-1:
            if board[y_start-d_y][x_start-d_x] == col:
                y_start+=d_y
                x_start+=d_x
                continue
        if is_bounded(board, y_end, x_end, length, d_y,d_x) == "OPEN":
            open_seq_count +=1
        elif is_bounded(board, y_end, x_end, length, d_y,d_x) == "SEMIOPEN":
            semi_open_seq_count +=1
        x_start+=d_x
        y_start+=d_y
    return open_seq_count, semi_open_seq_count

def detect_rows(board, col, length):
    open_seq_count, semi_open_seq_count = 0, 0
    x_start = 0
    y_start = 0
    for i in range(len(board)):
        open_seq_count+= detect_row(board, col, y_start, x_start, length, 0, 1)[0]
        semi_open_seq_count+= detect_row(board, col, y_start, x_start, length, 0, 1)[1]
        open_seq_count+= detect_row(board, col, y_start, x_start, length, 1, 1)[0]
        semi_open_seq_count+= detect_row(board, col, y_start, x_start, length, 1, 1)[1]
        y_start+=1
    x_start = 0
    y_start = 0
    for i in range(len(board)):
        open_seq_count+= detect_row(board, col, y_start, x_start, length, 1, 0)[0]
        semi_open_seq_count+= detect_row(board, col, y_start, x_start, length, 1, 0)[1]
        if x_start!=0:
            open_seq_count+= detect_row(board, col, y_start, x_start, length, 1, 1)[0]
            semi_open_seq_count+= detect_row(board, col, y_start, x_start, length, 1, 1)[1]
        x_start+=1
    x_start = len(board)-1
    y_start = 0
    for i in range(len(board)):
        open_seq_count+= detect_row(board, col, y_start, x_start, length, 1, -1)[0]
        semi_open_seq_count+= detect_row(board, col, y_start, x_start, length, 1, -1)[1]
        y_start+=1
    x_start = len(board)-2
    y_start = 0
    for i in range(len(board)):
        open_seq_count+= detect_row(board, col, y_start, x_start, length, 1, -1)[0]
        semi_open_seq_count+= detect_row(board, col, y_start, x_start, length, 1, -1)[1]
        x_start-=1
    return open_seq_count, semi_open_seq_count

def search_max(board):
    optimal = -21471483648
    move_y = None
    move_x = None
    for i in range(len(board)):
        for j in range(len(board[i])):
            if board[i][j]==" ":
                board[i][j] = "b"
                if score(board)>optimal:
                    optimal = score(board)
                    move_y = i
                    move_x = j
                board[i][j] = " "
    return move_y, move_x

def score(board):
    MAX_SCORE = 100000

    open_b = {}
    semi_open_b = {}
    open_w = {}
    semi_open_w = {}

    for i in range(2, 6):
        open_b[i], semi_open_b[i] = detect_rows(board, "b", i)
        open_w[i], semi_open_w[i] = detect_rows(board, "w", i)

    if open_b[5] >= 1 or semi_open_b[5] >= 1:
        return MAX_SCORE

    elif open_w[5] >= 1 or semi_open_w[5] >= 1:
        return -MAX_SCORE

    return (-10000 * (open_w[4] + semi_open_w[4])+
            500  * open_b[4]                     +
            50   * semi_open_b[4]                +
            -100  * open_w[3]                    +
            -30   * semi_open_w[3]               +
            50   * open_b[3]                     +
            10   * semi_open_b[3]                +
            open_b[2] + semi_open_b[2] - open_w[2] - semi_open_w[2])

def is_win(board):
    open = 0
    for y in range(len(board)):
        for x in range(len(board[y])):
            if board[y][x] == " ":
                open+=1
            for d_y in range(-1,2):
                for d_x in range(-1,2):
                    if d_y == 0 and d_x == 0:
                        continue
                    temp = False
                    if (y+d_y*4)<=len(board)-1 and (y+d_y*4)>=0 and (x+d_x*4)>=0 and (x+d_x*4)<=len(board)-1:
                        if is_sequence_complete(board, "b", y, x, 5, d_y,d_x):
                            temp = False
                            if (y-d_y) >= 0 and (y-d_y)<=len(board)-1 and (x-d_x) >= 0 and (x-d_x)<=len(board)-1:
                                if board[y-d_y][x-d_x] == "b":
                                    temp = True
                            if (y+d_y*5)<=len(board)-1 and (y+d_y*5)>=0 and (x+d_x*5)<=len(board)-1 and (x+d_x*5)>=0:
                                if board[y+d_y*5][x+d_x*5] == "b":
                                    temp = True
                            if not(temp):
                                return "Black won"
                        if is_sequence_complete(board, "w", y, x, 5, d_y,d_x):
                            temp = False
                            if (y-d_y) >= 0 and (y-d_y)<=len(board)-1 and (x-d_x) >= 0 and (x-d_x)<=len(board)-1:
                                if board[y-d_y][x-d_x] == "w":
                                    temp = True
                            if (y+d_y*5)<=len(board)-1 and (y+d_y*5)>=0 and (x+d_x*5)<=len(board)-1 and (x+d_x*5)>=0:
                                if board[y+d_y*5][x+d_x*5] == "w":
                                    temp = True
                            if not(temp):
                                return "White won"
    if open!=0:
        return "Continue playing"
    return "Draw"

def print_board(board):

    s = "*"
    for i in range(len(board[0])-1):
        s += str(i%10) + "|"
    s += str((len(board[0])-1)%10)
    s += "*\n"

    for i in range(len(board)):
        s += str(i%10)
        for j in range(len(board[0])-1):
            s += str(board[i][j]) + "|"
        s += str(board[i][len(board[0])-1])

        s += "*\n"
    s += (len(board[0])*2 + 1)*"*"

    print(s)

def make_empty_board(sz):
    board = []
    for i in range(sz):
        board.append([" "]*sz)
    return board

def analysis(board):
    for c, full_name in [["b", "Black"], ["w", "White"]]:
        print("%s stones" % (full_name))
        for i in range(2, 6):
            open, semi_open = detect_rows(board, c, i);
            print("Open rows of length %d: %d" % (i, open))
            print("Semi-open rows of length %d: %d" % (i, semi_open))

def play_gomoku(board_size):
    board = make_empty_board(board_size)
    board_height = len(board)
    board_width = len(board[0])

    while True:
        print_board(board)
        if is_empty(board):
            move_y = board_height // 2
            move_x = board_width // 2
        else:
            move_y, move_x = search_max(board)

        print("Computer move: (%d, %d)" % (move_y, move_x))
        board[move_y][move_x] = "b"
        print_board(board)
        analysis(board)

        game_res = is_win(board)
        if game_res in ["White won", "Black won", "Draw"]:
            return game_res

        print("Your move:")
        move_y = int(input("y coord: "))
        move_x = int(input("x coord: "))
        board[move_y][move_x] = "w"
        print_board(board)
        analysis(board)

        game_res = is_win(board)
        if game_res in ["White won", "Black won", "Draw"]:
            return game_res

def put_seq_on_board(board, y, x, d_y, d_x, length, col):
    for i in range(length):
        board[y][x] = col
        y += d_y
        x += d_x

if __name__ == '__main__':
    play_gomoku(8)