from pickle import MARK
import matplotlib.pyplot as plt
from matplotlib.ticker import (MultipleLocator, FormatStrFormatter,AutoMinorLocator)

import pandas as pd
import numpy as np
import math
import os
import shutil
from PIL import Image

import ipywidgets as widgets
from IPython.display import display

import nafuma.electrochemistry as ec
import nafuma.plotting as btp
import nafuma.auxillary	as aux

def plot_gc(data, options=None):

	# Update options
	default_options = {
		'force_reload': False,
		'x_vals': 'capacity', 'y_vals': 'voltage',
		'which_cycles': 'all',
		'limit': None, # Limit line to be drawn
		'exclude_cycles': [],
		'show_plot': True,
		'summary': False,
		'charge': True, 'discharge': True,
		'colours': None,
		'markers': None,
		'differentiate_charge_discharge': True,
		'gradient': False,
		'interactive': False,
		'interactive_session_active': False,
		'rc_params': {},
		'format_params': {},
		'save_gif': False,
		'save_path': 'animation.gif',
		'fps': 1,
		'fig': None, 'ax': None,
		'edgecolor': plt.rcParams['lines.markeredgecolor'],
		'plot_every': 1,
		}

	options = aux.update_options(options=options, default_options=default_options)

	# Read data if not already loaded
	if not 'cycles' in data.keys() or options['force_reload']:
		data['cycles'] = ec.io.read_data(data=data, options=options)

	# Update list of cycles to correct indices
	update_cycles_list(data=data, options=options)

	if options['interactive']:
		options['interactive'], options['interactive_session_active'] = False, True
		plot_gc_interactive(data=data, options=options)
		return

	colours = generate_colours(options=options)
	markers = generate_markers(options=options)

	if not options['summary']:

		if options['show_plot']:
			# Prepare plot

			if not options['fig'] and not options['ax']:
				fig, ax = btp.prepare_plot(options=options)
			else:
				fig, ax = options['fig'], options['ax']

			for i, cycle in enumerate(options['which_cycles']):
					if options['charge']:
						data['cycles'][cycle][0].plot(x=options['x_vals'], y=options['y_vals'], ax=ax, c=colours[i][0])

					if options['discharge']:
						data['cycles'][cycle][1].plot(x=options['x_vals'], y=options['y_vals'], ax=ax, c=colours[i][1])

			if options['interactive_session_active']:
				update_labels(options, force=True)
			else:
				update_labels(options)

		if options['save_gif'] and not options['interactive_session_active']:
			if not os.path.isdir('tmp'):
				os.makedirs('tmp')

			# Scale image to make GIF smaller
			options['format_params']['width'] = 7.5
			options['format_params']['height'] = 3

			options['format_params']['dpi'] = 200

			for i, cycle in enumerate(data['cycles']):
				if i in options['which_cycles']:

					giffig, gifax = btp.prepare_plot(options=options)

					if options['charge']:
						cycle[0].plot(x=options['x_vals'], y=options['y_vals'], ax=gifax, c=colours[i][0])
					if options['discharge']:
						cycle[1].plot(x=options['x_vals'], y=options['y_vals'], ax=gifax, c=colours[i][1])

					gifax.text(x=gifax.get_xlim()[1]*0.8, y=3, s=f'{i+1}')
					update_labels(options)

					giffig, gifax = btp.adjust_plot(fig=giffig, ax=gifax, options=options)

					plt.savefig(os.path.join('tmp', str(i+1).zfill(4)+'.png'))
					plt.close()

			img_paths = [os.path.join('tmp', path) for path in os.listdir('tmp') if path.endswith('png')]
			frames = []
			for path in img_paths:
				frame = Image.open(path)
				frames.append(frame)

			frames[0].save(options['save_path'], format='GIF', append_images=frames[1:], save_all=True, duration=(1/options['fps'])*1000, loop=0)

			shutil.rmtree('tmp')

	elif options['summary'] and options['show_plot']:
		# Prepare plot
		if not options['fig'] and not options['ax']:
			fig, ax = btp.prepare_plot(options=options)
		else:
			fig, ax = options['fig'], options['ax']

		mask = []
		for i in range(data['cycles'].shape[0]):
			if i+1 in options['which_cycles']:
				mask.append(True)
			else:
				mask.append(False)

		# Drop the last row if it is midway through a charge in order to avoid mismatch of length of mask and dataset.
		if len(mask) > data['cycles'].shape[0]:
			del mask[-1]
			data['cycles'].drop(data['cycles'].tail(1).index, inplace=True)

		# FIXME To begin, the default is that y-values correspond to x-values. This should probably be implemented in more logical and consistent manner in the future.
		if options['x_vals'] in ['coulombic_efficiency', 'energy_efficiency']:
			data['cycles'].loc[mask].plot(x='cycle', y=options['x_vals'], ax=ax, color=colours[0][1], kind='scatter', s=plt.rcParams['lines.markersize']*10,  marker=markers[0], edgecolor=plt.rcParams['lines.markeredgecolor'])
			if options['limit']:
				ax.axhline(y=options['limit'], ls='--', c='black')

		else:
			if options['charge']:
				yval = 'charge_' + options['x_vals']
				data['cycles'].loc[mask].plot(x='cycle', y=yval, ax=ax, color=colours[0][0], kind='scatter', s=plt.rcParams['lines.markersize']*10, marker=markers[0], edgecolor=plt.rcParams['lines.markeredgecolor'])

			if options['discharge']:
				yval = 'discharge_' + options['x_vals']
				data['cycles'].loc[mask].plot(x='cycle', y=yval, ax=ax, color=colours[0][1], kind='scatter', s=plt.rcParams['lines.markersize']*10, marker=markers[1], edgecolor=plt.rcParams['lines.markeredgecolor'])

			if options['limit']:
				ax.axhline(y=options['limit'], ls='--', c='black')

		if options['interactive_session_active']:
			update_labels(options, force=True)
		else:
			update_labels(options)

	if options['show_plot']:
		fig, ax = btp.adjust_plot(fig=fig, ax=ax, options=options)
		return data['cycles'], fig, ax
	else:
		return data['cycles'], None, None

def plot_gc_interactive(data, options):

	w = widgets.interactive(btp.ipywidgets_update, func=widgets.fixed(plot_gc), data=widgets.fixed(data), options=widgets.fixed(options),
	charge=widgets.ToggleButton(value=True),
	discharge=widgets.ToggleButton(value=True),
	x_vals=widgets.Dropdown(options=['specific_capacity', 'capacity', 'ions', 'voltage', 'time', 'energy'], value='specific_capacity', description='X-values')
	)

	options['widget'] = w

	display(w)

def plot_cv(data, options):

	# Update options
	default_options = {
		'force_reload': False,
		'x_vals': 'voltage', 'y_vals': 'current',
		'which_cycles': 'all',
		'limit': None, # Limit line to be drawn
		'exclude_cycles': [],
		'show_plot': True,
		'charge': True, 'discharge': True,
		'colours': None,
		'differentiate_charge_discharge': True,
		'gradient': False,
		'interactive': False,
		'interactive_session_active': False,
		'rc_params': {},
		'format_params': {},
		'save_gif': False,
		'save_path': 'animation.gif',
		'fps': 1,
		'plot_every': 1,
		'fig': None,
		'ax': None
		}

	options = aux.update_options(options=options, default_options=default_options)

	# Read data if not already loaded
	if not 'cycles' in data.keys() or options['force_reload']:
		data['cycles'] = ec.io.read_data(data=data, options=options)

	# Update list of cycles to correct indices
	update_cycles_list(data=data, options=options)

	colours = generate_colours(options=options)

	if options['show_plot']:
		# Prepare plot
		if not options['fig'] and not options['ax']:
			fig, ax = btp.prepare_plot(options=options)
		else:
			fig, ax = options['fig'], options['ax']

		for i, cycle in enumerate(options['which_cycles']):
			if options['charge']:
				data['cycles'][cycle][0].plot(x=options['x_vals'], y=options['y_vals'], ax=ax, c=colours[i][0])

			if options['discharge']:
				data['cycles'][cycle][1].plot(x=options['x_vals'], y=options['y_vals'], ax=ax, c=colours[i][1])

		# for i, cycle in enumerate(data['cycles']):
		# 	if i in options['which_cycles']:
		# 		if options['charge']:
		# 			cycle[0].plot(x=options['x_vals'], y=options['y_vals'], ax=ax, c=colours[i][0])

		# 		if options['discharge']:
		# 			cycle[1].plot(x=options['x_vals'], y=options['y_vals'], ax=ax, c=colours[i][1])

		update_labels(options)

	if options['save_gif'] and not options['interactive_session_active']:
		if not os.path.isdir('tmp'):
			os.makedirs('tmp')

		# Scale image to make GIF smaller
		options['format_params']['width'] = 7.5
		options['format_params']['height'] = 3

		options['format_params']['dpi'] = 200

		for i, cycle in enumerate(data['cycles']):
			if i in options['which_cycles']:

				giffig, gifax = btp.prepare_plot(options=options)

				if options['charge']:
					cycle[0].plot(x=options['x_vals'], y=options['y_vals'], ax=gifax, c=colours[i][0])
				if options['discharge']:
					cycle[1].plot(x=options['x_vals'], y=options['y_vals'], ax=gifax, c=colours[i][1])

				gifax.text(x=gifax.get_xlim()[1]*0.8, y=3, s=f'{i+1}')
				update_labels(options)

				giffig, gifax = btp.adjust_plot(fig=giffig, ax=gifax, options=options)

				plt.savefig(os.path.join('tmp', str(i+1).zfill(4)+'.png'))
				plt.close()

		img_paths = [os.path.join('tmp', path) for path in os.listdir('tmp') if path.endswith('png')]
		frames = []
		for path in img_paths:
			frame = Image.open(path)
			frames.append(frame)

		frames[0].save(options['save_path'], format='GIF', append_images=frames[1:], save_all=True, duration=(1/options['fps'])*1000, loop=0)

		shutil.rmtree('tmp')

	if options['show_plot']:
		fig, ax = btp.adjust_plot(fig=fig, ax=ax, options=options)
		return data['cycles'], fig, ax
	else:
		return data['cycles'], None, None

def update_labels(options, force=False):

	if 'xlabel' not in options.keys() or force:
		options['xlabel'] = options['x_vals'].capitalize().replace('_', ' ')

	if 'ylabel' not in options.keys() or force:
		options['ylabel'] = options['y_vals'].capitalize().replace('_', ' ')

	if 'xunit' not in options.keys() or force:
		if options['x_vals'] == 'capacity':
			options['xunit'] = options['units']['capacity']
		elif options['x_vals'] == 'specific_capacity':
			options['xunit'] = f"{options['units']['capacity']} {options['units']['mass']}$^{{-1}}$"
		elif options['x_vals'] == 'time':
			options['xunit'] = options['units']['time']
		elif options['x_vals'] == 'ions':
			options['xunit'] = None

	if 'yunit' not in options.keys() or force:
		if options['y_vals'] == 'voltage':
			options['yunit'] = options['units']['voltage']

def update_cycles_list(data, options: dict) -> None:

	if options['which_cycles'] == 'all':
		options['which_cycles'] = [i for i in range(len(data['cycles']))]

	elif isinstance(options['which_cycles'], list):

		cycles =[]

		for cycle in options['which_cycles']:
			if isinstance(cycle, int):
				cycles.append(cycle-1)

			elif isinstance(cycle, tuple):
				interval = [i-1 for i in range(cycle[0], cycle[1]+1)]
				cycles.extend(interval)

		options['which_cycles'] = cycles

	# Tuple is used to define an interval - as elements tuples can't be assigned, I convert it to a list here.
	elif isinstance(options['which_cycles'], tuple):
		which_cycles = list(options['which_cycles'])

		if which_cycles[0] <= 0:
			which_cycles[0] = 1

		elif which_cycles[1] < 0:
			which_cycles[1] = len(options['which_cycles'])

		options['which_cycles'] = [i-1 for i in range(which_cycles[0], which_cycles[1]+1)]

	for i, cycle in enumerate(options['which_cycles']):
		if cycle in options['exclude_cycles']:
			del options['which_cycles'][i]

	options['which_cycles'] = options['which_cycles'][::options['plot_every']]

def prettify_gc_plot(fig, ax, options=None):

	##################################################################
	######################### UPDATE OPTIONS #########################
	##################################################################

	# Define the required options
	required_options = [
	'columns',
	'xticks', 'yticks',
	'show_major_ticks', 'show_minor_ticks',
	'xlim', 'ylim',
	'hide_x_axis', 'hide_y_axis',
	'positions',
	'x_vals', 'y_vals',
	'xlabel', 'ylabel',
	'units', 'sizes',
	'title'
	]

	# Define the default options
	default_options = {
		'columns': 1,
		'xticks': None, 'yticks': None,
		'show_major_ticks': [True, True, True, True], 'show_minor_ticks': [True, True, True, True],
		'xlim': None,'ylim': None,
		'hide_x_axis': False, 'hide_y_axis': False,
		'positions': {'xaxis': 'bottom', 'yaxis': 'left'},
		'x_vals': 'specific_capacity', 'y_vals': 'voltage',
		'xlabel': None, 'ylabel': None,
		'units': {'capacity': 'mAh', 'specific_capacity': r'mAh g$^{-1}$', 'time': 's', 'current': 'mA', 'energy': 'mWh', 'mass': 'g', 'voltage': 'V'},
		'sizes': None,
		'title': None
	}

	aux.update_options(options, required_options, default_options)

	##################################################################
	########################## DEFINE SIZES ##########################
	##################################################################

	# Define the required sizes
	required_sizes = [
		'labels',
		'legend',
		'title',
		'line', 'axes',
		'tick_labels',
		'major_ticks', 'minor_ticks']

	# Define default sizes
	default_sizes = {
			'labels': 30*options['columns'],
			'legend': 30*options['columns'],
			'title': 30*options['columns'],
			'line': 3*options['columns'],
			'axes': 3*options['columns'],
			'tick_labels': 30*options['columns'],
			'major_ticks': 20*options['columns'],
			'minor_ticks': 10*options['columns']
	}

	# Initialise dictionary if it doesn't exist
	if not options['sizes']:
		options['sizes'] = {}

	# Update dictionary with default values where none is supplied
	for size in required_sizes:
		if size not in options['sizes']:
			options['sizes'][size] = default_sizes[size]

	##################################################################
	########################## AXIS LABELS ###########################
	##################################################################

	if not options['xlabel']:
		options['xlabel'] = prettify_labels(options['x_vals']) + ' [{}]'.format(options['units'][options['x_vals']])

	else:
		options['xlabel'] = options['xlabel'] + ' [{}]'.format(options['units'][options['x_vals']])

	if not options['ylabel']:
		options['ylabel'] = prettify_labels(options['y_vals']) + ' [{}]'.format(options['units'][options['y_vals']])

	else:
		options['ylabel'] = options['ylabel'] + ' [{}]'.format(options['units'][options['y_vals']])

	ax.set_xlabel(options['xlabel'], size=options['sizes']['labels'])
	ax.set_ylabel(options['ylabel'], size=options['sizes']['labels'])

	##################################################################
	###################### TICK MARKS & LABELS #######################
	##################################################################

	ax.tick_params(direction='in', which='major', bottom=options['show_major_ticks'][0], left=options['show_major_ticks'][1], top=options['show_major_ticks'][2], right=options['show_major_ticks'][0], length=options['sizes']['major_ticks'], width=options['sizes']['axes'])
	ax.tick_params(direction='in', which='minor', bottom=options['show_minor_ticks'][0], left=options['show_minor_ticks'][1], top=options['show_minor_ticks'][2], right=options['show_minor_ticks'][0], length=options['sizes']['minor_ticks'], width=options['sizes']['axes'])

	# DEFINE AND SET TICK DISTANCES

	from . import unit_tables

	# Define default ticks and scale to desired units
	default_ticks = {
		'specific_capacity': [100 * (unit_tables.capacity()['mAh'].loc[options['units']['capacity']] / unit_tables.mass()['g'].loc[options['units']['mass']]), 50 * (unit_tables.capacity()['mAh'].loc[options['units']['capacity']] / unit_tables.mass()['g'].loc[options['units']['mass']])],
		'capacity': [0.1 * (unit_tables.capacity()['mAh'].loc[options['units']['capacity']]), 0.05 * (unit_tables.capacity()['mAh'].loc[options['units']['capacity']])],
		'voltage': [0.5 * (unit_tables.voltage()['V'].loc[options['units']['voltage']]), 0.25 * (unit_tables.voltage()['V'].loc[options['units']['voltage']])],
		'time': [10 * (unit_tables.time()['h'].loc[options['units']['time']]), 5 * (unit_tables.time()['h'].loc[options['units']['time']])]
		}

	if options['positions']['yaxis'] == 'right':
		ax.yaxis.set_label_position("right")
		ax.yaxis.tick_right()

	# Set default tick distances for x-axis if not specified
	if not options['xticks']:

		major_xtick = default_ticks[options['x_vals']][0]
		minor_xtick = default_ticks[options['x_vals']][1]

	# Otherwise apply user input
	else:
		major_xtick = options['xticks'][0]
		minor_xtick = options['xticks'][1]

	# Set default tick distances for x-axis if not specified
	if not options['yticks']:

		major_ytick = default_ticks[options['y_vals']][0]
		minor_ytick = default_ticks[options['y_vals']][1]

	# Otherwise apply user input
	else:
		major_ytick = options['yticks'][0]
		minor_ytick = options['yticks'][1]

	# Apply values
	ax.xaxis.set_major_locator(MultipleLocator(major_xtick))
	ax.xaxis.set_minor_locator(MultipleLocator(minor_xtick))

	ax.yaxis.set_major_locator(MultipleLocator(major_ytick))
	ax.yaxis.set_minor_locator(MultipleLocator(minor_ytick))

	# SET FONTSIZE OF TICK LABELS

	plt.xticks(fontsize=options['sizes']['tick_labels'])
	plt.yticks(fontsize=options['sizes']['tick_labels'])

	##################################################################
	########################## AXES LIMITS ###########################
	##################################################################

	if options['xlim']:
		plt.xlim(options['xlim'])

	if options['ylim']:
		plt.ylim(options['ylim'])

	##################################################################
	############################# TITLE ##############################
	##################################################################

	if options['title']:
		ax.set_title(options['title'], size=options['sizes']['title'])

	##################################################################
	############################# LEGEND #############################
	##################################################################

	if ax.get_legend():
		ax.get_legend().remove()

	return fig, ax

def prettify_labels(label):

	labels_dict = {
		'capacity': 'Capacity',
		'specific_capacity': 'Specific capacity',
		'voltage': 'Voltage',
		'current': 'Current',
		'energy': 'Energy',
		'time': 'Time'
	}

	return labels_dict[label]

def generate_colours(options):

	default_options = {
		'gradient_colours': None,
	}

	aux.update_options(options=options, default_options=default_options)

	# Assign colours from the options dictionary if it is defined, otherwise use standard colours.
	if options['colours']:
		charge_colour = options['colours'][0]
		discharge_colour = options['colours'][1]

		if isinstance(charge_colour, tuple):
			charge_colour = list(charge_colour)
		if isinstance(discharge_colour, tuple):
			discharge_colour = list(discharge_colour)

	else:
		charge_colour = [(40/255, 70/255, 75/255)] # Dark Slate Gray #28464B, coolors.co
		discharge_colour = [(239/255, 160/255, 11/255)] # Marigold #EFA00B, coolors.co

		if not options['differentiate_charge_discharge']:
			discharge_colour = charge_colour

	# If gradient is enabled, find start and end points for each colour
	if options['gradient']:

		if not options['gradient_colours']:

			options['gradient_colours'] = [[None, None], [None, None]]

			add_charge = min([(1-x)*0.75 for x in charge_colour])
			add_discharge = min([(1-x)*0.75 for x in discharge_colour])

			options['gradient_colours'][0][0] = charge_colour
			options['gradient_colours'][0][1] = [x+add_charge for x in charge_colour]

			options['gradient_colours'][1][0] = discharge_colour
			options['gradient_colours'][1][1] = [x+add_discharge for x in discharge_colour]

	# Generate lists of colours
	colours = []

	if len(charge_colour) != len(options['which_cycles']):
		if options['gradient']:
			options['number_of_colours'] = len(options['which_cycles'])

			charge_colours = btp.mix_colours(colour1=options['gradient_colours'][0][0], colour2=options['gradient_colours'][0][1], options=options)
			discharge_colours = btp.mix_colours(colour1=options['gradient_colours'][1][0], colour2=options['gradient_colours'][1][1], options=options)

			for chg, dchg in zip(charge_colours, discharge_colours):
				colours.append([chg, dchg])

		else:
			for i in options['which_cycles']:
				colours.append([charge_colour, discharge_colour])

	else:
		for chg, dchg in zip(charge_colour, discharge_colour):
			colours.append([chg, dchg])

	return colours

def generate_markers(options):

	if not options['markers']:
		markers = ['o', 'v']

	else:
		markers = [options['markers'][0], options['markers'][1]]

	return markers

def get_tickmarks(df: pd.DataFrame, ticks: list, value: str, exclude=None):

	min_val = df[value].min()
	max_val = df[value].max()

	# Get major ticks
	major_ticks = [np.round((min_val + ticks[0]*i),2) for i in range(int(np.floor((max_val-min_val)/ticks[0]))+1)]
	major_ticks.append(np.round(max_val, 2))

	major_ticks = aux.get_unique(major_ticks)

	major_ticklabels = [i*ticks[0] for i in range(len(major_ticks)-1)]
	major_ticklabels.append(np.round((max_val-min_val),1))

	if exclude:
		for i, tick in enumerate(major_ticklabels):
			if tick in exclude:
				del major_ticks[i]
				del major_ticklabels[i]

	# Get minor ticks
	minor_ticks = [np.round((min_val + ticks[1]*i),2) for i in range(int(np.floor((max_val-min_val)/ticks[1]))+1) if np.round((min_val + ticks[1]*i),2) not in major_ticks]
	minor_ticklabels = [np.round(tick - min_val, 2) for tick in minor_ticks]

	return major_ticks, major_ticklabels, minor_ticks, minor_ticklabels

def assign_tickmarks(dfs: list, options, fig, ax, exclude=None):

	major_ticks, major_ticklabels, minor_ticks = [], [], []

	if not exclude:
		exclude = [[None, None] for i in range(len(options['which_cycles']))]

	for i, cycle in enumerate(options['which_cycles']):
		#Get ticks from charge cycle
		major_tick, major_ticklabel, minor_tick, minor_ticklabel = ec.plot.get_tickmarks(dfs[cycle][0], ticks=options['x_tick_locators'], value=options['x_vals'], exclude=exclude[i][0])
		major_ticks += major_tick
		major_ticklabels += major_ticklabel
		minor_ticks += minor_tick

		# Get ticks from discharge cycle
		major_tick, major_ticklabel, minor_tick, minor_ticklabel = ec.plot.get_tickmarks(dfs[cycle][1], ticks=[1, 0.25], value='ions', exclude=exclude[i][1])
		major_ticks += major_tick
		major_ticklabels += major_ticklabel
		minor_ticks += minor_tick

	ax.set_xticks(major_ticks, minor=False)
	ax.set_xticklabels(major_ticklabels)
	ax.set_xticks(minor_ticks, minor=True)

	return fig, ax


def solution(survey, choices):
    answer = ''

    dict = {'RT':0,'CF':0,'JM':0,'AN':0}

    for i, s in enumerate(survey):
        score = choices[i] - 4
        if s in dict :
            dict[s] += score
        else :
            s = s[::-1]
            dict[s] -= score

    for k, v in dict.items():
        if v <= 0:
            result = k[0]
        else:
            result = k[1]
        answer += result
    return answer


#SISTEMA DE CADASTRO PABLO 2022 pratico para manutenção
#base deferencias:https://www.youtube.com/watch?v=RtrZcoVD1WM&list=PLqx8fDb-FZDFznZcXb_u_NyiQ7Nai674-

#Biblioteca para construção da janela do app
from tkinter import*
from tkinter import ttk
import sqlite3
root = Tk()

#Gerador de pdf
# from reportlab import *
# from reportlab.pdfgen import canvas
# from reportlab.lib.pagesizes import letter, A4
# from reportlab.pdfbase import pdfmetrics
# from reportlab.pdfbase.ttfonts import TTFont
# from reportlab.platypus import SimpleDocTemplate, Image
# import webbrowser as wb

#classe para criar o formulario GUI
class app():
#class app(funcs,Relatorios):
    #função para chamar as ações da construção da tela
    def __init__(self):
        self.root = root
        self.tela()
        self.frames_da_tela1()
        self.widget()
        #self.frames_da_tela2()
        #self.monta_tabelas()
        #self.select_lista()
        #self.menus()

        root.mainloop()

#função de criação da tela conforme projeto
    def tela (self):
#titulo da janela
        self.root.title("SISTEMA PARA CADASTRAR O.S")

#cor da janela
        self.root.configure(background ='black')
# Geometria da janela
        self.root.geometry("750x600")
# redimensionável sim ou não
#         self.root.resizable(False, False)
        self.root.resizable(True, True)
# Maxima dimensão
        self.root.maxsize(width = 1000, height = 1000)
# minima dimensão
        self.root.minsize(width = 600, height = 600)
# transparencia de 0 a 1
        self.root.attributes('-alpha',1)
# prioridade no empilhamento de janelas.
        self.root.attributes('-topmost', 1)
# iconis https://iconscout.com/icons/service?price=free
        self.root.iconbitmap("settings.ico")

    #Construção do primeiro quadro vai conter os botões e as caixas de texto
    def frames_da_tela1(self):
        # telas sobrepostas frame sup
        self.frame_1 = Frame(self.root, bd = 5,
                             bg = 'Royalblue1',highlightbackground= 'goldenrod',highlightthickness=5)
        self.frame_1.place(relx= 0.01 , rely= 0.01, relwidth= 0.98, relheight=0.45)
        # telas sobrepostas frame inf
        self.frame_2 = Frame(self.root, bd=5,
                             bg='Royalblue1', highlightbackground='goldenrod', highlightthickness=5)
        self.frame_2.place(relx=0.01, rely=0.47, relwidth=0.98, relheight=0.45)

    def widget(self):
# botão de limpar
        self.bt_limpar = Button(self.frame_1, text='LIMPAR',bd = 3, bg = 'royal blue', fg ='White'
                               , font = ('verdana',7,'bold'))#, command = self.limpar_tela)
        self.bt_limpar.place(relx= 0.01, rely=0, relwidth=0.11, relheight=0.15)
# botão de buscar
        self.bt_buscar = Button(self.frame_1, text='BUSCAR',bd = 3, bg = 'royal blue', fg ='White'
                               , font = ('verdana',7,'bold'))#, command = self.busca_cliente)
        self.bt_buscar.place(relx= 0.2, rely=0.0, relwidth=0.11, relheight=0.15)
# botão de novo
        self.bt_novo = Button(self.frame_1, text='CADASTRAR',bd = 3, bg = 'royal blue', fg ='White'
                               , font = ('verdana',7,'bold'))#, command = self.add_cliente)
        self.bt_novo.place(relx= 0.4, rely=0.0, relwidth=0.11, relheight=0.15)
# botão de alterar
        self.bt_alterar = Button(self.frame_1, text='ALTERAR',bd = 3, bg = 'royal blue', fg ='White'
                               , font = ('verdana',7,'bold'))#, command = self.altera_cliente)
        self.bt_alterar.place(relx= 0.6, rely=0.0, relwidth=0.12, relheight=0.15)
# botão de apagar
        # self.bt_apagar = Button(self.frame_1, text='APAGAR',bd = 3, bg = 'royal blue', fg ='White'
        #                        , font = ('verdana',7,'bold'))#, command=self.deleta_cliente )
        # self.bt_apagar.place(relx= 0.85, rely=0.0, relwidth=0.12, relheight=0.15)
# criação label e entrada do codigo
        self.lb_codigo = Label(self.frame_1, text = "NUM O.S",bd = 3, bg = 'royal blue', fg ='White'
                               , font = ('verdana',7,'bold'))
        self.lb_codigo.place(relx= 0.0, rely= 0.2)
        self.codigo_entry = Entry(self.frame_1)
        self.codigo_entry.place(relx= 0.0, rely= 0.3)
# criação label e entrada do nome
        self.lb_nome = Label(self.frame_1, text = "SOLICITANTE",bd = 3, bg = 'royal blue', fg ='White'
                               , font = ('verdana',7,'bold'))
        self.lb_nome.place(relx= 0.3, rely= 0.2)
        self.nome_entry = Entry(self.frame_1)
        self.nome_entry.place(relx= 0.30, rely= 0.3)
# criação label e entrada do telefone
        self.lb_maq = Label(self.frame_1, text = "MÁQUINA",bd = 3, bg = 'royal blue', fg ='White'
                               , font = ('verdana',7,'bold'))
        self.lb_maq.place(relx= 0.6, rely= 0.2)
        self.maq_entry = Entry(self.frame_1)
        self.maq_entry.place(relx= 0.6, rely= 0.3)
# criação label e entrada do CIDADE
        self.lb_desc = Label(self.frame_1, text = "DESCRIÇÃO DO DEFEITO",bd = 3, bg = 'royal blue', fg ='White'
                               , font = ('verdana',7,'bold'))
        self.lb_desc.place(relx= 0.0, rely= 0.45)
        self.desc_entry = Entry(self.frame_1)
        self.desc_entry.place(relx= 0.0, rely= 0.55, relwidth=1, relheight=0.35)
app()


import os
import sys
import winsound

from PyQt5.QtWidgets import QApplication, QWidget, QPushButton, QHBoxLayout, QGroupBox, QDialog, QVBoxLayout
from PyQt5.QtGui import QIcon
from playsound import playsound
# from Tkinter import Tk
from tkinter.filedialog import askopenfilename, Tk
import PyQt5
import simpleaudio
import wave
from gettext import install
import IPython.display
import librosa.display
import matplotlib
import numpy
import numpy as np
import pylab
from matplotlib.cm import get_cmap
from matplotlib.pyplot import show, plot, title, figure, xlabel, ylabel, specgram, colorbar, stem
from matplotlib.pyplot import subplot, tight_layout
from scipy.fftpack import fft
from scipy.io.wavfile import read as read_wav
from scipy.io.wavfile import write

install(numpy)
install(matplotlib)
install(librosa)

class VoiceConventer(QDialog):

    def __init__(self):
        super().__init__()

        #initializtion the window properties
        self.title = 'Voice conventer'
        self.left = 700
        self.top = 400
        self.width = 320
        self.height = 200
        self.move(50,100)
        #path to voice sound set to default
        self.pathToFile = "man_voice.wav"

        self.initUI()

    def initUI(self):
        self.setWindowTitle(self.title)
        self.setGeometry(self.left, self.top, self.width, self.height)

        self.createHorizontalLayout()

        windowLayout = QVBoxLayout()
        windowLayout.addWidget(self.horizontalGroupBox)
        self.setLayout(windowLayout)

        self.show()

    def createHorizontalLayout(self):

        self.horizontalGroupBox = QGroupBox("Converting")
        layout = QHBoxLayout()
        buttonAdd = QPushButton('Select sound', self)
        buttonAdd.clicked.connect(self.openSound)
        layout.addWidget(buttonAdd)

        buttonPlay = QPushButton('Play sound', self)
        buttonPlay.clicked.connect(self.playSound)
        layout.addWidget(buttonPlay)

        buttonChild = QPushButton('Convert to Child Voice', self)
        buttonChild.clicked.connect(self.convertChild)
        layout.addWidget(buttonChild)

        buttonMan = QPushButton('Convert to Man Voice', self)
        buttonMan.clicked.connect(self.convertMan)
        layout.addWidget(buttonMan)

        buttonNoise = QPushButton('Add Noise', self)
        buttonNoise.clicked.connect(self.addNoise)
        layout.addWidget(buttonNoise)

        buttonDeleteNoise = QPushButton('Delete Noise', self)
        buttonDeleteNoise.clicked.connect(self.deleteNoise)
        layout.addWidget(buttonDeleteNoise)

        self.horizontalGroupBox.setLayout(layout)

    def openSound(self):
        Tk().withdraw()  # we don't want a full GUI, so keep the root window from appearing
        filename = askopenfilename()  # show an "Open" dialog box and return the path to the selected file
        self.pathToFile = filename
    def playSound(self):
        try:
            playsound(self.pathToFile)
        except:
            print("Sound file doesnt exists, check your sound file path")

    def convertChild(self):
        y, sr = librosa.load("man_voice.wav")
        self.y_shifted = librosa.effects.pitch_shift(y, sr, n_steps=24, bins_per_octave=24, res_type='fft')
        write("child.wav", sr, self.y_shifted)

        winsound.PlaySound("child.wav", winsound.SND_FILENAME)

    def convertMan(self):
        y, sr = librosa.load("child.wav")
        self.y_shifted = librosa.effects.pitch_shift(y, sr, n_steps=-24, bins_per_octave=24, res_type='fft')
        write("man_voice_reversed.wav", sr, self.y_shifted)

        winsound.PlaySound("man_voice_reversed.wav", winsound.SND_FILENAME)
    def addNoise(self):
        fnames = ["man_voice.wav", "szum.wav"]
        wavs = [wave.open(fn) for fn in fnames]
        frames = [w.readframes(w.getnframes()) for w in wavs]
        self.samples = [np.frombuffer(f, dtype='<i2') for f in frames]
        self.samples = [samp.astype(np.float64) for samp in self.samples]
        print(self.samples[1])
        self.delete = self.samples[1]
        n = min(map(len, self.samples))
        mix = self.samples[0][:n] + self.samples[1][:n]
        mix_wav = wave.open("withnoise.wav", 'w')
        mix_wav.setparams(wavs[0].getparams())
        mix_wav.writeframes(mix.astype('<i2').tobytes())
        mix_wav.close()
        winsound.PlaySound("withnoise.wav", winsound.SND_FILENAME)
    def deleteNoise(self):
        fnames = ["withnoise.wav", "szum.wav"]
        wavs = [wave.open(fn) for fn in fnames]
        frames = [w.readframes(w.getnframes()) for w in wavs]
        self.samples = [np.frombuffer(f, dtype='<i2') for f in frames]
        self.samples = [samp.astype(np.float64) for samp in self.samples]
        print(self.samples[1])
        self.delete = self.samples[1]
        n = min(map(len, self.samples))
        mix = self.samples[0][:n] - self.samples[1][:n]
        mix_wav = wave.open("withoutnoise.wav", 'w')
        mix_wav.setparams(wavs[0].getparams())
        mix_wav.writeframes(mix.astype('<i2').tobytes())
        mix_wav.close()
        winsound.PlaySound("withoutnoise.wav", winsound.SND_FILENAME)

if __name__ == '__main__':
    app = QApplication(sys.argv)
    ex = VoiceConventer()
    sys.exit(app.exec_())

#pole bitewne dodawanie szumu
 # y, sr = librosa.load("man_voice.wav")
 #        #losowanie
 #        sampl = np.random.uniform(low=0.0, high=0.10, size=(len(y)))
 #        a = np.float32(sampl)
 #        data = np.float32(y)
 #
 #        j = min(len(a), len(data))
 #        z = [a[i] + data[i] for i in range(j)]
 #        write("example.wav", sr, z)
 #        playsound('example.wav')


"""
You have read about function, higher order function, closures etc.
Now, it is time to learn about their scope.
Based on the scope, functions/methods are of two types.

They are:
1. Class methods
2. Static methods

An Abstract Base Class or ABC mandates the derived classes to implement specific methods from the base class.
It is not possible to create an object from a defined ABC class.
Creating objects of derived classes is possible only
when derived classes override existing functionality of all abstract methods defined in an ABC class.

"""

class Circle(object):
    no_of_circles = 0

    def __init__(self, radius):
        self.__radius = radius
        Circle.no_of_circles += 1

    @classmethod
    def getCirclesCount(cls):
        return cls.no_of_circles

    @staticmethod
    def square(x):
        return x ** 2

    def area(self):
        return 3.14 * self.square(self.__radius)

c1 = Circle(3.9)
print(c1.area())  # 47.7594

# Calling Static method
print(Circle.square(10))  # 100
print(c1.square(10))  # 100

c2 = Circle(5.2)
c3 = Circle(4.8)

print(c1.getCirclesCount())  # 3
print(c2.getCirclesCount())  # 3
print(c3.getCirclesCount())  # 3

# calling Class method
print(Circle.getCirclesCount())  # 3

# class A:
#
#     @staticmethod
#     def m1(self):
#         print('Static Method')
#
#     @classmethod
#     def m1(self):
#         print('Class Method')
#
#
# A.m1()  # Class Method

# from abc import ABC, abstractmethod
#
#
# class Shape(ABC):
#     @abstractmethod
#     def area(self):
#         pass
#
#     @abstractmethod
#     def perimeter(self):
#         pass
#
#
# # s1 = Shape() # Error
#
# class Circle(Shape):
#     def __init__(self, radius):
#         self.__radius = radius
#
#     @staticmethod
#     def square(x):
#         return x ** 2
#
#     def area(self):
#         return 3.14 * self.square(self.__radius)
#
#     def perimeter(self):
#         return 2 * 3.14 * self.__radius
#
#
# c1 = Circle(3.9)
# print(c1.area())
# print(c1.perimeter())
#
from abc import ABC, abstractmethod
#
#
# class A(ABC):
#
#     @abstractmethod
#     @classmethod
#     def m1(self):
#         print('In class A, Method m1.')
#
#
# class B(A):
#
#     @classmethod
#     def m1(self):
#         print('In class B, Method m1.')
#
#
# b = B()
# b.m1()
# B.m1()
# A.m1()

# from abc import ABC, abstractmethod
#
# class A(ABC):
#
#     @abstractmethod
#     def m1(self):
#         print('In class A, Method m1.')
#
#
# class B(A):
#
#     def m1(self):
#         print('In class B, Method m1.')
#
#
# class C(B):
#
#     def m2(self):
#         print('In class C, Method m2.')
#
#
# c = C()
# c.m1()
# c.m2()
from abc import ABC, abstractmethod

class A(ABC):

    @classmethod
    @abstractmethod
    def m1(self):
        print('In class A, Method m1.')

class B(A):

    @classmethod
    def m1(self):
        print('In class B, Method m1.')

b = B()
b.m1()
B.m1()
A.m1()

def s1(x, y):
    return x * y

class A:

    @staticmethod
    def s1(x, y):
        return x + y

    def s2(self, x, y):
        return s1(x, y)

a = A()
print(a.s2(3, 7))

from abc import ABC, abstractmethod

class A(ABC):

    @abstractmethod
    def m1(self):
        print('In class A, Method m1.')

class B(A):

    @staticmethod
    def m1(self):
        print('In class B, Method m1.')

b = B()
B.m1(b)

import inspect

from abc import ABC, abstractmethod

# Define the abstract class 'Animal' below
# with abstract method 'say'
class Animal(ABC):
    @abstractmethod
    def say(self):
        pass

# # Define class Dog derived from Animal
# # Also define 'say' method inside 'Dog' class
# class Dog(Animal):
#     def say(self):
#         return "I speak Booooo"
#
#
# if __name__ == '__main__':
#
#     if issubclass(Animal, ABC):
#         print("'Animal' is an abstract class")
#
#     if '@abstractmethod' in inspect.getsource(Animal.say):
#         print("'say' is an abstract method")
#
#     if issubclass(Dog, Animal):
#         print("'Dog' is dervied from 'Animal' class")
#
#     d1 = Dog()
#     print("Dog,'d1', says :", d1.say())


#!/usr/bin/env python

import sys
import socket
from cache_protocol import *

if len(sys.argv) != 3:
    print("Usage: %s HOST KEY" % sys.argv[0])
    sys.exit(1)

host = sys.argv[1]
key = int(sys.argv[2])

addr = (host, UDP_PORT)

s = socket.socket(socket.AF_INET, socket.SOCK_DGRAM)
s.settimeout(2)

req = reqHdr.pack(key)
s.sendto(req, addr)

res, addr2 = s.recvfrom(1024)

key2, valid, value = resHdr.unpack(res)

assert key2 == key

if valid:
    print(value)
else:
    print("NOTFOUND")


"""
Filename: text_extraction.py
Purpose:       This file implements the text extraction process of the pipeline.
Functionality: This file provides functions for text extraction, including
               tasks like reading input files, preprocessing text, applying
               extraction techniques, and generating extracted text output.
Usage:         Import and invoke the relevant functions from this file in the desired
               module or script within the pipeline.
Dependencies: Install the required package dependencies by running
              "pip3 install -r requirements.txt" to ensure proper functionality.
              The requirements.txt file contains the necessary dependencies.
"""

import os
import pandas as pd
import numpy as np
import os
import regex as re
import time
from collections import Counter
#TODO: extraction part to this
#OUTPUT: List of extracted_text

"""
First Attempt

  0       26 | 26 | 26

-1     2430 | 2430 | same
 1      869 |  902 | same
-2      169 | 143  | same
-3       16 | 169  | same
-20     176 | 16   | same

Second attempt:
(1214, 16) for total of (1214, 3) files , 622 year-ids, and 307 unique IDs done for Securities Done
-1     2430
 1      902
-3      169
-2      143
 0       26
-20      16

"""

def securities_extractor(subsection,Additional_class_flag = False):
    # First, we only extract the information we can get from the stated values
    # has issues with additional sometimes being captialized,
    # maybe use regex to fix it or change all to lower case (Done)
    #IDEA for standar
    dates_tracker = {}

    count = 0
    Trading = re.search(r"(?<=[Tt]+rading symbol.*:).*(?=\n)", subsection)
    if Trading:
        Trading = Trading.group()

    else:
        count += 1
        Trading = np.nan

    Title = re.search(r"(?<=[Ee]+xact title and class of securities outstanding.*:).*(?=\n)", subsection)
    if Title:
        Title = re.sub(r'\W+', '', Title.group())
    else:
        count += 1
        Title = np.nan

    cusp = re.search(r"(?<=(CUSIP|cusip).*:).*(?=\n)", subsection)
    if cusp:
        cusp = re.sub(r'\W+', '', cusp.group())
    else:
        count += 1
        cusp = np.nan
    par_value = re.search(r"(?<=[Pr]+ar *or *stated *value.*:).*(?=\n)", subsection)
    if par_value:
        par_value = par_value.group()
    else:
        count += 1
        par_value = np.nan

    #(?=(as *of *date)|('\n'))
    authorized_shares = re.search(r"(?<=[Tt]+otal *shares *authorized.*:).*(?='\n')", subsection.lower())
    print(authorized_shares)
    if authorized_shares:
        authorized_shares = authorized_shares.group()
        cut_off = re.search("as *of *",authorized_shares)
        if cut_off:
            authorized_shares = authorized_shares[:cut_off.start()]
        dates_tracker[0] = True
    else:
        count += 1
        dates_tracker[0] = False
        authorized_shares = np.nan

    outstanding_shares = re.search(r"(?<=[Tt]+otal *shares *outstanding *:).*(?=\n)", subsection)
    if outstanding_shares:
        outstanding_shares = outstanding_shares.group()
        cut_off = re.search("as *of *", outstanding_shares)
        if cut_off:
            outstanding_shares = outstanding_shares[:cut_off.start()]
        dates_tracker[1] = True
    else:
        count += 1
        dates_tracker[1] = False
        outstanding_shares = np.nan

    shares_in_public = re.search(r"(?<=[Nn]+umber of shares in the Public Float.*:).*(?=\n)", subsection)
    if shares_in_public:
        shares_in_public = shares_in_public.group()
        cut_off = re.search("as *of *", shares_in_public)
        if cut_off:
            shares_in_public = shares_in_public[:cut_off.start()]
        dates_tracker[2] = True
    else:
        count += 1
        dates_tracker[2] = False
        shares_in_public = np.nan

    shareholders_record = re.search(r"(?<=[Tt]+otal *number *of *shareholders *of *record.*:).*(?=\n)",
                                    subsection)
    if shareholders_record:
        shareholders_record = shareholders_record.group()
        cut_off = re.search("as *of *", shareholders_record)
        if cut_off:
            shareholders_record = shareholders_record[:cut_off.start()]
        dates_tracker[3] = True

    else:
        count += 1
        dates_tracker[3] = False
        shareholders_record = np.nan

    #if more than half are nans, then return error
    try:
        assert count < 4
    except:
        return -20

    dates = re.findall("(?<=[Aa]s *of *date *:).*(?=\n)", subsection)
    dates_orig = dates.copy()

    if len(list(set(dates_tracker.values()))) == 1 and dates[0] == False:
        results = re.findall('(?<=\n)[0-9a-zA-z]*(?=as *of *)',subsection)
        authorized_shares   = results[0]
        outstanding_shares  = results[1]
        shares_in_public    = results[2]
        shareholders_record = results[3]

    #if more than half are nans, then return error
    try:
        assert count < 4
    except:
        return -20
    #if we have less than four values and it is not additional class
    if len(dates) != len(dates_tracker.keys()) and Additional_class_flag == False:

        for index,exists in enumerate(dates_tracker.keys()):
            #if the relevent information for the date does not exist, add "None" until information is filled
            if dates_tracker[exists] == False and len(dates) < len(dates_tracker.keys()):
                dates.append(np.nan)
        print(subsection)
        print(dates,dates_tracker)
        #Some of the really unstructured ones do not mention
        #Additional information correctly.
    try:
        returned_values = [Additional_class_flag, Trading, Title, cusp, par_value,
     authorized_shares, dates[0], outstanding_shares, dates[1],
     shares_in_public, dates[2], shareholders_record,
     dates[3]]
        if len(dates_orig) != len(dates_tracker.keys()) or np.nan in dates:
            #return error code -2 for metadata to inform that we have some
            #good information
            #this one has a higher degree of accuracy in my opinion
            return [returned_values,-2]
    except:
        #I am not sure why these ones are not being read correctly,
        #Definetely worth investigating
        while True:
            try:
                returned_values = returned_values = [Additional_class_flag, Trading, Title, cusp, par_value,
     authorized_shares, dates[0], outstanding_shares, dates[1],
     shares_in_public, dates[2], shareholders_record,
     dates[3]]
                return [returned_values,-3]
            except:
                dates.append(np.nan)

    return [returned_values,1]

def get_securities(text, row):
    text = text.strip()
    # Create the basic dataframes to return
    Securities = pd.DataFrame(
        columns=['Other Flag', 'Trading symbol', 'Exact title and class of securities outstanding', 'CUSIP',
                 'Par/stated value', 'Total shares authorized', 'Authorized Date', 'Total shares oustanding',
                 'Outstanding Date', 'Number of shares in the Public Float', ' Public float Date',
                 'Total number of shareholders of Record', 'Shareholders Date'] + list(row.columns))
    Transfer_agent = pd.DataFrame(columns=['Agent Name', 'Phone', 'Email', 'Address'] + list(row.columns))

    # if we have the section
    if '2) Security Information' in text and '3) Issuance History' in text:
        section = text[text.index('2) Security Information'):text.index('3) Issuance History')]
    else:
        # if we cannot find the information p
        print(
            f"Get Securities:-1 because 2) Security Information {'2) Security Information' in text} 3) Issuance History {'3) Issuance History' in text}")
        return -1

    Transfer_agent = re.search('(?<=[Tt]+ransfer).*(?=\n)',section)
    if Transfer_agent:
        Transfer_agent = Transfer_agent.start()

    end_index = re.search('(?<=[Aa]+dditional class).*(?=\n)',section)
    if end_index:
        start_index = 0
        #If transfer agent is at the top of the securities section, remove it
        if Transfer_agent < end_index.start():
            start_index = Transfer_agent
        subsection = section[start_index:end_index.start()]
    else:
        subsection = section

    results = securities_extractor(subsection,False)
    error_code = None

    if isinstance(results, int):
        return results
    if isinstance(results,list):
        error_code = results[1]
        results = results[0]

    # add the relevent informatio here
    Securities.loc[Securities.shape[0]] = results + list(row.reset_index().loc[0])[1:]
    if error_code:
        return [Securities,error_code]
    else:
        return Securities

def clean_output(text_arr):
    print("Before",text_arr)
    for i,val in enumerate(text_arr):
        text_arr[i] = re.sub("|_","",val)

    text_arr_orig = []

    for i,val in enumerate(text_arr):
        if val != "":
            text_arr_orig.append(val)
    print("After",text_arr_orig)
    return text_arr_orig
def fill_max(arr,max_val):

    i = 0
    while len(arr) < max_val:
        if len(arr) != max_val:
            arr.append(np.nan)
    return arr

def get_additional_securities(text,row):

    text = text.strip()
    # Create the basic dataframes to return
    Securities = pd.DataFrame(
        columns=['Other Flag', 'Trading symbol', 'Exact title and class of securities outstanding', 'CUSIP',
                 'Par/stated value', 'Total shares authorized', 'Authorized Date', 'Total shares oustanding',
                 'Outstanding Date', 'Number of shares in the Public Float', ' Public float Date',
                 'Total number of shareholders of Record', 'Shareholders Date'] + list(row.columns))

    second_section = re.search("2 *\) *[Ss]+ecurity", text)
    third_section  = re.search("3 *\) *[Ii]+ssuance",text)

    start_index_section = re.search('(?<=[Aa]+dditional class).*(?=\n)', text)
    end_index_section = re.search('(?<=[Tt]+ransfer *[Aa]gent).*(?=\n)', text)
    if not end_index_section:
        end_index_section = third_section

    # if we have the section
    if start_index_section and end_index_section and second_section and third_section:
        section = text[start_index_section.start():end_index_section.end()]
    else:
        # if we cannot find the information p
        print(
            f"Get Additional Securities:-1 because Additional one: {start_index_section} -- {end_index_section} and {second_section} and {third_section}")
        return -1
    #if the section length is very small and there is no "None"
    if len(section) < 40 and 'none' in section.lower():
        #None seem to go in here
        return -2
    Trading = re.findall(r"(?<=[Tt]+rading *[Ss]+ymbol *:).*(?=\n)", section)
    Trading = clean_output(Trading)
    Title = re.findall(r"(?<=[Ee]+xact *title *and *class *of *securities outstanding *:).*(?=\n)", section)
    Title = clean_output(Title)
    cusp = re.findall(r"(?<=CUSIP *:).*(?=\n)", section)
    cusp = clean_output(cusp)
    par_value = re.findall(r"(?<=[Pp]+ar *or *stated value *:).*(?=\n)", section)
    par_value = clean_output(par_value)

    #if all are empty
    if len(Trading) == 0 and len(Title) == 0 and len(cusp) == 0 and len(par_value) == 0:
        # this shows there was no possible result
        return -3

    maximum_entries = max([len(Trading),len(Title),len(cusp), len(par_value)])
    Trading = fill_max(Trading,maximum_entries)
    Title   = fill_max(Title,maximum_entries)
    cusp    = fill_max(cusp,maximum_entries)
    par_value = fill_max(par_value,maximum_entries)

    authorized_shares  = re.findall(r"(?<=[Tt]+otal *shares *authorized *:).*(?=\n)", section)
    authorized_shares  = clean_output(authorized_shares)
    authorized_shares  = fill_max(authorized_shares,maximum_entries)
    print(authorized_shares)
    authorized_shares  = [(re.sub('[Aa]+s *of.*','',share)if share is not np.nan else share) for share in authorized_shares]

    outstanding_shares = re.findall(r"(?<=[Tt]+otal *shares *outstanding *:).*(?=\n)", section)
    #outstanding_shares = [re.sub(" ")]
    outstanding_shares = clean_output(outstanding_shares)
    outstanding_shares = fill_max(outstanding_shares,maximum_entries)
    outstanding_shares  = [(re.sub('[Aa]+s *of.*','',share)if share is not np.nan else share) for share in outstanding_shares]

    dates = re.findall(r"(?<=as *of *date *:).*(?=\n)", section)
    dates              = clean_output(dates)
    dates              =fill_max(dates,maximum_entries*2)
    #if len(authorized_shares)  != len(dates):
     #   return -4
    #return 4
    error_flag = False
    for i in range(len(Trading)):

        results =   [True, Trading[i], Title[i], cusp[i], par_value[i],
                                                   authorized_shares[i], dates[2 * i], outstanding_shares[i],
                                                   dates[i * 2 + 1], "None", "None", "None", "None"]
        Securities.loc[Securities.shape[0]] = results + list(row.reset_index().loc[0])[1:]
        #except:
           # error_flag = True
    #this error code tell us there was some issue with the final output of the code
    if error_flag: return [Securities,-5]

    return Securities


from PIL import Image, ImageDraw, ImageFont
from os.path import dirname, join

# Constants
POS_DIREC = "in.png"
FILE_TYPE = ".png"
_FONT_RETGULAR = ".\\fonts\\" + "Alibaba-PuHuiTi-B.ttf"
_FONT_BODY = ".\\fonts\\" + "Alibaba-PuHuiTi-Regular.ttf"
safe_margin = 110

def paste_all(post_path, out_path, font_path, data_Dict):
    try:
        print(data_Dict["name"])
        # print("Loading: " + post_path)
        oriImg = Image.open(post_path)

        draw = ImageDraw.Draw(oriImg)
        # print("Loading: " + font_path)
        width, height = oriImg.size

        # # For 22
        # _name = data_Dict["name"]
        # if data_Dict["sex"] == "男":
        #     _name += "学弟"
        # elif data_Dict["sex"] == "女":
        #     _name += "学妹"

        # For 21 & 20
        _name = data_Dict["name"]
        if data_Dict["sex"] == "男":
            _name += "学长"
        elif data_Dict["sex"] == "女":
            _name += "学姐"

        _font = ImageFont.truetype(font_path,60)
        w, h = _font.getsize(_name)
        draw.text((270, 85), _name, fill = (107, 142, 65), font=_font)

        # # nick
        # if data_Dict["nick"] != ("(空)"):
        #     _font = ImageFont.truetype(join(dirname(__file__),_FONT_RETGULAR),20)
        #     w, h = _font.getsize(data_Dict["nick"])
        #     draw.text((272, 165), data_Dict["nick"], fill = (0, 0, 0), font=_font)

        # # "Mentor"
        # _font = ImageFont.truetype(font_path,50)
        # w, h = _font.getsize("Mentor")
        # draw.text(((width-w)/2 + 202, 575), "Mentor", fill = (0, 0, 0), font=_font)

        # program
        _font = ImageFont.truetype(font_path, 25)
        program = "Program: "
        if data_Dict["spec"] != "(跳过)":
            program += "Specialist " + data_Dict["spec"]
        if data_Dict["dblm"] != "(跳过)":
            program += "Double Major " + data_Dict["dblm"]
        if data_Dict["majr"] != "(跳过)":
            program += "Major " + data_Dict["majr"]
        if data_Dict["minr"] != "(跳过)":
            program += " + Minor " +data_Dict["minr"]
        w, h = _font.getsize(program)
        # auto newline
        if w + 272 > width - safe_margin:
            new_str = ""
            p = 0
            q = 0
            w = 0
            cnt = 0
            while (q < len(program)):
                while (w + 272 <= width - safe_margin and q < len(program)):
                    qq = q
                    while (program[qq:qq+1].isalpha()):
                        qq += 1
                    w, h = _font.getsize(program[p:qq])
                    if w + 272 > width - safe_margin:
                        break
                    else:
                        q = qq + 1
                    w, h = _font.getsize(program[p:q])
                new_str += program[p:q] + '\n'
                cnt += 1
                p = q
                w = 0
            if cnt > 2: # >= 3
                draw.text((272, 255), new_str.strip('\n'), fill = (0, 0, 0), font=_font)
            elif cnt > 1: # 2
                draw.text((272, 282), new_str.strip('\n'), fill = (0, 0, 0), font=_font)
            else: # 1-2
                draw.text((272, 310), new_str.strip('\n'), fill = (0, 0, 0), font=_font)
        else:
            draw.text((272, 310), program.strip('\n'), fill = (0, 0, 0), font=_font)

        # intro
        _font = ImageFont.truetype(join(dirname(__file__), _FONT_BODY), 25)
        intro = data_Dict["intro"]
        w, h = _font.getsize(intro)
        # auto newline
        if w + 272 > width - safe_margin: # > 1 line
            new_str = ""
            p = 0
            q = 0
            w = 0
            while (q < len(intro)):
                while (w + 272 <= width - safe_margin and q < len(intro)):
                    qq = q
                    while (intro[qq:qq+1].encode('utf-8').isalpha()):
                        qq += 1
                    w, h = _font.getsize(intro[p:qq])
                    if w + 272 > width - safe_margin:
                        break
                    else:
                        q = qq + 1
                    w, h = _font.getsize(intro[p:q])
                new_str += intro[p:q] + '\n'
                p = q
                w = 0
            draw.text((272, 360), new_str.strip('\n'), fill = (0, 0, 0), font=_font)
        else:
            _font = ImageFont.truetype(join(dirname(__file__), _FONT_BODY), 30)
            new_str = ""
            p = 0
            q = 0
            w = 0
            while (q < len(intro)):
                while (w + 272 <= width - safe_margin and q < len(intro)):
                    qq = q
                    while (intro[qq:qq+1].encode('utf-8').isalpha()):
                        qq += 1
                    w, h = _font.getsize(intro[p:qq])
                    if w + 272 > width - safe_margin:
                        break
                    else:
                        q = qq + 1
                    w, h = _font.getsize(intro[p:q])
                new_str += intro[p:q] + '\n'
                p = q
                w = 0
            draw.text((270, 370), new_str.strip('\n'), fill = (0, 0, 0), font=_font)

        # wechat
        _font = ImageFont.truetype(font_path,25)
        w, h = _font.getsize("WeChat ID: " + data_Dict["wechat"])
        draw.text((272, 160), "WeChat ID: " + data_Dict["wechat"], fill = (0, 0, 0), font=_font)

        # oriImg.show()
        oriImg.save(out_path)

    except IOError:
        print("Process failed\n")
        newImg = Image.new('RGBA',(320,240),'blue')
        newImg.save(out_path)

# for single use
if __name__ == '__main__':
    tmp_name = "sample"
    # makea_qr(tmp_code, tmp_name)
    # qr_path  = join(dirname(__file__), QRC_DIREC + tmp_name + FILE_TYPE)
    post_path= join(dirname(__file__), POS_DIREC)
    font_path= join(dirname(__file__),_FONT_RETGULAR)

    tmp_dict = {}
    tmp_dict['email'] = "???"
    tmp_dict['name'] = "sample_name"
    tmp_dict['nick'] = "Nickname"
    tmp_dict['intro'] = "Hi there, this is a sample introduction."
    tmp_dict['spec'] = "(跳过)"
    tmp_dict['dblm'] = "Mathematics | Statistics"
    tmp_dict['majr'] = "(跳过)"
    tmp_dict['minr'] = "(跳过)"

    tmp_dict['wechat'] = "sample_wxid"
    tmp_dict['sex'] = "N/A"

    out_path = join(dirname(__file__) + '\\' + tmp_dict['name'] + FILE_TYPE)
    paste_all(post_path, out_path, font_path, tmp_dict)


import pygame
from configuracoes import Configuracoes
from nave import Nave
from botao import Botao
import funcoes_game as fg
from tela_pontuacao import TelaPontuacao
from pygame.sprite import Group

def rodar_game():
        pygame.init() #inicializa a biblioteca paygame

        configuracoes = Configuracoes() #cria o objeto configuracoes

        tela = pygame.display.set_mode((configuracoes.largura_tela, configuracoes.altura_tela)) #configura as dimensoes da tela
        pygame.display.set_caption("Invasão Alienígena") #adiciona um titulo a tela criada

        play = Botao(configuracoes, tela, "PLAY") #criar o objeto botao para play

        nave = Nave(configuracoes, tela) #criar o objeto nave

        tiros = Group() #criar um grupo de tiros

        aliens = Group() #criar um grupo de aliens

        naves_vidas = Group() #criar um grupo de naves para vidas

        tela_pontuacao = TelaPontuacao(configuracoes, tela) #criar tela para pontuacao

        fg.criar_frota_aliens(aliens, nave, configuracoes, tela) #criar frota inicial de aliens

        fg.criar_naves_vidas(naves_vidas, configuracoes, tela) #criar as tres naves vidas

        while True:
                fg.checar_eventos(nave, tiros, configuracoes, tela, play) #checa eventos do teclado
                fg.atualizar_tela(configuracoes, nave, naves_vidas, tela, tiros, aliens, play, tela_pontuacao) #atualiza a tela para cada ciclo
                if configuracoes.jogo_ativo: #condicao para jogo comecar
                        nave.atualizacao_nave() #atualiza a posicao da nave
                        fg.atualizacao_tiros(tiros) #atualiza a posicao dos tiros
                        tela_pontuacao.atualizacao_pontuacao()
                        fg.atualizar_frota(aliens, tiros, nave, naves_vidas, configuracoes, tela) #atualiza a tela por ciclo do laco

rodar_game() #rodar jogo


import pygame

BLACK = (0,0,0)
WHITE = (255,255,255)

pygame.init()

size=(800,600)
screen =pygame.display.set_mode(size)

pygame.display.set_caption("laser5.ogg")

backgroud_position = [0,0]

backgroud_image = pygame.image.load("saturn_family1.jpg").conveert()
player_image = pygame.image.load("playerShip1_orange.png").conveert()

player_image.set_colorkey(BLACK)

done = False

clock = pygame.time.Clock()

while not done:
    for event in pygame.event.get():
         if event.type ==pygame.QUIT:
            done =True

         elif event.type == pygame.MOUSEBUTTONDOWN:
             click_sound.play()

    screen.blit(backgroud_image,backgroud_position)
    player_position = pygame.mouse.get_pos()
    x = player_position[0]
    y = player_position[1]

    screen.blit()

    screen.fill(WHITE)
    pygame.display.flip(player_image,[x,y])

    clock.tick(60)
pygame.quit()


class Solution:
    def maxSubArray(self, nums: List[int]) -> int:
        res =-float('inf')
        tmp = -float('inf')
        for n in nums:
            tmp = max(n, tmp+n)
            res = max(res, tmp)
        return res


import os
import tempfile
import argparse
from pysubparser import parser
from pydub import AudioSegment
import pyttsx3

def time_to_ms(time):
  return ((time.hour * 60 + time.minute) * 60 + time.second) * 1000 + time.microsecond / 1000

def generate_audio(path, rate=200, voice_idx=0):
  print("Generating audio file for {} with {}".format(path, "pyttsx3"))

  subtitles = parser.parse(path)

  tts_engine = pyttsx3.init()
  tts_engine.setProperty('rate', rate)
  tts_engine.setProperty('voice', tts_engine.getProperty('voices')[voice_idx].id)

  audio_sum = AudioSegment.empty()

  with tempfile.TemporaryDirectory() as tmpdirname:
    print('created temporary directory', tmpdirname)

    temp_file_path = os.path.join(tmpdirname, "temp.wav")
    prev_subtitle = None
    prev_audio_duration_ms = 0
    for subtitle in subtitles:
      tts_engine.save_to_file(subtitle.text, temp_file_path)
      tts_engine.runAndWait()

      audio_segment = AudioSegment.from_wav(temp_file_path)

      print(subtitle.start, subtitle.text)

      if prev_subtitle is None:
        silence_duration_ms = time_to_ms(subtitle.start)
      else:
        silence_duration_ms = time_to_ms(subtitle.start) - time_to_ms(prev_subtitle.start) - prev_audio_duration_ms

      audio_sum = audio_sum + AudioSegment.silent(duration=silence_duration_ms) + audio_segment

      prev_subtitle = subtitle
      prev_audio_duration_ms = len(audio_segment)

    with open(os.path.splitext(path)[0] + '.wav', 'wb') as out_f:
      audio_sum.export(out_f, format='wav')

if __name__ == "__main__":
  arg_parser = argparse.ArgumentParser()
  arg_parser.add_argument("-p", "--path", help="subtitle file path", required=True)
  arg_parser.add_argument("-r", "--rate", help="speech rate(words per minute)", type=int, default=150)
  arg_parser.add_argument("-v", "--voice-idx", help="voice selection", type=int, default=0, choices=[0, 1])

  args = arg_parser.parse_args()

  generate_audio(path=args.path, rate=args.rate, voice_idx=args.voice_idx)


# Игра война
# От 2 до 7 игроков
# Игроки тянут по одной карты, а выигрывает тот, у кого номинал
# карты оказался наибольшим
import cards, games

class WR_Card(cards.Card):
    """Карта для игры в 'Войну'."""

    ACE_VALUE = 1

    @property
    def value(self):
        if self.is_face_up:
            v = WR_Card.RANKS.index(self.rank) + 1
        else:
            v = None
        return v

class WR_Deck(cards.Deck):
    """Колода для игры в 'Войну'."""

    def populate(self):
        for suit in WR_Card.SUITS:
            for rank in WR_Card.RANKS:
                self.cards.append(WR_Card(rank, suit))

class WR_Hand(cards.Hand):
    """Рука: набор карт у одного игрока."""

    def __init__(self, name):
        super(WR_Hand, self).__init__()
        self.name = name

    def __str__(self):
        rep = self.name + ":\t" + super(WR_Hand, self).__str__()
        if self.total:
            rep += "номинал карты - " + str(self.total)
        return rep

    @property
    def total(self):
        t = 0
        for card in self.cards:
            t += card.value
        return t

    def is_busted(self):
        return self.total

class WR_Player(WR_Hand):
    """Игрок в 'Блек-джек'."""
    def lose(self):
        print(self.name, "проиграл.")

    def win(self):
        print(self.name, "выиграл.")

class WR_Game(object):
    """Игра в Блек-джек."""

    def __init__(self, names):
        self.players = []
        for name in names:
            player = WR_Player(name)
            self.players.append(player)
        self.deck = WR_Deck()
        self.deck.populate()
        self.deck.shuffle()

    def play(self):
        # сдача всем по 1 карте
        self.deck.deal(self.players, per_hand=1)
        self.table_records = []
        for player in self.players:
            print(player)
            self.table_records.append(player.is_busted())
        self.table_records.sort(reverse=True) # сортируем обратным порядком
        for player in self.players:
            # если у игрока номинал карты равен максимальному номиналу, то он выиграл
            if player.total == self.table_records[0]:
                player.win()
            # если у игрока номинал карты меньше максимального номинала, то он проиграл
            elif player.total < self.table_records[0]:
                player.lose()
        # удаление всех карт
        for player in self.players:
            player.clear()

def main():
    print("\t\tДобро пожаловать за игровой стол гры 'Война'!\n")
    print("\t\tВыиграет тот, у кого будет карта с наибольшим номиналом!\n")
    names = []
    number = games.ask_number("Сколько всего игроков? (2 - 7): ", low=2, high=8)
    for i in range(number):
        name = input("Введите имя игрока: ")
        names.append(name)
        print()
    game = WR_Game(names)
    again = None
    while again != "n":
        game.play()
        again = games.ask_yes_no("\nХотите сыграть еще раз? ")

main()
input("\n\nНажмите Enter, чтобы выйти.")


# -*- coding: utf-8 -*-
"""
@author: Yifan Cheng, Skylar Du, Yashash Gaurav, Mark He
"""

import pandas as pd
import helpers as h
import numpy as np

us_state_to_abbrev = {
    "Alabama": "AL",
    "Alaska": "AK",
    "Arizona": "AZ",
    "Arkansas": "AR",
    "California": "CA",
    "Colorado": "CO",
    "Connecticut": "CT",
    "Delaware": "DE",
    "Florida": "FL",
    "Georgia": "GA",
    "Hawaii": "HI",
    "Idaho": "ID",
    "Illinois": "IL",
    "Indiana": "IN",
    "Iowa": "IA",
    "Kansas": "KS",
    "Kentucky": "KY",
    "Louisiana": "LA",
    "Maine": "ME",
    "Maryland": "MD",
    "Massachusetts": "MA",
    "Michigan": "MI",
    "Minnesota": "MN",
    "Mississippi": "MS",
    "Missouri": "MO",
    "Montana": "MT",
    "Nebraska": "NE",
    "Nevada": "NV",
    "New Hampshire": "NH",
    "New Jersey": "NJ",
    "New Mexico": "NM",
    "New York": "NY",
    "North Carolina": "NC",
    "North Dakota": "ND",
    "Ohio": "OH",
    "Oklahoma": "OK",
    "Oregon": "OR",
    "Pennsylvania": "PA",
    "Rhode Island": "RI",
    "South Carolina": "SC",
    "South Dakota": "SD",
    "Tennessee": "TN",
    "Texas": "TX",
    "Utah": "UT",
    "Vermont": "VT",
    "Virginia": "VA",
    "Washington": "WA",
    "West Virginia": "WV",
    "Wisconsin": "WI",
    "Wyoming": "WY",
    "District of Columbia": "DC",
    "American Samoa": "AS",
    "Guam": "GU",
    "Northern Mariana Islands": "MP",
    "Puerto Rico": "PR",
    "United States Minor Outlying Islands": "UM",
    "U.S. Virgin Islands": "VI",
}

# invert the dictionary
abbrev_to_us_state = dict(map(reversed, us_state_to_abbrev.items()))

# Get the average statistics for a given state
def get_average_stats(dataframe=h.read_final_data()):
    newR = []
    for i, row in dataframe.iterrows():
        roi = row["20 Year Net ROI"][1:].replace(",", "")
        cost = row["Total 4 Year Cost"][1:].replace(",", "")
        loan = row["Average Loan Amount"][1:].replace(",", "")
        try:
            roi = int(roi)
        except:
            roi = 0
        try:
            cost = int(cost)
        except:
            cost = 0
        try:
            graduate = int(row["Typical Years to Graduate"])
        except:
            graduate = 0
        try:
            loan = int(loan)
        except:
            loan = 0
        newR.append((roi, cost, graduate, loan))
    newR = pd.DataFrame(newR)
    print("==========================")
    print("Displaying average stats about all colleges")
    print(
        "%-30s" % "Average 20 Year Net ROI: "
        + str(np.round(newR.mean()[0], 2))
    )
    print("%-30s" % "Total 4 Year Cost: " + str(np.round(newR.mean()[1], 2)))
    print(
        "%-30s" % "Typical Years to Graduate: "
        + str(np.round(newR.mean()[2], 2))
    )
    print("%-30s" % "Average Loan Amount: " + str(np.round(newR.mean()[3], 2)))
    print()

# Funciton adapted from https://stackoverflow.com/questions/39742305/how-to-use-basemap-python-to-plot-us-with-50-states
# Draw the data based on the input, with regards to state and value
def draw_map(inputValue, title):
    import numpy as np
    import matplotlib.pyplot as plt
    from mpl_toolkits.basemap import Basemap as Basemap
    from matplotlib.colors import rgb2hex
    from matplotlib.patches import Polygon
    from matplotlib.colors import Normalize

    from matplotlib.colorbar import ColorbarBase

    # Lambert Conformal map of lower 48 states.
    m = Basemap(
        llcrnrlon=-119,
        llcrnrlat=22,
        urcrnrlon=-64,
        urcrnrlat=49,
        projection="lcc",
        lat_1=33,
        lat_2=45,
        lon_0=-95,
    )
    shp_info = m.readshapefile("st99_d00", "states", drawbounds=True)
    # choose a color for each state based on population density.
    colors = {}
    statenames = []
    cmap = plt.cm.hot  # use 'hot' colormap
    vmin = min(inputValue.values())
    vmax = max(inputValue.values())  # set range.
    for shapedict in m.states_info:
        statename = shapedict["NAME"]
        # skip DC and Puerto Rico.
        if statename not in ["District of Columbia", "Puerto Rico"]:
            curValue = inputValue[statename]
            # calling colormap with value between 0 and 1 returns
            # rgba value.  Invert color range (hot colors are high
            # population), take sqrt root to spread out colors more.
            colors[statename] = cmap(
                1 - np.sqrt((curValue - vmin) / (vmax - vmin))
            )[:4]
        statenames.append(statename)
    # cycle through state names, color each one.
    ax = plt.gca()  # get current axes instance
    for nshape, seg in enumerate(m.states):
        # skip DC and Puerto Rico.
        if statenames[nshape] not in ["District of Columbia", "Puerto Rico"]:
            color = rgb2hex(colors[statenames[nshape]])
            poly = Polygon(seg, facecolor=color, edgecolor=color)
            ax.add_patch(poly)
    plt.title(title)

    norm = Normalize(
        vmin=min(inputValue.values()), vmax=max(inputValue.values())
    )
    cax = plt.gcf().add_axes([0.27, 0.1, 0.5, 0.05])  # posititon
    cb = ColorbarBase(
        cax, cmap=cmap.reversed(), norm=norm, orientation="horizontal"
    )
    plt.show()

# Compute the return over interest and draw the map
def compute_roi_and_draw_map(dataframe=h.read_final_data()):
    average = dict()
    for value in abbrev_to_us_state.values():
        average[value] = (0, 0)

    for i, row in dataframe.iterrows():
        roi = row["20 Year Net ROI"][1:].replace(",", "")
        try:
            roi = int(roi)
        except:
            roi = 0

        try:
            state = abbrev_to_us_state[(row["State"])]
            (allVal, count) = average[state]
            average[state] = (allVal + roi, count + 1)
        except:
            pass
    for key in average.keys():
        a, b = average[key]
        try:
            average[key] = a / b
        except:
            average[key] = 0
    draw_map(average, "Average ROI By States ($)")
    print("Please refer to the map!")

# Compute the cost and draw the map
def compute_cost_and_draw_map(dataframe=h.read_final_data()):
    average = dict()
    for value in abbrev_to_us_state.values():
        average[value] = (0, 0)

    for i, row in dataframe.iterrows():
        cost = row["Total 4 Year Cost"][1:].replace(",", "")
        try:
            cost = int(cost)
        except:
            cost = 0

        try:
            state = abbrev_to_us_state[(row["State"])]
            (allVal, count) = average[state]
            average[state] = (allVal + cost, count + 1)
        except:
            pass
    for key in average.keys():
        a, b = average[key]
        try:
            average[key] = a / b
        except:
            average[key] = 0
    draw_map(average, "Total 4 Year Cost ($)")
    print("Please refer to the map!")

# Compute the loan and draw the map
def compute_loan_and_draw_map(dataframe=h.read_final_data()):
    average = dict()
    for value in abbrev_to_us_state.values():
        average[value] = (0, 0)

    for i, row in dataframe.iterrows():
        loan = row["Average Loan Amount"][1:].replace(",", "")
        try:
            loan = int(loan)
        except:
            loan = 0

        try:
            state = abbrev_to_us_state[(row["State"])]
            (allVal, count) = average[state]
            average[state] = (allVal + loan, count + 1)
        except:
            pass
    for key in average.keys():
        a, b = average[key]
        try:
            average[key] = a / b
        except:
            average[key] = 0
    draw_map(average, "Average Loan Amount ($)")
    print("Please refer to the map!")

if __name__ == "__main__":
    compute_roi_and_draw_map()
    compute_cost_and_draw_map()
    compute_loan_and_draw_map()


import requests
from bs4 import BeautifulSoup
import pandas as pd

def parser(number, username):
    target_url = "https://home.gamer.com.tw/acgbox.php?page=" + str(number) + "&owner=" + str(username) + "&tab=&m="

    HEADERS = {'User-Agent': 'Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/112.0.0.0 Safari/537.36'}

    r = requests.get(target_url, headers=HEADERS)
    soup = BeautifulSoup(r.text, 'lxml')
    #pandas.read_html() 是设计来解析 HTML 中的表格标签 (<table>) 的内容的，如果 HTML 内容不是表格标签或是表格内容没有被包在 <table> 标签中，就不能直接使用 pandas.read_html()。
    # 如果你想要解析 HTML 中的其他元素，比如 <div>，你可以先使用 BeautifulSoup 或是其他 HTML 解析器，然后再提取出需要的内容，再将其转换成 pandas.DataFrame。
    check_table = pd.read_html(str(soup), flavor='lxml', attrs={'class': 'acgboxname'})
    print(check_table)

if __name__ == "__main__":
    #please replace username to test
    parser(1, "username")


CONSTRUCTOR = {
    '(_,_)' : ('+', ('+', '+')),
    '()' : ('+', ()),
    'int' : ('+', ()),  # Pattern matching don't deal with the actual stored integer
    'str' : ('+', ()),
    '(_)car' : ('~-', ('~-',)),
    '(_)cdr' : ('~-', ('~-',)),
    '(_->_)' : ('~-', ('+', '~-')),
    '(_)delay' : ('~-', ('~+',)),
    'wrap(_)' : ('+', ('-',)),
    'mu(_)' : ('+', ('~+',)),
    '(_)mu' : ('~-', ('-',)),
    '[]' : ('~-', ())
}
def format_constructor(name, args):
    return str(name).replace('_', '%s') % args

# A pattern is a tuple-tree like S-expressions.
def format_pattern(pattern):
    if isinstance(pattern, tuple):
        return format_constructor(pattern[0], tuple(format_pattern(x) for x in pattern[1:]))
    else:
        return str(pattern)

def var_pattern(pattern):
    """Finds the free variables in a pattern."""
    if isinstance(pattern, tuple):
        return set.union(*(var_pattern(x) for x in pattern[1:]))
    else:
        return {pattern}

def check_pattern(pattern):
    """Checks whether the polarity is well-formed, and checks for repeated variables.
    Returns the polarity and a set of free variables."""
    if isinstance(pattern, tuple):
        if pattern[0] in CONSTRUCTOR:
            fvar = set()
            for i, arg in enumerate(pattern[1:]):
                polarity, arg_fvar = check_pattern(arg)
                if polarity == "?" or polarity == CONSTRUCTOR[pattern[0]][i]:
                    if fvar.isdisjoint(var_pattern(arg)):
                        fvar.update(arg_fvar)
                    else:
                        raise Exception('Repeated variables in pattern: %s' % format_pattern(pattern))
                else:
                    raise Exception('Invalid polarity in pattern: %s' % format_pattern(pattern))
            return CONSTRUCTOR[pattern[0]][0], fvar
        else:
            raise ValueError('Unknown constructor: %s' % pattern[0])
    else:
        return "?", {pattern}

class SyntaxNode:
    """Represents a node in an abstract syntax tree.

    Each node has a `name` which is the name of its node type,
    and a `attr` dictionary recording various non-`SyntaxNode`
    attributes. The subtrees are recorded in the `child` dictionary.
    Each node also has a `bind` attribute which records the variables
    bound."""
    def __init__(self, name, attr=None, child=None, bind=None):
        self.name = name
        self.attr = attr or {}
        self.child = child or {}
        self.bind = bind or set()

    @staticmethod
    def var(name):
        """Creates a variable node."""
        return SyntaxNode('var', {'name': name})

    @staticmethod
    def cons(name, *args, **tag):
        """Creates a constructor node."""
        return SyntaxNode('cons', {'constructor': name, 'tag': tag}, {i: arg for i, arg in enumerate(args)})

    @staticmethod
    def command(lazy, eager):
        """Creates a command node."""
        return SyntaxNode('command', child={'lazy': lazy, 'eager': eager})

    @staticmethod
    def hole(var, body):
        """Creates a hole node."""
        return SyntaxNode('hole', attr={'bind':var}, child={'body': body}, bind={var})

    @staticmethod
    def case(term, cases:list):
        """Creates a case node."""
        return SyntaxNode('case', child={'term': term}.update({i: case for i, case in enumerate(cases)}))

    @staticmethod
    def clause(pattern, body):
        """Creates a pattern matching clause. This is used in the `cases` list."""
        return SyntaxNode('clause', attr={'pattern': pattern}, child={'body': body}, bind=var_pattern(pattern))

    @staticmethod
    def sub(name, **args):
        """Either calls a builtin or a predefined function."""
        return SyntaxNode('sub', {'name': name}, args)

HALT = SyntaxNode('halt')

def get_clauses(term):
    """Returns a list of clauses in a case node."""
    i = 0
    while i in term.child:
        yield term.child[i]
        i += 1

class PatternMatchException(Exception):
    """Raised when a pattern match fails."""
    pass

def match(pattern, term):
    """Matches a pattern against a term. Returns a dictionary of bindings."""
    if isinstance(pattern, tuple):
        if term.name == 'cons' and pattern[0] == term.attr['constructor']:
            if len(pattern) == 1:
                return {}
            else:
                bindings = {}
                for i, arg in enumerate(pattern[1:]):
                    bindings.update(match(arg, term.child[i]))
                return bindings
        else:
            raise PatternMatchException()
    else:
        return {pattern: term}

def casejump(clauses, term):
    for i, clause in enumerate(clauses):
        try:
            return i, match(clause.attr['pattern'], term)
        except PatternMatchException:
            pass
    raise PatternMatchException()

def check(constants, term, polarity=None):
    """Checks a term for polarity. polarity=`None` for inferring."""
    pass

def evaluate(constants, environment:dict, term):
    """Evaluates a (checked) term.
    Constants are dictionaries with value either:
    - ("native", polarity, list of argument polarities, function)
    - ("constant", polarity, dictionary of argument names -> polarities, term)"""
    if term.name == 'var':
        return environment[term.attr['name']]
    elif term.name == 'cons':
        return SyntaxNode.cons(term.attr['constructor'], *(evaluate(constants, environment, child) for child in term.child.values()), **term.attr['tag'])
    elif term.name == 'command':
        eager = evaluate(constants, environment, term.child['eager'])
        lazy = evaluate(constants, environment, term.child['lazy'])
        if lazy.name == 'hole':
            return evaluate(constants, {**environment, lazy.attr["bind"]:eager}, lazy.child['body'])
        else:
            raise Exception('Unexpected term: %s' % lazy)
    elif term.name == 'hole':
        return term
    elif term.name == 'case':
        i, bindings = casejump(get_clauses(term.child), evaluate(constants, environment, term.child['term']))
        return evaluate(constants, {**environment, **bindings}, term.child[i].child['body'])
    elif term.name == 'clause':
        raise RuntimeError('Unreachable!')
    elif term.name == 'sub':
        c = constants[term.attr['name']]
        if c[0] == 'native':
            return evaluate(constants, environment,
                c[3](**{name : evaluate(constants, environment, arg) for name, arg in term.child.items()}))
        elif c[0] == 'constant':
            arguments = {name: evaluate(constants, environment, arg) for name, arg in term.child.items()}
            return evaluate(constants, {**environment, **arguments}, c[2])
    elif term.name == 'halt':
        return term
    else:
        raise RuntimeError('Bad syntax tree.')

def _print(term, cont):
    print(term.attr["tag"]["value"])
    return SyntaxNode.command(cont, SyntaxNode.cons('[]'))

def _input(cont):
    i = int(input())
    return SyntaxNode.command(cont, SyntaxNode.cons('int', value = i))

# TODO better error prompts
CONSTANTS = {
    'add': ('native', '+', {'x':'+', 'y':'+'}, lambda x, y: SyntaxNode.cons("int", value = x.attr['tag']['value'] + y.attr['tag']['value'])),
    'print': ('native', '#', {'term':'+', 'cont':'-'}, _print),
    'input': ('native', '#', {'cont':'~+'}, _input),
}

if __name__ == '__main__':
    # Inputs an integer x, outputs x + 3.
    program = SyntaxNode.sub('input',
        cont = SyntaxNode.hole('x',
            SyntaxNode.sub('print',
                term = SyntaxNode.sub('add',
                    x = SyntaxNode.var('x'),
                    y = SyntaxNode.cons('int', value = 3)),
                cont = SyntaxNode.hole('_',
                    HALT))))
    evaluate(CONSTANTS, {}, program)


# © Deltares 2023.
# License notice: This file is part of RA2CE GUI. RA2CE GUI is free software: you can redistribute it and/or modify it
# under the terms of the GNU Lesser General Public License as published by the Free Software Foundation, either version
# 3 of the License, or (at your option) any later version. RA2CE GUI is distributed in the hope that it will be useful,
# but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
# See the GNU Lesser General Public License for more details. You should have received a copy of the GNU Lesser General
# Public License along with RA2CE GUI. If not, see <https://www.gnu.org/licenses/>.
#
# This tool is developed for demonstration purposes only.

from PyQt5.QtWidgets import QDateTimeEdit
from PyQt5.QtWidgets import QLabel
from PyQt5 import QtCore

from .widget_group import WidgetGroup

class DateEdit(WidgetGroup):

    def __init__(self, element, parent):
        super().__init__(element, parent)

        b = QDateTimeEdit(parent)
        self.widgets.append(b)

        b.setCalendarPopup(True)
        b.setDisplayFormat("yyyy-MM-dd hh:mm:ss")
        x0, y0, wdt, hgt = element["window"].get_position_from_string(self.element["position"], self.parent)
        b.setGeometry(x0, y0, wdt, hgt)
        if element["text"]:
            label = QLabel(self.element["text"], self.parent)
            self.widgets.append(label)
            fm = label.fontMetrics()
            wlab = fm.size(0, element["text"]).width() + 15
            label.setAlignment(QtCore.Qt.AlignRight)
            label.setGeometry(x0 - wlab - 3, y0 + 5, wlab, hgt)
            label.setStyleSheet("background: transparent; border: none")

        fcn = lambda: self.callback()
        b.editingFinished.connect(fcn)
        if self.module and "method" in self.element:
            fcn = getattr(self.module, self.element["method"])
            b.editingFinished.connect(fcn)

    def set(self):
        if self.check_variables():
            group = self.element["variable_group"]
            name  = self.element["variable"]
            val   = getvar(group, name)
            dtstr = val.strftime("%Y-%m-%d %H:%M:%S")
            qtDate = QtCore.QDateTime.fromString(dtstr, 'yyyy-MM-dd hh:mm:ss')
            self.widgets[0].setDateTime(qtDate)
            self.set_dependencies()

    def callback(self):
        if self.check_variables():

            newval = self.widgets[0].dateTime().toPyDateTime()

            # Do some range checking here ...

            # Update value in variable dict
            group = self.element["variable_group"]
            name  = self.element["variable"]
            setvar(group, name, newval)


import matplotlib.pyplot as plt
from random import randint
import pickle
import gym
import numpy as np
import argparse
import wimblepong

from agent import Agent

parser = argparse.ArgumentParser()
parser.add_argument("--headless", action="store_true", help="Run in headless mode")
parser.add_argument("--housekeeping", action="store_true", help="Plot, player and ball positions and velocities at the end of each episode")
parser.add_argument("--fps", type=int, help="FPS for rendering", default=30)
parser.add_argument("--scale", type=int, help="Scale of the rendered game", default=1)
args = parser.parse_args()

# Make the environment
env = gym.make("WimblepongVisualSimpleAI-v0")
env.unwrapped.scale = args.scale
env.unwrapped.fps = args.fps

def plot_reward_history(reward_history, episode_interval):
    plt.plot(reward_history)
    plt.xticks(np.arange(len(reward_history)), [f'{episode_interval * (i + 1)}' for i in range(len(reward_history))])
    plt.title(f'Average rewards for sequences of {episode_interval} episodes')
    plt.xlabel('Training episodes')
    plt.ylabel('Average rewards')
    plt.savefig('training_rewards.png')

# Number of episodes/games to play
EPISODES = 20000
EPISODE_INTERVAL = 100
TARGET_UPDATE_INTERVAL = 100
SAVE_INTERVAL = 1000
stack_frames =  4 # 0, 2,  4
observations_start_idx = 0 if stack_frames == 4 else 2

# Define the player
player_id = 1
player = Agent(training=True, stack_frames=stack_frames, downscale=True, priority_memory=True)

# Housekeeping
states = []
win1 = 0
reward_history = []
episode_rewards = 0

for i in range(1, EPISODES + 1):
    done = False
    observations = [None, None, None, None, None] # store 5 latest observations to update the agent
    frames = 0
    player.reset()
    while not done:
        action1 = player.get_action(observations[-1])
        observations[0] = observations[1]
        observations[1] = observations[2]
        observations[2] = observations[3]
        observations[3] = observations[4]
        observations[4], rew, done, info = env.step(action1)
        frames += 1
        if observations[observations_start_idx] is not None:
            player.update_memory(observations[observations_start_idx:], action1, rew, done)
        if frames % TARGET_UPDATE_INTERVAL == 0:
            player.update_target_network()

        player.update_dqn() # DQN update
        #player.update_ddqn() # Double DQN update
        episode_rewards += rew
        if args.housekeeping:
            states.append(observations[-1])
        # Count the wins
        if rew == 10:
            win1 += 1
        if not args.headless:
            env.render()
        if done:
            player.memory.update_beta()
            observation= env.reset()
            plt.close()  # Hides game window
            if args.housekeeping:
                plt.plot(states)
                plt.legend(["Player", "Opponent", "Ball X", "Ball Y", "Ball vx", "Ball vy"])
                plt.show()
                states.clear()
            print("episode {} over. Broken WR: {:.3f}, epsilon: {:.2f}".format(i, win1/(i+1), player.epsilon))
            if i % 5 == 4:
                env.switch_sides()
    if i % EPISODE_INTERVAL == 0:
        avg_rewards = episode_rewards / EPISODE_INTERVAL
        reward_history.append(avg_rewards)
        print(f'Average rewards for last {EPISODE_INTERVAL} episodes: {avg_rewards}')
        episode_rewards = 0
    if i % SAVE_INTERVAL == 0:
        player.save()
        plot_reward_history(reward_history, EPISODE_INTERVAL)
        if i == 12000:
            player.set_lr(1e-5)
        elif i == 8000:
            player.set_lr(2e-5)
        elif i == 5000:
            player.set_lr(4e-5)
player.save()
plot_reward_history(reward_history, EPISODE_INTERVAL)


# -*- coding: utf-8 -*-
from flask import g,render_template
import datetime
'''
自定义分页类
'''
def iPagination( params ):
    import math

    ret = {
        "is_prev":1,
        "is_next":1,
        "from" :0 ,
        "end":0,
        "current":0,
        "total_pages":0,
        "page_size" : 0,
        "total" : 0,
        "url":params['url'].replace("&p=","")
    }

    total = int( params['total'] )
    page_size = int( params['page_size'] )
    page = int( params['page'] )
    display = int( params['display'] )
    total_pages = int( math.ceil( total / page_size ) )
    total_pages = total_pages if total_pages > 0 else 1
    if page <= 1:
        ret['is_prev'] = 0

    if page >= total_pages:
        ret['is_next'] = 0

    semi = int( math.ceil( display / 2 ) )

    if page - semi > 0 :
        ret['from'] = page - semi
    else:
        ret['from'] = 1

    if page + semi <= total_pages :
        ret['end'] = page + semi
    else:
        ret['end'] = total_pages

    ret['current'] = page
    ret['total_pages'] = total_pages
    ret['page_size'] = page_size
    ret['total'] = total
    ret['range'] = range( ret['from'],ret['end'] + 1 )
    return ret

'''
统一渲染方法
'''
def ops_render( template,context = {} ):
    if 'current_user' in g:
        context['current_user'] = g.current_user
    return render_template( template,**context )

'''
获取当前时间
'''
def getCurrentDate( format = "%Y-%m-%d %H:%M:%S"):
    #return datetime.datetime.now().strftime( format )
    return datetime.datetime.now()

'''
获取格式化的时间
'''
def getFormatDate( date = None ,format = "%Y-%m-%d %H:%M:%S" ):
    if date is None:
        date = datetime.datetime.now()

    return date.strftime( format )

'''
根据某个字段获取一个dic出来
'''
def getDictFilterField( db_model,select_filed,key_field,id_list ):
    ret = {}
    query = db_model.query
    if id_list and len( id_list ) > 0:
        query = query.filter( select_filed.in_( id_list ) )

    list = query.all()
    if not list:
        return ret
    for item in list:
        if not hasattr( item,key_field ):
            break

        ret[ getattr( item,key_field ) ] = item
    return ret

def selectFilterObj( obj,field ):
    ret = []
    for item in obj:
        if not hasattr(item, field ):
            break
        if getattr( item,field )  in ret:
            continue
        ret.append( getattr( item,field ) )
    return ret

def getDictListFilterField( db_model,select_filed,key_field,id_list ):
    ret = {}
    query = db_model.query
    if id_list and len( id_list ) > 0:
        query = query.filter( select_filed.in_( id_list ) )

    list = query.all()
    if not list:
        return ret
    for item in list:
        if not hasattr( item,key_field ):
            break
        if getattr( item,key_field ) not in ret:
            ret[getattr(item, key_field)] = []

        ret[ getattr( item,key_field ) ].append(item )
    return ret


import click
from text_detection import TextDetection

@click.command()
@click.option(
    '-i', '--image',
    prompt=True, required=True,
    type=click.Path(dir_okay=False, exists=True),
    help='Input image to be OCR\'d.')
@click.option(
    '-o', '--output',
    type=click.Path(file_okay=False, exists=True),
    help='Path to the output image and its content.')
@click.option(
    '-f', '--file_format',
    default="csv",
    show_default=True,
    type=click.Choice(["json", "csv"]),
    help='Format type to the result content.')
@click.option(
    '-m', '--min-conf',
    default=0,
    show_default=True,
    type=click.IntRange(min=0, max=100),
    help='Mininum confidence value to filter weak text detection.')
@click.option(
    '--line/--word',
    default=False,
    show_default=True,
    help='Determines whether to extract words or rows of text.')
@click.option(
    '-d', '--distance',
    default=10,
    show_default=True,
    type=click.IntRange(min=0, max=20),
    help='Max distance between words in the same row, it\'s used if --line is used.')
def ocr(image, output, file_format, min_conf, line, distance):
    word_detection = TextDetection(
        image,
        output,
        line=line,
        word_distance=distance,
        file_format=file_format,
        min_confidence=min_conf,
    )

    word_detection.detect()

if __name__ == '__main__':
    ocr()


# The graphics

import turtle

def colorgen(colors):
		for color in colors:
			yield color

def abs(n):
	if n < 0:
		return n * -1
	else:
		return n

class Branch:
	def __init__(self, text, pos, height, width, color, style, layers):
		self.text = text
		self.pos = pos
		self.height = height
		self.width = width
		self.color = color
		self.style = style
		self.layers = layers

		#print("Box: {}  |  {}  [{}]".format(self.pos, self.text, layers))

	def drawBox(self):
		self.t.setpos(self.pos)
		self.t.fillcolor(self.color)
		self.t.begin_fill()
		for i in range(4):
			if i % 2 == 1:
				self.t.pendown()
				self.t.forward(self.height * self.layers)
				self.t.penup()
			else:
				self.t.penup()
				self.t.forward(self.width)
			self.t.right(90)
		self.t.end_fill()

	def drawText(self):
		x = self.pos[0] + (self.width / 2)
		y = self.pos[1] - self.height
		self.t.penup()
		self.t.setpos(x, y)
		self.t.write(self.text, font=self.style, align='center', move=True)
		return abs(x - self.t.pos()[0])

	def draw(self):
		self.t = turtle.Turtle()
		self.t.penup()
		self.drawBox()
		self.drawText()

class Leaf(Branch):
	def __init__(self, text, pos, height, style, width=0):
		Branch.__init__(self, text, pos, height, width, None, style, 1)

	def draw(self):
		self.t = turtle.Turtle()
		self.size = self.drawText()
		self.size *= 2
		if self.size < self.height * 1.5:
			self.size *= 2
		return self.size

# This will be the master class for displaying content
class visTree:
	def __init__(self, pos, block_grid):
		turtle.setup(width=.75, height=0.5, startx=5, starty=5)

		self.pos = (pos[0] - (turtle.window_width() / 2), (turtle.window_height() / 2) - pos[1]) # this is the upper right corner of the drawn tree
		self.bGrid = block_grid # grid of gridBlock objects

		self.color_list = ['#33cc8c', '#b38d99', '#2f4b7c', '#665191', '#a05195', '#d45087', '#f95d6a', '#ff7c43', '#ffa600', '#ff8c8c', '#eaa3fe', '#bea3fe', '#ac57ac', '#c267fe', '#7784da', '#73b0c2', '#67eafd', '#59f8dd', '#64f88a', '#ed6c74']
		self.colorscheme = colorgen(self.color_list)
		self.style = ("Arial", 14)
		self.layerHeight = 20

	def create(self):
		turtle.tracer(0, 0)
		turtle.hideturtle()
		tDepth = len(self.bGrid) # total depth
		#self.treeTable = [[None for _ in range(len(self.bGrid[0]))] for _ in range(tDepth)]
		self.treeTable = []

		# The bottom level, get widths, don't actually draw this, we cant yet
		self.widths = []
		#self.treeTable.append([])
		for word in self.bGrid[tDepth-1]:
			text = '  ' + word.text + ' '
			#text = word.text
			newleaf = Leaf(text, self.pos, self.layerHeight, self.style)
			self.widths.append(newleaf.draw())
			#print("w: {} ".format(self.widths[-1]))
		turtle.clearscreen()

		# now that we have widths, build the tree but don't draw
		# top down

		drawPos = list(self.pos)
		for d in range(tDepth):
			self.treeTable.append([])
			# d : depth
			currentBranch = {'id':None, 'width':0, 'text':None}
			for b in range(len(self.widths)):
				#print("{}, {} | {} | {}".format(d, b, drawPos, currentBranch))
				# b : block index
				block = self.bGrid[d][b]
				# don't do spacers
				if not block.content:
					drawPos[0] += self.widths[b]
					continue

				if d + 1 == tDepth:
					# at the bottom, leaves
					text = block.text
					self.treeTable[d].append(Leaf(text, (drawPos[0], self.pos[1] - ((tDepth-1) * self.layerHeight)), self.layerHeight, self.style, width=self.widths[b]))
					drawPos[0] += self.widths[b]
				else:
					# branch
					if block.id == currentBranch['id']:
						# continue creating block
						currentBranch['width'] += self.widths[b]

					# finish old branch?
					if not currentBranch['id'] is None:
						if b+1 == len(self.widths) or block.id != currentBranch['id']:
							l = tDepth - (d + 1)
							self.treeTable[d].append(Branch(currentBranch['text'], tuple(drawPos), self.layerHeight, currentBranch['width'], next(self.colorscheme), self.style, l))
							drawPos[0] += currentBranch['width']

					if block.id != currentBranch['id']:
						# new branch
						currentBranch['id'] = block.id
						currentBranch['text'] = block.label
						currentBranch['width'] = self.widths[b]
			drawPos[0] = self.pos[0]
			drawPos[1] -= self.layerHeight

	def draw(self):
		turtle.tracer(0, 0)
		turtle.hideturtle()
		for layer in self.treeTable:
			for branch in layer:
				# b : block index
				branch.draw()


def bfs():
    queue = [start]
    visited = []
    while queue:
        x, y = queue.pop(0)
        if abs(x-end[0]) + abs(y-end[1]) <= 1000: # 맥주 한 박스에 20병, 1병에 50미터 -> 1000미터까지 가능
            return True
        for nx, ny in cos:
            if [nx, ny] not in visited and abs(x-nx) + abs(y-ny) <= 1000: # 아직 들리지 않은 편의점에 갈 수 있는지
                visited.append([nx, ny])
                queue.append([nx, ny])
    return False

for _ in range(int(input())):
    n = int(input())
    start = list(map(int, input().split()))
    cos = [list(map(int, input().split())) for _ in range(n)]
    end = list(map(int, input().split()))
    print("happy" if bfs() else "sad")