import numpy as np
import cv2
from pathfinding.core.diagonal_movement import DiagonalMovement
from pathfinding.core.grid import Grid
from pathfinding.finder.best_first import BestFirst
from pathfinding.core import heuristic, diagonal_movement
import math

def scaleImage(image,scale):
    scale_percent = scale # percent of original size
    width = int(image.shape[1] * scale_percent / 100)
    height = int(image.shape[0] * scale_percent / 100)
    dim = (width, height)

    # resize image
    resized = cv2.resize(image, dim, interpolation=cv2.INTER_AREA)
    new_img_size = (resized.shape[1] - (resized.shape[1] % 32), resized.shape[0] - (resized.shape[0] % 32))
    resized_img = cv2.resize(resized, new_img_size)

    return resized_img

imagecp = cv2.imread("/Users/frederikhelsoe/Desktop/Robo-Billeder/RoboBillede5.jpg")
imagecp = scaleImage(imagecp,80)
imagecp = cv2.cvtColor(imagecp,cv2.COLOR_BGR2RGB)
image = imagecp.copy()

# Grayscale
gray = cv2.cvtColor(image, cv2.COLOR_BGR2GRAY)
blurred = cv2.GaussianBlur(gray, (5, 5), 0)
edges = cv2.Canny(blurred, 50, 150)
contours, _ = cv2.findContours(edges, cv2.RETR_EXTERNAL, cv2.CHAIN_APPROX_SIMPLE)

for cont in contours:
    perimeter = cv2.arcLength(cont, True)
    approx = cv2.approxPolyDP(cont, 0.04 * perimeter, True)
    area =  cv2.contourArea(cont)
    if len(approx) == 3 and area > 300 and  area < 600:
        # Triangle detected
        cv2.drawContours(image, [approx], 0, (0, 255, 0), 2)
        x, y, w, h = cv2.boundingRect(approx)
        roi = imagecp[y:y+h, x:x+w]

        # Check the color inside the triangle ROI
        green_mask = cv2.inRange(roi, (0, 50, 0), (0, 255, 0))
        blue_mask = cv2.inRange(roi, (0, 0, 50), (0, 0, 255))
        if cv2.countNonZero(green_mask) > cv2.countNonZero(blue_mask):
            # The triangle contains green and blue
            cv2.putText(image, "Green", (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 255, 0), 2)
        else:
            # The triangle does not contain green and blue
            cv2.putText(image, "Blue", (x, y-10), cv2.FONT_HERSHEY_SIMPLEX, 0.7, (0, 0, 255), 2)

cv2.imshow("Shapes", image)
cv2.waitKey(0)
cv2.destroyAllWindows()


# -*- coding: utf-8 -*
import sys
import os
import time
import datetime
import json
import threading
import requests
from azure.storage.blob import AppendBlobService
from azure.storage.blob import ContentSettings
from .utils import resource
from .configuration import get_config
from .ans_platform_api import AnsPlatformAPI
from .context import APP_CONTEXT

class FileLoger():
    def __init__(self, device_properties):
        '''Initialize and create a CSV file
        '''
        start_time = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
        self.device_properties = device_properties
        if not self.device_properties:
            print('No properties found')
            os._exit(1)

        self.root_folder = os.path.join(resource.get_executor_path(), r'data')
        if not os.path.exists(self.root_folder):
            os.mkdir(self.root_folder)
        self.output_packets = self.device_properties['userMessages']['outputPackets']
        self.log_file_rows = {}
        self.log_file_names = {}
        self.log_files_obj = {}
        self.log_files = {}
        self.user_file_name = ''  # the prefix of log file name.
        self.msgs_need_to_log = []
        self.ws = False
        # azure app.
        self.user_id = ''
        self.file_name = ''
        self.sas_token = ''
        self.db_user_access_token = ''
        # 'http://40.118.233.18:3000/'  # TODO: set a host url
        self.host_url = get_config().ANS_PLATFORM_URL

        #
        self.threads = []  # thread of receiver and paser
        self.exit_thread = False  # flag of exit threads
        self.exit_lock = threading.Lock()  # lock of exit_thread
        self.data_dict = {}  # data container
        self.data_lock = threading.Lock()  # lock of data_queue

        self.device_log_info = None
        self.ans_platform = AnsPlatformAPI()

    def start_user_log(self, file_name='', ws=False):
        '''
        start log.
        return:
                0: OK
                1: exception that has started logging already.
                2: other exception.
        '''
        try:
            if len(self.log_file_rows) > 0:
                return 1  # has started logging already.

            self.ws = ws
            self.exit_thread = False
            self.user_file_name = file_name
            start_time = datetime.datetime.now().strftime('%Y%m%d_%H%M%S')
            current_path = os.path.join(self.root_folder, start_time)
            if not os.path.exists(current_path):
                os.mkdir(current_path)

            for packet in self.output_packets:
                # if 1 == packet['save2file']:
                has_save2file = packet.__contains__('save2file')
                save2file = 1
                if has_save2file:
                    save2file = packet['save2file']

                if save2file == 1:
                    self.msgs_need_to_log.append(packet['name'])

                self.log_file_rows[packet['name']] = 0
                if self.user_file_name == '':
                    self.log_file_names[packet['name']
                                        ] = packet['name'] + '.csv'
                else:
                    self.log_file_names[packet['name']] = self.user_file_name + \
                        '_' + packet['name'] + '.csv'
                self.log_files[packet['name']
                               ] = self.log_file_names[packet['name']]

                self.log_files_obj[packet['name']] = open(
                    current_path + '/' + self.log_file_names[packet['name']], 'w')

            if self.ws:
                self.get_sas_token()
                self.data_dict.clear()
                for i, (k, v) in enumerate(self.log_files.items()):  # k:pack type  v:log file name
                    self.data_dict[v] = ''
                    threading.Thread(target=self.upload_azure,
                                     args=(k, v)).start()
            return 0
        except Exception as e:
            print('Exception! File:[{0}], Line:[{1}]. Exception:{2}'.format(
                __file__, sys._getframe().f_lineno, e))
            return 2

    def stop_user_log(self):
        '''
        stop log.
        return:
                0: OK
                1: exception that driver hasn't started logging files yet.
                2: other exception.
        '''
        rev = 0
        try:
            if len(self.log_file_rows) == 0:
                return 1  # driver hasn't started logging files yet.
            for i, (k, v) in enumerate(self.log_files_obj.items()):
                v.close()
            self.log_file_rows.clear()
            self.log_file_names.clear()
            self.log_files_obj.clear()
            rev = 0
        except Exception as e:
            print(e)
            rev = 2

        if self.ws:
            time.sleep(1)
            self.exit_lock.acquire()
            self.exit_thread = True
            self.exit_lock.release()
            self.ws = False

        return rev

    def upload_azure(self, packet_type, log_file_name):
        if self.db_user_access_token == '' or self.sas_token == '':
            print(
                "Error: Can not upload log to azure since token is empty! Please check the network.")

        print(datetime.datetime.now().strftime(
            '%Y_%m_%d_%H_%M_%S:'), log_file_name, ' start.')

        config = get_config()
        account_name = config.AZURE_STORAGE_ACCOUNT
        container_name = config.AZURE_STORAGE_DATA_CONTAINER
        url_name = datetime.datetime.now().strftime(
            '%Y_%m_%d_%H_%M_%S') + '-' + self.user_id + '-' + log_file_name
        bcreate_blob_ok = False

        error_connection = 'ConnectionError'
        error_authorization = 'AuthenticationFailed'

        while True:
            # get data from data_dict.
            self.data_lock.acquire()
            text = self.data_dict[log_file_name]
            self.data_dict[log_file_name] = ''
            self.data_lock.release()

            # check if user stop logging data.
            self.exit_lock.acquire()
            if self.exit_thread:
                # check for internet and text
                if text == '':
                    self.exit_lock.release()
                    break
                else:
                    pass
            self.exit_lock.release()

            # let CPU have a break.
            if text == '':
                time.sleep(1)
                continue

            # create blob on azure
            if not bcreate_blob_ok:
                try:
                    self.append_blob_service = AppendBlobService(account_name=account_name,
                                                                 sas_token=self.sas_token,
                                                                 protocol='http')
                    self.append_blob_service.create_blob(container_name=container_name, blob_name=url_name,
                                                         content_settings=ContentSettings(content_type='text/plain'))
                    bcreate_blob_ok = True
                    threading.Thread(target=self.save_to_db_task, args=(
                        packet_type, log_file_name, url_name)).start()
                except Exception as e:
                    # print('Exception when create_blob:', type(e), e)
                    if error_connection in str(e):
                        pass
                    elif error_authorization in str(e):
                        self.get_sas_token()
                        self.append_blob_service = AppendBlobService(account_name=account_name,
                                                                     sas_token=self.sas_token,
                                                                     protocol='http')
                    print('Retry to create_blob again...')
                    continue

            # append blob on azure
            try:
                # self.append_blob_service.append_blob_from_text(countainerName, fileName, text, progress_callback=self.upload_callback)
                self.append_blob_service.append_blob_from_text(
                    container_name, url_name, text)
            except Exception as e:
                # print('Exception when append_blob:', type(e), e)
                if error_connection in str(e):
                    pass
                elif error_authorization in str(e):
                    self.get_sas_token()
                    self.append_blob_service = AppendBlobService(account_name=account_name,
                                                                 sas_token=self.sas_token,
                                                                 protocol='http')
                    # if append blob failed, do not drop 'text', but push 'text' to data_dict and re-append next time.
                    self.data_lock.acquire()
                    self.data_dict[log_file_name] = text + \
                        self.data_dict[log_file_name]
                    self.data_lock.release()

            time.sleep(5)

        if bcreate_blob_ok:
            # if not self.save_to_ans_platform(packet_type, log_file_name):
            #     print('save_to_ans_platform failed.')
            print(datetime.datetime.now().strftime(
                '%Y_%m_%d_%H_%M_%S:'), log_file_name, ' done.')

    def save_to_db_task(self, packet_type, file_name, url_name):
        if not self.save_to_ans_platform(packet_type, file_name, url_name):
            print('save_to_ans_platform failed.')

    def append(self, packet_type, packet):
        if len(self.log_file_rows) == 0:  # if hasn't started logging.
            return

        if packet_type in self.msgs_need_to_log:
            self.log(packet_type, packet)

    def get_log_file_names(self):
        return self.log_file_names.copy()

    def log(self, packet_type, data):
        ''' Parse the data, read in from the unit, and generate a data file using
            the json properties file to create a header and specify the precision
            of the data in the resulting data file.
        '''
        output_packet = next(
            (x for x in self.output_packets if x['name'] == packet_type), None)

        fields = [field['name'] for field in output_packet['payload']]
        '''Write row of CSV file based on data received.  Uses dictionary keys for column titles
        '''
        if self.log_file_rows[packet_type] == 0:
            # Loop through each item in the data dictionary and create a header from the json
            #   properties that correspond to the items in the dictionary
            labels = ''
            # for key in data:
            for i, (k, v) in enumerate(data.items()):
                '''dataStr = output_packet['payload'][i]['name'] + \
                          ' [' + \
                          output_packet['payload'][i]['unit'] + \
                          ']'''
                if not fields.__contains__(k):
                    continue
                data_str = output_packet['payload'][i]['name']
                unit_str = output_packet['payload'][i]['unit']
                if unit_str == '':
                    labels = labels + '{0:s},'.format(data_str)
                else:
                    labels = labels + \
                        '{0:s} ({1:s}),'.format(data_str, unit_str)

            # Remove the comma at the end of the string and append a new-line character
            labels = labels[:-1]
            header = labels + '\n'
        else:
            header = ''

        self.log_file_rows[packet_type] += 1

        # Loop through the items in the data dictionary and append to an output string
        #   (with precision based on the data type defined in the json properties file)
        write_str = ''
        for i, (k, v) in enumerate(data.items()):
            if not fields.__contains__(k):
                continue
            output_packet_type = output_packet['payload'][i]['type']

            if output_packet['payload'][i].__contains__('scaling'):
                write_str += '{0},'.format(v)
            else:
                if output_packet_type == 'uint32' or output_packet_type == 'int32' or \
                        output_packet_type == 'uint16' or output_packet_type == 'int16' or \
                        output_packet_type == 'uint64' or output_packet_type == 'int64':
                    # integers and unsigned integers
                    write_str += '{0},'.format(v)
                elif output_packet_type == 'double':
                    # double
                    write_str += '{0:0.8f},'.format(v)  # 15.12
                elif output_packet_type == 'float':
                    write_str += '{0:0.4f},'.format(v)  # 12.8
                elif output_packet_type == 'uint8':
                    # byte
                    write_str += '{0:d},'.format(v)
                elif output_packet_type == 'uchar' or output_packet_type == 'char' or output_packet_type == 'string':
                    # character
                    write_str += '{:},'.format(v)
                else:
                    # unknown
                    write_str += '{0:3.5f},'.format(v)
        #
        write_str = header + write_str[:-1] + '\n'

        try:
            self.log_files_obj[packet_type].write(write_str)
            self.log_files_obj[packet_type].flush()
        except ValueError:
            APP_CONTEXT.get_logger().logger.error(
                'I/O Exception, file may be closed before using')
        except Exception as ex:
            APP_CONTEXT.get_logger().logger.error(ex)

        if self.ws:
            self.data_lock.acquire()
            self.data_dict[self.log_files[packet_type]
                           ] = self.data_dict[self.log_files[packet_type]] + write_str
            self.data_lock.release()

    def set_info(self, info):
        self.device_log_info = info
        pass

    def set_user_id(self, user_id):
        self.user_id = user_id
        if not isinstance(self.user_id, str):
            self.user_id = str(self.user_id)

    def set_user_access_token(self, access_token):
        self.db_user_access_token = access_token

    def get_sas_token(self):
        try:
            self.ans_platform.set_access_token(self.db_user_access_token)
            self.sas_token = self.ans_platform.get_sas_token()
        except Exception as e:
            self.sas_token = ''
            print('Exception when get_sas_token:', e)

    def save_to_ans_platform(self, packet_type, file_name, url_name):
        ''' Upload CSV related information to the database.
        '''
        if not self.device_log_info:
            return False

        try:
            self.device_log_info['fileName'] = file_name
            self.device_log_info['url'] = url_name
            self.device_log_info['userId'] = self.user_id
            self.device_log_info['logInfo']['packetType'] = packet_type
            data = self.device_log_info

            # data = {
            #     "type": self.device_log_info['type'],
            #     "model": self.device_log_info['name'],
            #     "fileName": file_name,
            #     "url": file_name,
            #     "userId": self.user_id,
            #     "logInfo": {
            #             "pn": self.device_log_info['pn'],
            #             "sn": self.device_log_info['sn'],
            #             "packetType": packet_type,
            #             "insProperties": json.dumps(self.device_properties)
            #     }
            # }

            self.ans_platform.set_access_token(self.db_user_access_token)
            return self.ans_platform.save_record_log(data)
        except Exception as e:
            print('Exception when update db:', e)

    def internet_on(self):
        try:
            url = 'https://navview.blob.core.windows.net/'
            if sys.version_info[0] > 2:
                import urllib.request
                response = urllib.request.urlopen(url, timeout=1)
            # print(response.read())
            return True
        except Exception as err:
            return False


"""users table

Revision ID: 1eed6b4550cb
Revises:
Create Date: 2018-08-09 23:23:04.461128

"""
from alembic import op
import sqlalchemy as sa

# revision identifiers, used by Alembic.
revision = '1eed6b4550cb'
down_revision = None
branch_labels = None
depends_on = None

def upgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.create_table('user',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('username', sa.String(length=64), nullable=True),
    sa.Column('displayName', sa.String(length=120), nullable=True),
    sa.Column('password', sa.String(length=128), nullable=True),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_user_displayName'), 'user', ['displayName'], unique=True)
    op.create_index(op.f('ix_user_username'), 'user', ['username'], unique=True)
    op.create_table('inventori',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('namaBarang', sa.String(length=120), nullable=True),
    sa.Column('jumlahBarang', sa.Integer(), nullable=True),
    sa.Column('namaHimpunan', sa.String(length=120), nullable=True),
    sa.ForeignKeyConstraint(['namaHimpunan'], ['user.displayName'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_inventori_jumlahBarang'), 'inventori', ['jumlahBarang'], unique=False)
    op.create_index(op.f('ix_inventori_namaBarang'), 'inventori', ['namaBarang'], unique=True)
    op.create_table('pinjam',
    sa.Column('id', sa.Integer(), nullable=False),
    sa.Column('namaPeminjam', sa.String(length=120), nullable=True),
    sa.Column('namaBarang', sa.String(length=120), nullable=True),
    sa.Column('namaPemilik', sa.String(length=120), nullable=True),
    sa.Column('jumlahPinjam', sa.Integer(), nullable=True),
    sa.Column('awalPinjam', sa.Integer(), nullable=True),
    sa.Column('akhirPinjam', sa.Integer(), nullable=True),
    sa.ForeignKeyConstraint(['namaPeminjam'], ['user.displayName'], ),
    sa.PrimaryKeyConstraint('id')
    )
    op.create_index(op.f('ix_pinjam_jumlahPinjam'), 'pinjam', ['jumlahPinjam'], unique=False)
    op.create_index(op.f('ix_pinjam_namaBarang'), 'pinjam', ['namaBarang'], unique=False)
    # ### end Alembic commands ###

def downgrade():
    # ### commands auto generated by Alembic - please adjust! ###
    op.drop_index(op.f('ix_pinjam_namaBarang'), table_name='pinjam')
    op.drop_index(op.f('ix_pinjam_jumlahPinjam'), table_name='pinjam')
    op.drop_table('pinjam')
    op.drop_index(op.f('ix_inventori_namaBarang'), table_name='inventori')
    op.drop_index(op.f('ix_inventori_jumlahBarang'), table_name='inventori')
    op.drop_table('inventori')
    op.drop_index(op.f('ix_user_username'), table_name='user')
    op.drop_index(op.f('ix_user_displayName'), table_name='user')
    op.drop_table('user')
    # ### end Alembic commands ###


#!/usr/bin/env python3
# -*- coding: utf-8 -*-

# @File   : 0049-group-anagrams.py
# @Date   : 2019/08/17
# @Author : Yuvv <yuvv_th@outlook.com>

from typing import List

class Solution:
    def groupAnagrams(self, strs: List[str]) -> List[List[str]]:
        d = dict()
        for s in strs:
            sorted_s = ''.join(sorted(s))
            if sorted_s not in d:
                d[sorted_s] = []
            d[sorted_s].append(s)
        result = list()
        for v in d.values():
            result.append(v)
        return result

if __name__ == "__main__":
    s = Solution()
    print(s.groupAnagrams(["eat", "tea", "tan", "ate", "nat", "bat"]))
    print(s.groupAnagrams(['abab', 'baba', 'abba', 'ababa', 'babab', 'abbaa', '', '']))
    print(s.groupAnagrams(["tao", "pit", "cam", "aid", "pro", "dog"]))


"""Find peaks in a spectrum."""

import argparse
from typing import List
from typing import Tuple

import numpy as np
from sklearn.linear_model import LinearRegression

def lin_fit(x: List, y: List) -> Tuple:
    X = np.array(x).reshape(len(x), 1)
    y = np.array(y).reshape(len(y), 1)

    reg = LinearRegression().fit(X, y)

    return reg.coef_[0][0], reg.intercept_[0]

if __name__ == "__main__":
    parser = argparse.ArgumentParser(description="Get coefficients of linear regression for energy calibration")
    parser.add_argument("--counts", type=str, help="Channel values of peaks")
    parser.add_argument("--thickness", type=str, help="Reference energy of peaks")
    args = parser.parse_args()

    counts = [float(c) for c in args.counts.split(",")]
    thickness = [float(e) for e in args.thickness.split(",")]

    x = thickness
    y = [np.log(counts[0]) - np.log(c) for c in counts]
    m, b = lin_fit(x, y)

    print(f"X = {x}")
    print(f"Y = {y}")
    print(f"Slope = {m}")
    print(f"Intercept = {b}")


class Node:
    def __init__(self, value):
        self.value = value
        self.left = None
        self.right  = None

class BiTree:
    def __init__(self):
        self.root = None

    def has_path(self, node, target_sum, curr=0):
        if node == None:
            return False

        new_curr = curr + node.value
        leaf = node.left == None and node.right == None
        if leaf:
            return 1 if target_sum == new_curr else 0

        return (
            self.has_path(node.left, target_sum, new_curr) +
            self.has_path(node.right, target_sum, new_curr)
        )

root = Node(1)
root.left = Node(2)
root.right = Node(2)
root.left.left = Node(2)
root.left.right = Node(5)
# root.right.left = Node(0)
root.right.right = Node(5)
new_tree = BiTree()
print(new_tree.has_path(root, 8))


from flask import Flask

import models
from Resources.employee import employee_api

DEBUG = True
HOST = '127.0.0.1'
PORT = 8000

app = Flask(__name__)
app.register_blueprint(employee_api)

@app.route('/')
def index():
    return 'Hello World'

if __name__ == '__main__':
    models.initialize()
    app.run(debug=DEBUG, host=HOST, port=PORT)


#!/usr/bin/env python3
# -*- coding: utf-8 -*-
"""
Created on Sun Aug  7 18:59:03 2022

@author: s1997751
"""

import numpy as np
from pandas import read_csv
from torch.utils.data import Dataset
from torch.utils.data import DataLoader
from torch.utils.data import random_split
from torch import nn
import torch
import os
from tqdm import tqdm
import matplotlib.pyplot as plt
import concurrent.futures
#from concurrent.futures import ProcessPoolExecutor
#from concurrent.futures import ThreadPoolExecutor
from os import listdir
from pathlib import Path

# custom dataset definition
class CSVDataset(Dataset):
  # load the dataset
  def __init__(self, path):
    # load the csv file as a dataframe
    df = read_csv(path, header=None)
    # store the inputs and outputs
    self.X = df.values[1:, 2:-1]
    self.y = df.values[1:, -1]
    # ensure input and output data is floats
    self.X = self.X.astype('float32')
    self.y = self.y.astype('float32')
    self.y = self.y.reshape((len(self.y), 1))
    self.label = str(df.values[1,1])

  # number of rows in the dataset
  def __len__(self):
    return len(self.X)

  # get a row at an index
  def __getitem__(self, idx):
    return [self.X[idx], self.y[idx]]

class TXTDataset(Dataset):
  # load the dataset
  def __init__(self, path):
    # load the csv file as a dataframe
    df = np.load(path,dtype = object)
    # store the inputs and outputs
    self.X = df[1:-1]
    self.y = df[-1]
    # ensure input and output data is floats
    self.X = self.X.astype('float32')
    self.y = self.y.astype('float32')
    self.y = self.y.reshape((len(self.y), 1))
    self.label = str(df[0])

  # number of rows in the dataset
  def __len__(self):
    return len(self.X)

  # get a row at an index
  def __getitem__(self, idx):
    return [self.X[idx], self.y[idx]]

class PathDataset(Dataset):

    def __init__(self, folder_file):
        """
        Args:
            csv_file (string): Path to the csv file with annotations.
            root_dir (string): Directory with types of directories.
            transform (callable, optional): Optional transform to be applied
                on a sample. -> could implement soap here if needed
        """
        self.files = np.load(folder_file)
        self.files = self.files[:10000]
        #print(self.files)
        self.label = str(folder_file.split("/")[-1][:-4])

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

    def __getitem__(self, idx):
        sample = np.load(str(self.files[idx]),allow_pickle=True)

        # store the inputs and outputs
        self.X = sample[1:-1]
        self.y = np.array([sample[-1]])
        # ensure input and output data is floats
        self.X = self.X.astype('float32')
        self.y = self.y.astype('float32')
        # self.X = self.X.reshape((len(self.X), 1))
        # self.y = self.y.reshape((len(self.y), 1))

        return [self.X, self.y]

class Data_Loaders():
    def __init__(self, master_file, batch_size, split_prop=0.8):
        self.path_dataset = PathDataset(master_file)
        self.label = self.path_dataset.label

        # compute number of samples
        self.N_train = int(len(self.path_dataset) * split_prop)
        self.N_validate = int(len(self.path_dataset) * 0.5*(1.-split_prop))
        self.N_test = len(self.path_dataset) - self.N_train - self.N_validate

        if self.N_test == 0 or self.N_validate == 0:
            print(f'-----Need more samples for {self.label}!!---------')

        # split the data set
        self.train_set, self.validate_set, self.test_set = random_split(self.path_dataset, \
                                      [self.N_train, self.N_validate, self.N_test])

        # create the data loaders
        self.train_loader = DataLoader(self.train_set, batch_size=batch_size)
        self.validate_loader = DataLoader(self.validate_set, batch_size=batch_size)
        self.test_loader = DataLoader(self.test_set, batch_size=batch_size)

class MLP(nn.Module):
    '''
    Multilayer Perceptron for regression.
    '''
    def __init__(self, n1, n2, n3):
        super().__init__()
        self.layers = nn.Sequential(
        nn.Linear(560, n1),
        nn.ReLU(),
        nn.Linear(n1, n2),
        nn.ReLU(),
        nn.Linear(n2, n3),
        nn.ReLU(),
        nn.Linear(n3, 1)
        )

    def forward(self, x):
        '''
      Forward pass
        '''
        return self.layers(x)

def rmsre(outputs, targets):
    '''
    Root mean squared relative error
    '''

    return torch.sqrt(torch.mean(torch.pow(torch.div(torch.sub(outputs,targets),targets),2)))

def test(model, test_loader, loss_function):
    model.eval()
    test_loss = list()

    with torch.no_grad():
      for data in test_loader:

        if torch.cuda.is_available():
                inputs = data[0].cuda()
                targets = data[1].cuda()
                model.cuda()
#                data = data.cuda()
#                print("Using GPU")
#        inputs, targets = data
        inputs, targets = inputs.float(), targets.float()

        outputs=model(inputs)
        targets = targets.view(-1,1)

        loss=loss_function(outputs,targets)
        test_loss.append(loss.item())

    rmse_test_loss=np.sqrt(np.mean(np.array(test_loss)**2))

    #print('Test Loss: %.3f' %(rmse_test_loss))
    return rmse_test_loss

def train_and_test_model(path):

    # setting parameters here as input must only be path to dataset
    epochs = 100
    model = MLP(256, 128, 64)
    loss_function = rmsre
    optimizer = torch.optim.Adam(model.parameters(), lr=1e-3)
    batch_size = 16
    name = path.split("/")[-1]
    master_file = path+"/"+name+".npy"

    # create data loaders
    data_loaders = Data_Loaders(master_file, batch_size)
    trainloader = data_loaders.train_loader
    validateloader = data_loaders.validate_loader
    testloader = data_loaders.test_loader
    label = data_loaders.label

    # start training
    model.train()
    running_loss_mean = list()
    running_validate_loss_mean = list()
    for e in tqdm(range(epochs), desc=name, total=epochs):
        #print(f'Starting epoch {e+1}')
        train_loss = list()
        for data in trainloader:

            # Transfer Data to GPU if available
            if torch.cuda.is_available():
                inputs = data[0].cuda()
                targets = data[1].cuda()
                model.cuda()
#                data = data.cuda()

#            inputs, targets = data
            inputs, targets = inputs.float(), targets.float()

            # Clear the gradients
            optimizer.zero_grad()
            # Forward Pass
            outputs = model(inputs)
            # Find the Loss
            # print(outputs.shape, targets.shape)
            targets = targets.view(-1,1)
            loss = loss_function(outputs, targets)
            # Calculate gradients
            loss.backward()
            # Update Weights
            optimizer.step()
            # Calculate Loss
            train_loss.append(loss.item())

        rmse_validate_loss = test(model, validateloader, loss_function)

        running_loss_mean.append(np.sqrt(np.mean(np.array(train_loss)**2)))
        running_validate_loss_mean.append(np.array(rmse_validate_loss)**2)
        #print(f'Epoch {e+1} \t Training Loss: {running_loss_mean[-1]:.2f} \t Validation Loss: {running_validate_loss_mean[-1]:.2f}')

    # test the model
    test_loss = test(model, testloader, loss_function)
    #print('Training process has finished.')
    print(f'Model {label}, Test Loss: {test_loss:.2f}')

    return label, running_loss_mean, running_validate_loss_mean, test_loss, model.state_dict()

    # save the model and also the training and validation curves and testing loss

    # results_path = '/home/s2122199/Documents/Edinburgh/projects/IBM/data/QMrxn/geometries/DistanceModels/'+label
    # print(results_path)
    # os.mkdir(results_path)

    # torch.save(model.state_dict(), results_path+'/model')
    # np.save(results_path+'/training_loss.npy', running_loss_mean)
    # np.save(results_path+'/validation_loss.npy', running_validate_loss_mean)
    # np.save(results_path+'/test_loss.npy', test_loss)

    #return running_loss_mean, running_validate_loss_mean, test_loss

####%%
if __name__ == '__main__':

    # create list of paths to files
    #folder_path = '/Users/Andrew/Documents/Edinburgh/ChemistyML/bond_files1/'
    folder_path = '/home/aidan/Documents/PhD/Year2/ibm_project/data_files/qmrxn/bonds_files/'
    paths = [folder_path+temp for temp in listdir(folder_path)]
    names = listdir(folder_path)

#    with ProcessPoolExecutor(max_workers=4) as executor:
#      results = list(tqdm(executor.map(train_and_test_model, paths), total=len(paths)))
    idx=0
    with tqdm(total=len(paths),desc="Total Progress") as pbar:
        # let's give it some more threads:
        with concurrent.futures.ThreadPoolExecutor(max_workers=28) as executor:
            futures = {executor.submit(train_and_test_model, path): path for path in paths}
            results = {}
            for future in concurrent.futures.as_completed(futures):
                arg = futures[future]
                results[idx] = future.result()
#                print(results[idx][0])
                pbar.update(1)
                idx+=1

    for i in results:

        results_path = '/home/aidan/Documents/PhD/Year2/ibm_project/data_files/qmrxn/mlp_outs/' + results[i][0]

        if not Path(results_path).exists():
            Path(results_path).mkdir(parents = True)
        np.save(results_path+'/training_loss.npy', results[i][1])
        np.save(results_path+'/validation_loss.npy', results[i][2])
        np.save(results_path+'/test_loss.npy', results[i][3])
        torch.save(results[i][4], results_path+'/model')


from bs4 import BeautifulSoup
import json, os, glob, re

result = []

def safe_get(el, prop):
    if el and el.has_attr(prop):
        return el[prop]
    return ''

def remove_all_but_digits_and_parse_int(x):
    return int(re.sub('\D', '', x) or '0') # 0 for cases then nothing remains

def process_files_in_dir_by_glob(path, mor):
    pattern = os.path.join(path, mor)
    files = glob.glob(pattern)
    files.insert(0, files.pop()) # move file without number in bracets to the beginning (not tested with timestamps (then more than 100 files downloaded with the same name)), remove if order is unrelevant
    for file in files:
        process_file(file)
        print("processed",file)

def process_file(path):
    process_posts(json.load(open(path, encoding='utf-8')))

class SoupWrapper:
    def __init__(self, soup):
        self.soup = soup
    def s(self, selector):
        return SoupWrapper(self.soup and self.soup.select_one(selector) or None)
    def m(self, selector):
        return [SoupWrapper(x) for x in (self.soup.select(selector) if self.soup else [])]
    def g(self, att):
        if self.soup and self.soup.has_attr(att):
            return self.soup[att]
        return ''
    def get_text(self, sep = ''):
        return self.soup and self.soup.get_text(sep) or ''
    def decompose(self):
        self.soup and self.soup.decompose()
    def replace_with_children(self):
        self.soup and self.soup.replace_with_children()

def process_image_data(d):
    for c in ['z', 'y', 'x']: # return best quality
        if c in d:
            return d[c]

def process_dup_comments(data):
    if len(data) == 0: return
    last = data[-1]
    comments = last["first_comments"]
    d = []
    lastAdded = None
    for comment in comments:
        if comment != lastAdded:
            d.append(comment)
            lastAdded = comment
    last["first_comments"] = d

def process_posts(posts):
    for post in posts:
        soup = BeautifulSoup(post, "html.parser")
        sw = SoupWrapper(soup)
        comment_author = sw.s('.author')
        replywrap = sw.s('.reply_wrap')
        is_comment = replywrap.soup != None # remove deleted comments?
        is_post = not is_comment
        if is_post:
            process_dup_comments(result)
            id_ = sw.s('a.PostHeaderTitle__authorLink').g('data-post-id')
            if id_ == '':
                print("NO ID FOR")
                print(post)
                id_ = '-1_-1'
            text_el = sw.s('.wall_post_text')
            show_more = text_el.s('.PostTextMore')
            show_more.decompose() # clear 'Показать еще'
            hidden_part_span = text_el.s('span')
            hidden_part_span.replace_with_children() # clear odd \n
            text = text_el.get_text('\n')
            subtitle_from = sw.s('a.PostHeaderSubtitle__item').g('href')
            when = sw.s('time').get_text()
            imgs_data = [process_image_data(json.loads(x.g('data-options'))['temp']) for x in sw.m('[data-options]')]
            audios_data = [json.loads(x.g('data-audio')) for x in sw.m('[data-audio]')]
            lincs = [x.g('href') for x in sw.m('a')]
            away_lincs = [x for x in lincs if x.startswith('/away.php')]
            videos_lincs = [x for x in lincs if x.startswith('/video') and x[6] in '-0123456789'] # is 7'th symbol always present?
            other_lincs = [x.g('href') for x in sw.s('.wall_text').m('a')]
            other_lincs = [x for x in other_lincs if not x.startswith('/feed?section=search&q=%23') and x not in other_lincs and x not in videoLincs] # remove search tags and lincs from other cats
            votingEl = sw.s('.media_voting')
            votingData = {}
            if votingEl.soup:
                question = votingEl.s(".media_voting_question").get_text();
                info = votingEl.s(".media_voting_info").get_text();
                options = [x.get_text() for x in votingEl.m(".media_voting_option_text")]
                votersCount = remove_all_but_digits_and_parse_int(votingEl.s("._media_voting_footer_voted_text").get_text());
                firstVoters = [x.g('href') for x in votingEl.m(".media_voting_footer_voted_friend")]
                votingData = {"question" : question, "info" : info, "options" : options, "voters_count" : votersCount, "first_voters" : firstVoters}
            lices = remove_all_but_digits_and_parse_int(sw.s('.PostBottomAction').get_text())
            comments = remove_all_but_digits_and_parse_int(sw.s('[data-like-button-type="comment"]').get_text())
            reposts = remove_all_but_digits_and_parse_int(sw.s('[data-like-button-type="share"]').get_text())
            #stats = [remove_all_but_digits_and_parse_int(x.get_text()) for x in sw.m('.PostBottomAction__count')]
            #if stats != []:
            #    lices = stats[0]
            #    comments = stats[1] if len(stats) == 3 else 0 # may miss comments and reposts? TODO
            #    reposts = stats[2] if len(stats) == 3 else (stats[1] if len(stats) == 2 else 0) # reposts can be banned?
            #else:
            #    lices = comments = reposts = -1
            resultPost = {'id' : id_, "from" : subtitle_from, "text" : text, 'when' : when, 'imgs' : imgs_data, 'videos' : videos_lincs, 'audios' : audios_data, 'lincs' : {'away' : away_lincs, 'other' : other_lincs}, 'first_comments' : [], "voting_data" : votingData, 'stats' : {'lices' : lices, 'comments' : comments, 'reposts' : reposts}}
            result.append(resultPost)
        elif is_comment:
            author_el = sw.s('.author')
            from_ = author_el.get_text()
            from_id = author_el.g('data-from-id')
            text = sw.s('.wall_reply_text').get_text('\n') # no support for everything except text for now; remove \n after mention? TODO
            when = sw.s('.rel_date').get_text()
            #print("before", result[-1]["comments"])
            if result == []:
                print("warning: no posts to append comments to")
                continue
            result[-1]['first_comments'].append({'from' : from_, 'from_id' : from_id, 'text' : text, 'when' : when})
            #print("after", result[-1]["comments"])

def toDb(data, path):
    import sqlite3
    db = sqlite3.connect(path)
    c = db.cursor()
    c.execute("CREATE TABLE IF NOT EXISTS posts (internalId INTEGER PRIMARY KEY AUTOINCREMENT, srcId INT, postId INT, when_ TEXT, from_ TEXT, text TEXT, votingData TEXT, lices INT, comments INT, reposts INT)")
    c.execute("CREATE TABLE IF NOT EXISTS imgs (internalId INTEGER REFERENCES posts(internalId), linc TEXT)")
    c.execute("CREATE TABLE IF NOT EXISTS videos (internalId INTEGER REFERENCES posts(internalId), linc TEXT)")
    c.execute("CREATE TABLE IF NOT EXISTS audios (internalId INTEGER REFERENCES posts(internalId), data TEXT)")
    c.execute("CREATE TABLE IF NOT EXISTS lincs (internalId INTEGER REFERENCES posts(internalId), linc TEXT)")
    c.execute("CREATE TABLE IF NOT EXISTS comments (internalId INTEGER REFERENCES posts(internalId), from_ TEXT, from_id INT, text TEXT, when_ TEXT)")
    firstId = int(c.execute("SELECT MAX(internalId) FROM posts").fetchone()[0] or '0') + 1
    def f(p):
        id_ = p['id'].split('_')
        srcId = int(id_[0])
        postId = int(id_[1])
        s = p['stats']
        ret= [srcId, postId, p['when'], p['from'], p['text'], json.dumps(p['voting_data'],ensure_ascii=False) if p['voting_data'] else '', s['lices'], s['comments'], s['reposts']]
        # empty voting_data is '', better leave {} ?
        return ret
    c.executemany("INSERT INTO posts (srcId, postId, when_, from_, text, votingData, lices, comments, reposts) VALUES (?,?,?,?,?,?,?,?,?)", [f(p) for p in data]) # order guaranteed?
    for i, p in enumerate(data):
        c.executemany("INSERT INTO imgs VALUES (?, ?)", [[firstId + i, img] for img in p['imgs']])
        c.executemany("INSERT INTO videos VALUES (?, ?)", [[firstId + i, img] for img in p['videos']])
        c.executemany("INSERT INTO audios VALUES (?, ?)", [[firstId + i, json.dumps(img,ensure_ascii=False)] for img in p['audios']])
        c.executemany("INSERT INTO lincs VALUES (?, ?)", [[firstId + i, img] for img in [*p['lincs']['away'], *p['lincs']['other']]])
        c.executemany("INSERT INTO comments VALUES (?, ?, ?, ?, ?)", [[firstId + i, c['from'], c['from_id'], c['text'], c['when']] for c in p['first_comments']])
    db.commit()

process_files_in_dir_by_glob('/media/paul/B0701CFA701CC94C/Users/Paul/Downloads/', 'psyamour_part*.json')
toDb(result, '/home/paul/Загрузки/psyamour.db')


import logging
import json
import re

class TickerResponseParser:
    _if_data_is_string = True

    @classmethod
    def _check_if_json(cls, data=None):
        """ Checks if data is a dictionary. """
        if data:
            data_type = type(data)
            if data_type == str:
                cls._if_data_is_string = False
                return data

            return json.loads(data)

    @classmethod
    def get_json(cls, html:str = None):

        json_str = html.split('root.App.main =')[1].split(
            '(this)')[0].split(';\n}')[0].strip()
        data = json.loads(json_str)[
            'context']['dispatcher']['stores']['QuoteSummaryStore']
        # add data about Shares Outstanding for companies' tickers if they are available
        try:
            data['annualBasicAverageShares'] = json.loads(
                json_str)['context']['dispatcher']['stores'][
                    'QuoteTimeSeriesStore']['timeSeries']['annualBasicAverageShares']
        except Exception:
            pass

        # return data
        new_data = json.dumps(data).replace('{}', 'null')
        new_data = re.sub(
            r'\{[\'|\"]raw[\'|\"]:(.*?),(.*?)\}', r'\1', new_data)

        return json.loads(new_data)


# -*- coding: utf-8 -*-
"""
-------------------------------------------------
   File Name：     convert
   Description :
   Author :       Liangs
   date：          2019/8/7
-------------------------------------------------
   Change Activity:
                   2019/8/7:
-------------------------------------------------
"""

def sentence2empty_conllu(sentence_seg: list,
                          sentence_pos: list):
    assert len(sentence_pos) == len(sentence_seg)
    conllu = []
    for index, (word, pos) in enumerate(zip(sentence_seg, sentence_pos), start=1):
        conllu.append(f"{index}\t{word}\t{word}\t{pos}\t{pos}\t_\t_\t_\t_\t_\n")
    return conllu


#!/usr/bin/env python

import re
import glob
import pandas as pd
from sys import argv
import time
from datetime import datetime

assembly_files = glob.glob("*_merged.txt")
all_assembly_stats = "batch_allmerged.txt"
ts = time.time()
st = datetime.fromtimestamp(ts).strftime('%Y-%m-%d_%H-%M-%S')

for assembly_file in assembly_files:
    name=re.sub('_merged.txt', '', assembly_file)[:31]
    file_out = 'stat-' + name + '_' + st + '.xlsx'
    writer = pd.ExcelWriter(file_out)
    df = pd.read_csv(assembly_file, sep='\t', index_col='Sample')
    df.to_excel(writer, name)
    df = pd.read_csv(all_assembly_stats, sep='\t', index_col='Sample')
    df.to_excel(writer, 'batch_assembly_stats')
    print ("Text file, {}, has been placed into Excel file {}" .format(assembly_file, file_out))
    writer.save()


import pandas as pd
from sklearn.mixture import GaussianMixture
from sklearn.cluster import KMeans
import numpy as np
from sklearn.preprocessing import MinMaxScaler
import matplotlib.pyplot as plt
import warnings
warnings.filterwarnings('ignore')
#数据加载
df = pd.read_csv('team_cluster_data.csv',encoding='gbk')
train_x = df[['2019国际排名','2018世界杯排名','2015亚洲杯排名']]
#设置分类个数
GMM = GaussianMixture(n_components=3,covariance_type='full')
GMM.fit(train_x)
predict_GMM = GMM.predict(train_x)
#聚类结果返回到df
df = pd.concat([df,pd.DataFrame(predict_GMM,columns = ['GMM_pred'])],axis =1)
#print(df)

#用kmeans进行测试
SSE = []
for i in range(1,10):
    KM = KMeans(n_clusters=i)
    KM.fit(train_x)
    KM.predict(train_x)
    SSE.append(KM.inertia_)
plt.figure(figsize= (12,9))
plt.plot(range(1,10),SSE)
plt.xlabel('簇数量——聚类的k值')
plt.ylabel('簇的误差平方和SSE')
plt.show()
KM = KMeans(n_clusters=3)
df = pd.concat([df,pd.DataFrame(KM.fit_predict(train_x),columns = ['KM_pred'])],axis =1)
print(df)

EM聚类/聚类（EM）-对球队进行聚类.py

聚类（EM）-对球队进行聚类.py


#!/usr/bin/python3
from conf import banner
from conf import webmapargs
from Core import MsgLkg
from Core.scanandverif import *
from Core import report
import datetime
#url="http://www.btoa.cn/m/login.php"

st=datetime.datetime.now()
print("Starting webmap at "+str(st)+' CST')
report.init()
MsgLkg.info()
MsgLkg.httpHead(webmapargs.url)
MsgLkg.ipLkg(webmapargs.url)
MsgLkg.options(webmapargs.url)
MsgLkg.robots(webmapargs.url)
MsgLkg.mwcs(webmapargs.url)
MsgLkg.httpauth(webmapargs.url)
nikto(webmapargs.url)
py_nmap(webmapargs.url,webmapargs.args.F,webmapargs.args.user,webmapargs.args.passwd,webmapargs.args.userfile,webmapargs.args.passwdfile)

wapiti(webmapargs.url)
#t="http://math.tust.edu.cn/phpmyadmin/export.php"

et=datetime.datetime.now()
print("测试用时：",et-st)
vulnsum.vulnprint()
report.ptrst()
report.htmlend()
report.browser()


from dataclasses import dataclass

from sortedcontainers import SortedSet

from product_list_optimizer import ProductListOptimizer

class PerPartnerSimulator:
    def __init__(self, partner_id, partner_avg_click_cost, npm_in_percents, click_cost_ratio, optimizer_config):
        self.partner_id = partner_id
        self.partner_avg_click_cost = partner_avg_click_cost
        self.npm = npm_in_percents / 100
        self.click_cost_ratio = click_cost_ratio
        self.optimizer = ProductListOptimizer(self.partner_id, partner_avg_click_cost, optimizer_config)
        self.previous_day_excluded_products = []

    def next_day(self, one_day_partner_data):
        if one_day_partner_data is None:
            return PerDayProfitGainFactors(), \
                   PerDayProductsData(products_seen_so_far=list(self.optimizer.products_seen_so_far),
                                      products_to_exclude=self.previous_day_excluded_products,
                                      products_actually_excluded=[])

        one_day_partner_data_only_excluded = one_day_partner_data.loc[
            one_day_partner_data['product_id'].isin(self.previous_day_excluded_products)]
        one_day_partner_data_without_excluded = one_day_partner_data.loc[
            -one_day_partner_data['product_id'].isin(self.previous_day_excluded_products)]

        per_day_profit_gain_factors = self.__calculate_per_day_profit_gain_factors(
            one_day_partner_data_only_excluded,
            one_day_partner_data_without_excluded
        )

        actually_excluded_products = SortedSet(one_day_partner_data_only_excluded['product_id'])
        per_day_products_data = PerDayProductsData(
            products_seen_so_far=list(self.optimizer.products_seen_so_far),
            products_to_exclude=self.previous_day_excluded_products,
            products_actually_excluded=list(actually_excluded_products))

        self.previous_day_excluded_products = self.optimizer.next_day(one_day_partner_data_without_excluded)
        return per_day_profit_gain_factors, per_day_products_data

    def __calculate_per_day_profit_gain_factors(self, one_day_partner_data_only_excluded,
                                                one_day_partner_data_without_excluded):
        total_clicks_savings = 0.0
        total_sale_losses = 0.0
        total_profit_losses = 0.0
        total_net_profit_gain = 0.0

        for excluded_product_id in self.previous_day_excluded_products:
            excluded_product_df = one_day_partner_data_only_excluded.loc[
                one_day_partner_data_only_excluded['product_id'] == excluded_product_id]
            excluded_product_total_sales = excluded_product_df['sales_amount_in_euro'].sum()
            excluded_product_total_clicks_count = len(excluded_product_df.index)

            excluded_product_clicks_savings = excluded_product_total_clicks_count * self.partner_avg_click_cost
            total_clicks_savings += excluded_product_clicks_savings

            excluded_product_sale_losses = excluded_product_total_sales
            total_sale_losses += excluded_product_sale_losses

            excluded_product_profit_losses = excluded_product_total_sales * self.npm
            total_profit_losses += excluded_product_profit_losses

            excluded_product_net_profit_gain = \
                excluded_product_total_clicks_count * self.partner_avg_click_cost \
                - excluded_product_total_sales * (self.click_cost_ratio + self.npm)
            total_net_profit_gain += excluded_product_net_profit_gain

        not_excluded_products_total_sales = one_day_partner_data_without_excluded['sales_amount_in_euro'].sum()
        not_excluded_products_total_clicks_count = len(one_day_partner_data_without_excluded.index)
        total_sustained_profit = \
            not_excluded_products_total_sales * (self.click_cost_ratio + self.npm) \
            - not_excluded_products_total_clicks_count * self.partner_avg_click_cost

        return PerDayProfitGainFactors(clicks_savings=total_clicks_savings,
                                       sale_losses=total_sale_losses,
                                       profit_losses=total_profit_losses,
                                       sustained_profit=total_sustained_profit,
                                       profit_gain=total_net_profit_gain)

@dataclass
class PerDayProfitGainFactors:
    clicks_savings: float = 0.0
    sale_losses: float = 0.0
    profit_losses: float = 0.0
    sustained_profit: float = 0.0
    profit_gain: float = 0.0

    def to_dict_with_date(self, date):
        return {
            'day': date.strftime('%Y-%m-%d'),
            'clicksSavings': self.clicks_savings,
            'saleLosses': self.sale_losses,
            'profitLosses': self.profit_losses,
            'sustainedProfit': self.sustained_profit,
            'profitGain': self.profit_gain
        }

@dataclass
class PerDayProductsData:
    products_seen_so_far: list
    products_to_exclude: list
    products_actually_excluded: list

    def to_dict_with_date(self, date):
        return {
            'day': date.strftime('%Y-%m-%d'),
            'productsSeenSoFar': self.products_seen_so_far,
            'productsToExclude': self.products_to_exclude,
            'productsActuallyExcluded': self.products_actually_excluded
        }


import random
import sys

puzzles = [
    [ "humanities", "sam", "samantha", "damon", "liane", "humans", "ancestor", "cultures", "civilizations", "angelisland", "ellisisland", "stereotype", "nativeamerican", "ohlone", "artifact", "immigration", "goldrush", "migration", "generation", "chinese", "mexican", "bracero", "greatdepression", "segregation", "slavery", "civilrights", "phoenixes", "rainbowsharks", "greencard" ],
    [ "math", "emily", "addition", "subtraction", "multiplication", "division", "negative", "kenken", "riddles", "wordproblems", "mathcounts", "moens", "divisor", "setpuzzles", "equations", "decimals", "mixednumbers", "improperfraction", "powers", "squareroots", "factors", "multiples", "prime", "algebra", "distributive", "commutative", "associative", "exponents", "negatives", "fractions", "numerator", "denominator", "primefactors", "primefactorization", "lcm", "gcf", "patterns", "systematic", "operation", "numbers", "digits", "double", "triple", "single", "quadruple" ],
    [ "science", "elena", "amy", "chemist", "experiment", "mixture", "plant", "bird", "flight", "stemfair", "steamday", "data", "reaction", "molecule", "atom", "nuclear", "power", "mass", "light", "sound", "water", "soundwaves", "tension", "refraction", "defraction", "solder", "arduino", "distance", "rate", "time" ],
    [ "sel", "lisa", "helpful", "imessage", "trashcan", "community", "exclusion", "inclusion", "bestself", "zentangle", "feelings", "emotion", "emotionalthemometer", "listen", "heart", "calm", "tone", "selfreflection", "talkitout", "intention", "mindfullness", "listenwitheyes", "deescalate", "cooloff", "stepup", "stepdown", "empathy" ],
    [ "swi", "rebecca", "noun", "verb", "adverb", "adjective", "handwriting", "story", "base", "suffix", "compoundword", "prefix", "root", "greek", "latin", "middleenglish", "oldenglish", "final", "medial", "initial", "vowel", "script", "grapheme", "phoneme", "syllable" ],
    [ "pe", "zubin", "exercise", "running", "pushharder", "healthy", "diet", "food", "jumprope", "sports", "football", "basketball", "soccer", "hockey", "climbing", "skiing", "swimming", "biking", "muscles", "bones", "body", "pingpong", "tennis", "persistence", "dodgeball", "thunderball", "ctf", "nutrition", "fiber", "lowsugar", "calories" ],
    [ "scratch", "lora", "code", "integer", "string", "float", "if", "for", "while", "true", "false", "variable", "list", "listoflists", "array", "datastructure", "function", "parameters", "indentation", "python", "javascript", "arduino", "concatenate", "algorithm", "logic", "loops", "break", "continue", "pixel", "sprite", "input", "output" ],
    [ "art", "reenie", "paint", "abstract", "modern", "clay", "sculpture", "tone", "statue", "colors", "carve", "brush", "design", "greetingcards", "drawing", "sketching", "pictures", "photos" ],
    [ "music", "gemma", "note", "rhythm", "beat", "song", "tone", "scale", "chorus", "instrument", "piano", "violin", "bass", "guitar", "chello", "trumpet", "melody", "harmony", "tune", "tenor", "pitch" ],
    [ "laraine", "kindergarten", "gingerbreadman", "investigation", "magnifyingglass", "flight", "detective", "klawn", "adddetail", "doyourbestwork", "choice", "mysteryreader", "circletime", "davinci", "monalisa", "postoffice", "postmaster", "sandbox", "garden", "joeyarea", "snacktime", "morningmeeting", "schedule", "readingtime", "clues", "curiosity", "resilience", "pioneer" ],
    [ "nueva", "diane", "megan", "community", "forts", "mansion", "teachers", "administration", "collaboration", "leadership", "campus", "gracious", "spirit", "kindness", "thankful", "caring", "innovate", "inclusion", "humor", "wisdom", "ilab", "ecenter", "sel", "swi", "quest", "stemfair", "steamday", "ilc", "garden", "trips", "auction", "klawn", "mavericks", "balletlawn", "library", "upperschool", "lowerschool", "differentiation", "cafe", "passionate", "citizenship", "stewardship", "asynchronous", "litclub", "bookgroups", "pathofthehero", "farmersmarket", "imessage", "stepupday", "celebrate" ],
    [ "zelda", "link", "hyrule", "breathofthewild", "championsballad", "hebra", "garudo", "tabantha", "divinebeast", "lostwoods", "amiibo", "faron", "hyrulecastle", "flameblade", "frostblade", "twilightbow", "sheikahslate", "shrine", "stable", "elixir", "champions", "parry", "durian", "mastersword", "hylianshield", "ancientbladesaw", "fireblight", "windblight", "waterblight", "thunderblight", "vahmedoh", "vahruta", "vahrudania", "vahnaboris", "bokoblin", "moblin", "lizafos", "chuchu", "lynel", "hinox", "ganon", "guardian", "akala", "greatplateau", "ancientarmor", "ancientbow", "ancientshortsword", "ancientshield" ],
    [ "minecraft", "iron", "gold", "diamond", "coal", "wood", "leather", "chest", "craftingtable", "furnace", "enchantingtable", "fence", "sheep", "wool", "cow", "pig", "dye", "dirt", "glass", "planks", "mobs", "coblestone", "slime", "spider", "skeleton", "enderman", "creeper", "endermite", "zombie", "desertzombie", "pickaxe", "nether", "end", "redstone" ],
    [ "twentythirty", "caden", "maddie", "griffen", "mari", "kai", "siena", "avi", "nikhil", "ishaan", "matthew", "anaya", "ellery", "natalie", "mayak", "arya", "maren", "audrey", "mayal", "sophia", "felix", "zoe", "ryder", "jt", "emily", "theo", "aoife", "nico", "elbert", "colton", "neel", "kate", "ishan", "taiye", "nyxerre", "chloes", "iliya", "jack", "katherine", "owen", "chloew", "sylvie", "sam", "damon", "samantha", "liane" ]
]

boardSize = 30
board = []
directions = [ "right", "left", "up", "down", "up right", "up left", "down right", "down left" ]

# Regeneration:
# $ python3 wordsearch.py > README.md
# $ python3 wordsearch.py solution > SOLUTION.md
def main():

    for words in puzzles:
        initializeBoard()
        insertWords(words)
        printHeader(words[0])
        replaceDot()
        printBoard()
        printWords(words)
        printFooter()

def printHeader(title):
    print()
    print()
    print()
    print("# ", title.upper())
    print()
    print("```")

def printFooter():
    print("```")

def initializeBoard():
    global board
    board = []
    for row in range(boardSize):
        board.append([])
        for _ in range(boardSize):
            board[row].append('.')

def printBoard():
    print()
    print()
    for row in range(boardSize):
        for column in range(boardSize):
            if (column == 0):
                print("    ", end="")
            if (board[row][column] == '.'):
                print(".", end="  ")
            else:
                print(board[row][column], end="  ")
        print()
        print()

def printWords(words):
    print()
    count = 0
    for word in words:
        print("   ", word.ljust(20), end="")
        count = count + 1
        if count == 4:
            print();
            count = 0
    print()

def insertWords(words):
    for word in words:
        while True:
            row = random.randint(0, (boardSize - 1))
            column = random.randint(0, (boardSize - 1))
            direction = random.choice(directions)
            valid = isValid(word, row, column, direction)
            if valid == False:
                continue
            insertWord(word, row, column, direction)
            break

def isValid(word, row, column, direction):
    for ch in word:

        if row >= boardSize or row < 0:
            return False
        if column >= boardSize or column < 0:
            return False

        if board[row][column] != ".":
            if board[row][column] != ch:
                return False

        updateDirectionList = updateDirection(row, column, direction)
        row = updateDirectionList[0]
        column = updateDirectionList[1]

    return True

def insertWord(word, row, column, direction):
    for ch in word:
        board[row][column] = ch
        updateDirectionList = updateDirection(row, column, direction)
        row = updateDirectionList[0]
        column = updateDirectionList[1]

def replaceDot():
    letters = [ "a", "b", "c", "d", "e", "f", "g", "h", "i", "j", "k", "l", "m", "n", "o", "p", "q", "r", "s", "t", "u", "v", "w", "x", "y", "z" ]
    for row in range(boardSize):
        for column in range(boardSize):
            letterPut = random.choice(letters)
            if board[row][column] == ".":
                board[row][column] = letterPut

def updateDirection(row, column, direction):
    if direction == "right":
        column = column + 1
        return [row, column]
    elif direction == "left":
        column = column - 1
        return [row, column]
    elif direction == "up":
        row = row - 1
        return [row, column]
    elif direction ==  "down":
        row = row + 1
        return [row, column]
    elif direction == "up right":
        row = row - 1
        column = column + 1
        return [row, column]
    elif direction == "up left":
        row = row - 1
        column = column - 1
        return [row, column]
    elif direction == "down right":
        row = row + 1
        column = column + 1
        return [row, column]
    elif direction == "down left":
        row = row + 1
        column = column - 1
        return [row, column]

main()


from decouple import config
import pickle
from aiokafka import AIOKafkaConsumer
from fastapi import FastAPI

from handler import payout_handler

app = FastAPI()

@app.on_event("startup")
async def startup():
    print(config("KAFKA_TOPIC_NAME"))
    consumer = AIOKafkaConsumer(
        config("KAFKA_TOPIC_NAME"),
        bootstrap_servers=f"{config('KAFKA_HOST')}:{config('KAFKA_POST')}",
    )
    await consumer.start()
    try:
        async for msg in consumer:
            deserialized_data = pickle.loads(msg.value)
            print(deserialized_data)
            payout_handler(deserialized_data)
    finally:
        await consumer.stop()


import sys,os,random,time,json
import logging

class SensorCLI():
    def __init__(self):
        filepath=os.path.join(os.getcwd(),'sensor_data')
        if (False == os.path.exists(filepath)):
            os.makedirs(filepath)
        self.sample_interval = 10  #millisecond
        logging.basicConfig(filename = os.path.join(os.getcwd(),'mylog.txt'), level = logging.DEBUG,
            format='LINE %(lineno)-4d : %(levelname)-8s %(message)s')

    def moni_data(self,songname,songtime):
        filepath=os.path.join(os.getcwd(),'sensor_data')
        if (False == os.path.exists(filepath)):
            os.makedirs(filepath)
        data={}
        data['interval'] = self.sample_interval
        data['sample'] = []
        for t in range(int(songtime)*1000/self.sample_interval ):
            data['sample'].append([round(random.uniform(-5, 5),3),
                    round(random.uniform(-5, 5),3),
                    round(random.uniform(-3, 3),3)])
            if(len(data['sample'])%10 == 0):
                self.write_data(songname,data)
            time.sleep(0.1)

    def write_data(self,songname,data):
        filename=self.get_data_file(songname)
        fp = open(filename,'w')
        fp.write(json.dumps(data))
        fp.close()

    def get_data_file(self,songid):
        return os.path.join(os.path.join(os.getcwd(),'sensor_data'),songid+'.data')

    #get sensor data
    def get_data(self,songid,startmsec,endmsec):
        filename=self.get_data_file(songid)
        if(os.path.exists(filename)):
            fp = open(filename,'r')
            data=json.loads(fp.read())
            startIndex=int(startmsec)/int(data['interval'])
            endIndex=int(endmsec)/int(data['interval'])
            data['sample']=data['sample'][int(startIndex):int(endIndex)]
            self.show_result(0,data)
        else:
            self.show_result(-1,"no data")

    def show_result(self,code,data):
        obj={}
        obj['code']=code
        obj['data']=data
        print(json.dumps(obj))

def main(argv):
    sensorcli = SensorCLI()
    cmd=argv[1]
    logging.debug('cmd='+' '.join(argv))
    if("get_data" == cmd):
        sensorcli.get_data(argv[2],argv[3],argv[4])
    elif("moni_data" == cmd):
        sensorcli.moni_data(argv[2],argv[3])
    elif("start_record" == cmd):
        sensorcli.start_record(argv[2],argv[3])
    else:
        print("no such cmd:"+cmd)

if __name__ == '__main__':
    main(sys.argv)


# use Python 3

#primes = [2, 3, 5, 7, 11, 13, 17, 19, 23, 29, 31, 37, 41, 43, 47, 53, 59, 61, 67, 71, 73, 79, 83, 89, 97]

# find all prime numbers in range from 0 to count
def findprimes(count):
    primes = []
    for x in range(count):
        isprime = True
        if x == 0 or x == 1:
            continue
        elif x == 2:
            pass
        else:
            for y in primes:
                asdf = x / float(y)
                if x / float(y) == x / y:
                    isprime = False
                    break
                else:
                    continue
        if isprime:
            primes.append(x)
    return primes

# returns a greatest common denominator
def findgcd(num1, num2):
    print('gcd(', num1, num2, ')')
    if num2 == 0:
        return num1
    count = 0
    while True:
        b = num2 * count
        remain = num1 - b
        if remain < num2:
            break
        count += 1
    return findgcd(num2, remain)

# returns a greatest common denominator but faster
def findgcdbetter(a, b):
    print('gcdbetter(', a, b, ')')
    if b == 0:
        return a
    else:
        r = a % b
        return findgcdbetter(b, r)

# find lowest common multiple
def findlcm(a, b):
    x = a * b
    y = findgcdbetter(a, b)
    return x / y

print(findgcdbetter(1953, 1937))


#! C:/Users/%USERPROFILE%/AppData/Local/Programs/Python/Python39/python.exe
import os
import sys
import random
from serverkeys import *
from twilio.rest import Client
import re

client_phone =  sys.argv[1]
random_id = ''.join([str(random.randint(0, 999)).zfill(3) for _ in range(2)])
account_sid = TWILIO_ACCOUNT_SID
auth_token = TWILIO_AUTH_TOKEN
srvr_phone = TWILIO_PHONE_NUMBER
client = Client(account_sid, auth_token)
phone_number = client.lookups.phone_numbers(client_phone).fetch(type=['carrier'])

if phone_number.carrier.get('type') == 'viop':
    print('null')

elif phone_number.carrier.get('type') == 'mobile':
    client.messages.create(
                            body=random_id,
                            from_=srvr_phone,
                            to=client_phone
                          )
    print(random_id)

else:
    print('null')


'''
modulo python: LAInterpreter

titulo:
    Analisador Semantico para a Linguagem Algoritmica(LA)
    TRABALHO 3 - COMPILADORES 1

autores:
    Luan V. Moraes da Silva - 744342
    Guilherme Servidoni - 727339
    Alisson Roberto Gomes - 725721
'''

from LASemantico import SemanticoUtils
from LAVisitor import LAVisitor
from LAUtils import Escopos

#
# LAInterpreter
# params: LAVisitor
# return: class nao produz retorno
class LAInterpreter(LAVisitor):
    escopos = Escopos()
    utils = SemanticoUtils()

    def visitPrograma(self, ctx):
        self.escopos.clearEscopos()
        self.escopos.criarEscopo()
        self.visitDeclaracoes(ctx.declaracoes())
        self.visitCorpo(ctx.corpo())

    # visitDeclaracoes
    # params: ctx
    # return: funcao original visitara cada declaracao
    def visitDeclaracoes(self, ctx):
        for declaracao in ctx.decl_local_global():
            self.visitDecl_local_global(declaracao)

    def visitDeclaracao_global(self, ctx):
        self.utils.verificar(self.escopos, ctx)

    def visitDeclaracao_local(self, ctx):
        self.utils.verificar(self.escopos, ctx)

    # visitCorpo
    # params: ctx
    # return: uma lista com o ou mais declaracoes e comandos
    def visitCorpo(self, ctx):
        for decs in ctx.declaracao_local():
            self.utils.verificar(self.escopos, decs)

        for cmd in ctx.cmd():
            if(cmd.cmdRetorne() != None):
                self.utils.erroRetorne(cmd.start)

            self.utils.verificar(self.escopos, cmd)


import igraph as ig
import matplotlib.pyplot as plt

ig.config["plotting.backend"] = "matplotlib"
ig.config["plotting.layout"] = "auto"
ig.config.save()

n = 5
edges = ([(0, 1), (0, 2),
          (1, 2), (1, 3), (1, 4),
          (2, 3), (2, 4),
          (3, 4)])

g = ig.Graph(n, edges)

divisor = [10, 20, 30, 40, 50]
g.vs["divisor"] = divisor
g.es["att"] = "goodbye"
g.es[g.get_eid(0,2)]["att"] = "hello"

print(g.es.select(_within=[0,2]))

fig, ax = plt.subplots(figsize=(5,5))

ig.plot(
    g,
    target=ax,
    vertex_color="red",
    vertex_label=g.vs["divisor"],
    label_color="white",
    edge_label=g.es["att"]
)

plt.show()


import uuid
import json

class Message(object):
    def __init__(self, send_from, send_to) -> None:
        self.msg_data = {
            'msg_id': self.create_id(),
            'send_from': send_from,
            'send_to': send_to
        }

    def get_msg_data(self) -> dict:
        return self.msg_data

    def get_msg(self) -> str:
        return json.dumps(self.msg_data)

    def create_id(self):
        return str(uuid.uuid1())

class REGISTRATION_REQ(Message):
    def __init__(self, send_from, send_to, role, location) -> None:
        super().__init__(send_from, send_to)
        self.msg_data['service'] = 'robot_registration'
        self.msg_data['msg_type'] = 'REGISTRATION_REQ'
        self.msg_data['payload'] = {
            'role': role,
            'loc': location
        }

class REGISTRATION_RES(Message):
    def __init__(self, send_from, send_to) -> None:
        super().__init__(send_from, send_to)
        self.msg_data['service'] = 'robot_registration'
        self.msg_data['msg_type'] = 'REGISTRATION_RES'

class ORDER_REQ(Message):
    def __init__(self, send_from, send_to, order) -> None:
        super().__init__(send_from, send_to)
        self.order_id = self.create_id()
        self.msg_data['service'] = 'order_processing'
        self.msg_data['msg_type'] = 'ORDER_REQ'
        self.msg_data['payload'] = {
            'order_id': self.order_id,
            'order': order
        }

    def get_order_id(self) -> str:
        return self.order_id

class ORDER_RES(Message):
    def __init__(self, send_from, send_to, order_id) -> None:
        super().__init__(send_from, send_to)
        self.msg_data['service'] = 'order_processing'
        self.msg_data['msg_type'] = 'ORDER_RES'
        self.msg_data['payload'] = {
            'order_id': order_id
        }


import socket
s = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
s.bind(("127.0.0.1", 20131))
s.listen(2)
print("Server is ready to connect!")
while True:
	user, addr = s.accept()
	print("NEW USER!")
	user.send("Welcome!".encode("utf-8"))
	data = user.recv(1024)
	print(data.decode("utf-8"))


from PIL import Image, ImageTk
from matplotlib.figure import Figure
from matplotlib.backends.backend_tkagg import FigureCanvasTkAgg

import tkinter as tk
from tkinter import font
from typing import List
import time

import ai
from game import BattleshipGame, EMPTY_TILE_ID

class BattleshipGUI(tk.Tk):
    def __init__(self, battleship: BattleshipGame, reference_size: int):
        super().__init__()

        # Some deafault inits that we will need for the UI
        self.reference_size = reference_size
        self.battleship = battleship
        self.title("Battleship AI")

        # 3 size font tags. NOT ALL USED
        self.font_large = font.Font(size=self.reference_size * 2)
        self.font_med = font.Font(size=self.reference_size * 8)
        self.font_small = font.Font(size=self.reference_size // 2)

        # A mapping of all of our images for the board
        self.image_dict = {
            "water": ImageTk.PhotoImage(
                Image.open("./images/water.jpeg")
                .convert("RGB")
                .resize(size=(self.reference_size, self.reference_size))
            ),
            "water_hit": ImageTk.PhotoImage(
                Image.open("./images/water_hit.jpeg")
                .convert("RGB")
                .resize(size=(self.reference_size, self.reference_size))
            ),
            "ship": ImageTk.PhotoImage(
                Image.open("./images/ship.jpeg")
                .convert("RGB")
                .resize(size=(self.reference_size, self.reference_size))
            ),
            "ship_hit": ImageTk.PhotoImage(
                Image.open("./images/ship_hit.jpeg")
                .convert("RGB")
                .resize(size=(self.reference_size, self.reference_size))
            ),
            # TKinter doesnt do paddinf for labels on mac, so the size is scaled to be slightly bigger for the player
            "water_big": ImageTk.PhotoImage(
                Image.open("./images/water.jpeg")
                .convert("RGB")
                .resize(
                    size=(
                        int(self.reference_size * 1.2),
                        int(self.reference_size * 1.2),
                    )
                )
            ),
            "water_hit_big": ImageTk.PhotoImage(
                Image.open("./images/water_hit.jpeg")
                .convert("RGB")
                .resize(size=(self.reference_size, self.reference_size))
            ),
            "ship_big": ImageTk.PhotoImage(
                Image.open("./images/ship.jpeg")
                .convert("RGB")
                .resize(
                    size=(
                        int(self.reference_size * 1.2),
                        int(self.reference_size * 1.2),
                    )
                )
            ),
            "ship_hit_big": ImageTk.PhotoImage(
                Image.open("./images/ship_hit.jpeg")
                .convert("RGB")
                .resize(size=(self.reference_size, self.reference_size))
            ),
        }

        # What I hopefully want the board to look like
        """
        New Game
        +---------------+
        |               |
        |  Enemy View   +---------------+
        |               |               |
        +---------------+   AI Moves    |
        |               |               |
        |   Your View   +---------------+
        |               |
        +---------------+
        """

        # FRAMES
        # ------

        # self nested frames
        self.game_play_frame = tk.Frame(
            master=self,
            padx=self.reference_size // 4,
            pady=self.reference_size // 4,
            relief=tk.SOLID,
        )
        self.ai_view_frame = tk.Frame(
            master=self,
            padx=self.reference_size // 4,
            pady=self.reference_size // 4,
            relief=tk.SOLID,
        )
        self.reset_button = tk.Button(
            master=self, font=self.font_small, text="Reset Game", command=self.reset
        )

        self.reset_button.grid(column=0, row=0, sticky="nsw")
        self.game_play_frame.grid(column=0, row=1)
        self.ai_view_frame.grid(column=1, row=1)

        # gameplay nested frames
        self.enemy_view_frame = tk.Frame(
            master=self.game_play_frame,
            padx=self.reference_size // 2,
            pady=self.reference_size // 2,
            relief=tk.SOLID,
        )
        self.player_view_frame = tk.Frame(
            master=self.game_play_frame,
            padx=self.reference_size // 2,
            pady=self.reference_size // 2,
            relief=tk.SOLID,
        )
        self.enemy_view_label = tk.Label(
            master=self.game_play_frame, font=self.font_small, text="Enemy Tile Select"
        )
        self.player_view_label = tk.Label(
            master=self.game_play_frame, font=self.font_small, text="Your Tile Select"
        )

        self.enemy_view_label.grid(column=0, row=0)
        self.enemy_view_frame.grid(column=0, row=1)
        self.player_view_label.grid(column=0, row=2)
        self.player_view_frame.grid(column=0, row=3)

        # ENEMY VIEW FRAME
        # ----------------
        self.enemy_view_buttons: List[tk.Button] = []
        # itterating over all of the board length and creating buttons linked to the grid size
        for row in range(self.battleship.size):
            for column in range(self.battleship.size):

                # A function to help allow for a button to refrence a command, but with a changing var
                # NOTE. just using the lambda would place a reference on the button, that is why we have this closure
                def fire_closure(x_position: int, y_position: int):
                    return lambda: self.fire(
                        x_position=x_position, y_position=y_position
                    )

                # Creating a button of the tile and adding it to the main list
                _button = tk.Button(
                    master=self.enemy_view_frame,
                    image=self.image_dict["water"],
                    command=fire_closure(x_position=column, y_position=row),
                )
                _button.grid(column=column, row=row)
                self.enemy_view_buttons.append(_button)

        # PLAYER VIEW FRAME
        # -----------------
        self.player_view_game_labels: List[tk.Label] = []
         # itterating over all of the board length and creating label linked to the grid size
        for row in range(self.battleship.size):
            for column in range(self.battleship.size):
                 # Creating a label of the tile and adding it to the main list
                _label = tk.Label(
                    master=self.player_view_frame,
                    image=self.image_dict["water_big"]
                    if self.battleship.player_1_board[row][column].ship_id
                    == EMPTY_TILE_ID
                    else self.image_dict["ship_big"],
                )
                _label.grid(column=column, row=row)
                self.player_view_game_labels.append(_label)

        # AI VIEW FRAME
        # -------------
        self.graph_figure = Figure(
            figsize=(
                self.reference_size,
                self.reference_size,
            ),
            dpi=self.reference_size,
        )
        self.graph_canvas = FigureCanvasTkAgg(
            master=self.ai_view_frame, figure=self.graph_figure
        )
        self.subplot = self.graph_figure.add_subplot(111)

        # Grabbing the initial AI best moves
        ai_heat_map_board, _, _ = ai.find_best_move(
            board=self.battleship.get_view_board_opponent(opponent_id=1),
            ship_lengths=[
                len(ship["tiles"])
                for ship_id, ship in self.battleship.player_1_pieces.items()
                if not ship["is_sank"]
            ],
        )

        # creating a heatmap of what the AI thinks are the best moves
        self.heatmap = self.subplot.imshow(
            ai_heat_map_board, cmap="hot_r", interpolation="nearest"
        )
        self.cbar = self.graph_figure.colorbar(self.heatmap)
        self.cbar.set_label(
            "AI Moves Confidence (heatmap)",
            fontsize=self.reference_size * 2,
            rotation=270,
            labelpad=self.reference_size * 2,
        )
        self.subplot.figure.set_facecolor("gray")
        self.subplot.figure.suptitle("AI Move View", fontsize=self.reference_size * 4)
        self.subplot.tick_params(axis="x", labelsize=self.reference_size * 2)
        self.subplot.tick_params(axis="y", labelsize=self.reference_size * 2)

        self.graph_canvas.draw()
        self.graph_canvas.get_tk_widget().pack()

        return

    def update_backend_to_frontend(self):
        """A function to connect all of the GUI with what works behind scenes
        """
        # itterating over the board and updating the buttons and labels
        for row in range(self.battleship.size):
            for column in range(self.battleship.size):

                # Updating the players labels
                if self.battleship.player_1_board[row][column].is_hit:
                    self.player_view_game_labels[
                        column + (row * self.battleship.size)
                    ].config(
                        image=self.image_dict["water_hit_big"]
                        if self.battleship.player_1_board[row][column].ship_id
                        == EMPTY_TILE_ID
                        else self.image_dict["ship_hit_big"]
                    )
                else:
                    self.player_view_game_labels[
                        column + (row * self.battleship.size)
                    ].config(
                        image=self.image_dict["water_big"]
                        if self.battleship.player_1_board[row][column].ship_id
                        == EMPTY_TILE_ID
                        else self.image_dict["ship_big"]
                    )
                 # Updating the enemys buttons
                if self.battleship.player_2_board[row][column].is_hit:
                    self.enemy_view_buttons[
                        column + (row * self.battleship.size)
                    ].config(
                        image=self.image_dict["water_hit"]
                        if self.battleship.player_2_board[row][column].ship_id
                        == EMPTY_TILE_ID
                        else self.image_dict["ship_hit"]
                    )
                else:
                    self.enemy_view_buttons[
                        column + (row * self.battleship.size)
                    ].config(image=self.image_dict["water"])

        # Clear existing graph
        self.subplot.clear()

        # Grabbing the AI best moves
        ai_heat_map_board, _, _ = ai.find_best_move(
            board=self.battleship.get_view_board_opponent(opponent_id=1),
            ship_lengths=[
                len(ship["tiles"])
                for ship_id, ship in self.battleship.player_1_pieces.items()
                if not ship["is_sank"]
            ],
        )
        self.heatmap = self.subplot.imshow(
            ai_heat_map_board, cmap="hot_r", interpolation="nearest"
        )
        self.subplot.figure.set_facecolor("gray")
        self.subplot.figure.suptitle("AI Move View", fontsize=self.reference_size * 4)
        self.subplot.tick_params(axis="x", labelsize=self.reference_size * 2)
        self.subplot.tick_params(axis="y", labelsize=self.reference_size * 2)
        self.graph_canvas.draw()

        # Updating the tkinter UI
        self.update()

    def fire(self, x_position: int, y_position: int):
        """A function for the players buttons to fire at a enemy tile

        Args:
            x_position (int): the x location of the button
            y_position (int): the y location of the button
        """

        # Firing at the ship!
        did_hit = self.battleship.fire_at_tile(
            opponent_id=2, x_position=x_position, y_position=y_position
        )

        # Updating the board, now that the player selected a tile
        self.update_backend_to_frontend()

        # if the player did not hit, then it is the AI's turn
        if not did_hit:

            # Grabbing the AI's move
            _, ai_x_move, ai_y_move = ai.find_best_move(
                board=self.battleship.get_view_board_opponent(opponent_id=1),
                ship_lengths=[
                    len(ship["tiles"])
                    for ship_id, ship in self.battleship.player_1_pieces.items()
                    if not ship["is_sank"]
                ],
            )

            # While the AI keeps hitting the player, we want to update the board and continue on with the next move
            while self.battleship.fire_at_tile(
                opponent_id=1, x_position=ai_x_move, y_position=ai_y_move
            ):
                self.update_backend_to_frontend()
                _, ai_x_move, ai_y_move = ai.find_best_move(
                    board=self.battleship.get_view_board_opponent(opponent_id=1),
                    ship_lengths=[
                        len(ship["tiles"])
                        for ship_id, ship in self.battleship.player_1_pieces.items()
                        if not ship["is_sank"]
                    ],
                )
                # small sleep so this doesnt happen all at once
                time.sleep(0.5)

            self.update_backend_to_frontend()

        return

    def reset(self):
        """A function for if a new game is wanted to be played
        """
        self.battleship = BattleshipGame(self.battleship.size)
        self.battleship.set_random_board(player_id=1)
        self.battleship.set_random_board(player_id=2)
        self.update_backend_to_frontend()

def main():
    game = BattleshipGame(size=10)
    game.set_random_board(player_id=1, seed=4)
    game.set_random_board(player_id=2, seed=1)

    gui = BattleshipGUI(battleship=game, reference_size=24)
    gui.mainloop()

if __name__ == "__main__":
    main()