# coding=utf-8
import document
import shape
from db import error, Trae_Fila, lee, rg_vacio, gpx, cl, copia_rg, FDC, GS_INS, u_libre, Busca_Prox, Fecha, i_selec, \
	Abre_Aplicacion, Abre_Empresa
from db import Int, Num, lista, Num_aFecha, lee_dc
from aa_funciones import Serie, GetColumnasACC_CK, LineaToDc
from shape import TextBox

def CertificadoSAT(partes, args, columnas_checks=GetColumnasACC_CK(), LineaToDc=LineaToDc, Serie=Serie, cl=cl, gpx=gpx):
	#from gsWord import document, shape
	import os

	u_libres = {}

	def Posicion(campo, arp, cl=cl, gpx=gpx):
		fila = Trae_Fila(FDC[gpx[1]][arp][2], campo, clr=-2)
		fmt = Trae_Fila(FDC[gpx[1]][arp][2], campo, clr=2)
		if fila is None:
			error(cl, "No existe el campo '%s' en el diccionario '%s'." % (campo, arp))
		return fila, fmt

	def merge_vars(text, dc, cl=cl):
		for key in dc.keys():
			if key not in text:
				continue
			if type(dc[key]) == list:
				text = text.split(' ')
				for k in range(len(text)):
					if text[k].startswith(key):
						text[k] = text[k].split('/')
						if len(text[k]) == 1:
							text[k] = str(dc[key])
						elif len(text[k]) == 2:
							v = ''
							if Int(text[k][1]) < len(dc[key]):
								v = str(dc[key][Int(text[k][1])])
							text[k] = v
							text[k] = str(dc[key][Int(text[k][1])])
						elif len(text[k]) == 3:
							v = ''
							if Int(text[k][1]) < len(dc[key]) and Int(text[k][2]) < len(dc[key][Int(text[k][1])]):
								v = str(dc[key][Int(text[k][1])][Int(text[k][2])])
							text[k] = v

				text = ' '.join(text)
			else:
				val = dc[key]
				if val is None:
					val = ''
				if hasattr(dc[key], 'keys') and 'IDX' in dc[key].keys():
					val = dc[key]['IDX']
				text = text.replace(key, val)

		return text

	##

	def GetAcciones(cd_parte, parte, idioma, columnas_checks=columnas_checks, _LineaToDc=LineaToDc, cl=cl, gpx=gpx):
		acciones_parte = i_selec(cl, gpx, 'acciones', 'ACC_NPAR', cd_parte, cd_parte)
		_checks = {}
		_contratos_checks = {}
		_tecnicos = []
		dc_tecnicos = {}
		_observaciones = {}

		_tipo_elementos = []
		arts = {}

		periodicidad = ''
		first_action = {}
		tipo_parte = parte['PT_TIPO']['IDX']
		acciones_parte=[]
		c='016232'
		while c < '016255':
			if c=='016250':
				c='016251'
				continue
			acciones_parte.append(c)
			c=Busca_Prox(c)
		for cd_accion in acciones_parte:
			rg_accion = lee_dc(lee_dc, gpx, 'acciones', cd_accion)

			if not periodicidad:
				periodicidad = rg_accion['ACC_TPER']
			if rg_accion['ACC_TPER'] == 'M':
				periodicidad = rg_accion['ACC_TPER']
			cdar = rg_accion['ACC_CDAR']['IDX']
			if cdar not in arts.keys():
				arts[cdar] = lee_dc(lee_dc, gpx, 'articulos', cdar, rels='')
			articulo = arts[cdar]

			if articulo['AR_TIPO'] != 'CC':
				deno_n1 = ''
				deno_n2 = ''
				for ln in FDC[gpx[1]]['articulos'][2]:
					campo, descripcion, tipo, cols, relaciones = ln[:5]
					if campo == idioma['PTCI_N1EI']:
						if relaciones:
							r = lee_dc(lee_dc, gpx, relaciones, articulo[campo])
							deno_n1 = r.get(FDC[gpx[1]][relaciones][2][0][0], '')
						else:
							deno_n1 = ''

					if campo == idioma['PTCI_N2EI']:
						if relaciones:
							r = lee_dc(lee_dc, gpx, relaciones, articulo[campo])
							try:
								deno_n2 = r.get(FDC[gpx[1]][relaciones][2][0][0], '')
							except:
								error(cl, (FDC[gpx[1]][relaciones][2][0][0], r))
						else:
							deno_n2 = ''

				if deno_n1:
					fila_n1 = Trae_Fila(_tipo_elementos, deno_n1, clb=0, clr=-2)
					if fila_n1 is None:
						fila_n1 = len(_tipo_elementos)
						_tipo_elementos.append([deno_n1, []])

					if deno_n2 and deno_n2 not in _tipo_elementos[fila_n1][1]:
						_tipo_elementos[fila_n1][1].append(deno_n2)

			tx_ = ''
			if rg_accion['ACC_NSER']:
				tx_ = idioma['PTCI_NS'] + ' ' + rg_accion['ACC_NSER'] + ' - '
			id_ns_ = cdar + rg_accion['ACC_MAR']['IDX'] + rg_accion['ACC_NSER']
			cd_numero_serie = '%s%s (%s)' % (tx_, articulo['AR_DENO'], id_ns_)
			normativa = ''
			# Se acumula por normativa
			if articulo['AR_TIPO'] == 'CC':
				# Si no hay check del elemento se busca el check del contrato
				cd_check = rg_accion['ACC_CKGC']
				if cd_check:
					rg_check = lee_dc(lee_dc, gpx, 'contratos_checklists', cd_check)
					if rg_check == 1:
						error(cl, "No existe el checklist del contrato '%s'." % cd_check)
					normativa = rg_check['CCK_NOR']['IDX']
			else:
				cd_check = rg_accion['ACC_CKG']['IDX']
				# Si hay check del elemento
				if cd_check:
					rg_check = lee_dc(lee_dc, gpx, 'checklists', cd_check)
					if rg_check == 1:
						error(cl, "No existe el checklist '%s'." % cd_check)
					normativa = rg_check['CK_NOR']['IDX']

			if normativa:
				rg_normativa = lee_dc(lee_dc, gpx, 'normativa', normativa)
				if rg_normativa == 1:
					error(cl, "No existe la normativa '%s'." % normativa)
			else:
				rg_normativa = {}

			_texto_antes, _texto_desupes, _tabla_resumen = '', '', ''
			oficial = 'S'
			for _linea in rg_normativa.get('NOR_CERT', []):

				if _linea[0] != tipo_parte or _linea[1] != oficial:
					continue
				_texto_antes, _texto_desupes, _tabla_resumen = _linea[2:5]

			'''_clave = (rg_normativa.get('NOR_NOR', 0), rg_normativa.get('NOR_CAP', 0), normativa,
			          rg_normativa.get('NOR_TITNOR', {}).get('NORC_DENO', ''),
			          rg_normativa.get('NOR_IMP', ''), _texto_antes, _texto_desupes)'''
			_clave = (rg_normativa.get('NOR_NOR', 0), rg_normativa.get('NOR_CAP', 0),)

			# print _clave
			if _clave not in _checks.keys():
				_checks[_clave] = {'BOLEANOS': [],
				                   'OTROS': [],
				                   'RESUMEN': {
					                   'horizontal': False,
					                   'titulos': [],
					                   'anchos': [],
					                   'h_align': [],
					                   'texto': [],
					                   'lineas': []
				                   },
				                   'DATA': [normativa,
				                            rg_normativa.get('NOR_TITNOR', {}).get('NORC_DENO', ''),
				                            rg_normativa.get('NOR_IMP', ''), _texto_antes, _texto_desupes]
				                   }

			if _tabla_resumen:
				td = eval(_tabla_resumen)
				if len(td) == 2:
					ls_tabla, horizontal = td
					texto_antes_tabla = ''
				elif len(td) == 3:
					ls_tabla, horizontal, texto_antes_tabla = td
				else:
					error(cl, "Nº de argumentos incorectos en la tabla de resumen")
				_checks[_clave]['RESUMEN']['horizontal'] = horizontal == 'S'
				_checks[_clave]['RESUMEN']['texto'] = texto_antes_tabla
				ln_tabla = []
				for ln_ in ls_tabla:
					col_name, diccionario, nombre_campo, columna, relacion, ancho, columna_filtrar, _idx_filtrar = ln_

					if diccionario == 'acciones':
						pos, fmt = Posicion(nombre_campo, diccionario)
						value = rg_accion[nombre_campo]
						if _clave not in first_action.keys():
							first_action[_clave] = True

						if first_action[_clave]:
							_checks[_clave]['RESUMEN']['anchos'].append(str(ancho) + '%')
							_checks[_clave]['RESUMEN']['titulos'].append(col_name)

						if columna_filtrar:
							fmt = fmt.split(' ')
							value = Trae_Fila(value, _idx_filtrar, clb=Int(columna_filtrar), clr=Int(columna))
							if value is None:
								value = ''
							fmt = fmt[Int(columna)]

						h_align = 'j'
						if fmt == 'd':
							h_align = 'c'
							value = Num_aFecha(value)
							if value is None:
								value = ''
						elif fmt in 'i012345':
							h_align = 'r'
						if first_action[_clave]:
							_checks[_clave]['RESUMEN']['h_align'].append(h_align)
						if type(value) == dict:
							value = value['IDX']
						ln_tabla.append(value)

				_checks[_clave]['RESUMEN']['lineas'].append(ln_tabla)

			if _clave not in _observaciones.keys():
				_observaciones[_clave] = []

			key = ''
			grupo = ''

			for k in range(len(rg_accion['ACC_CK'])):
				dc_check = _LineaToDc(rg_accion['ACC_CK'][k], columnas_checks)
				pregunta = dc_check['descripcion']
				respuesta = dc_check['respuesta']
				padre = dc_check['padre']
				numero = dc_check['numero']
				tipo = dc_check['tipo']
				if padre:
					fila_ns = None
					if grupo == 'BOLEANOS':
						fila_padre = Trae_Fila(_checks[_clave][grupo], padre, clb=0, clr=-2)
						if fila_padre is None:
							fila_padre = len(_checks[_clave][grupo])
							_checks[_clave][grupo].append(copia_rg(linea))
					else:

						fila_ns = Trae_Fila(_checks[_clave][grupo], cd_numero_serie, clb=0, clr=-2)
						if fila_ns is None:
							fila_ns = len(_checks[_clave][grupo])
							_checks[_clave][grupo].append([cd_numero_serie, []])
						fila_padre = Trae_Fila(_checks[_clave][grupo][fila_ns][1], padre, clb=0, clr=-2)

						if fila_padre is None:
							fila_padre = len(_checks[_clave][grupo][fila_ns][1])
							_checks[_clave][grupo][fila_ns][1].append(copia_rg(linea))
					# error(cl, (linea, fila_padre, checks[clave][grupo][fila_padre]))

					'''if grupo == 'BOLEANOS':
						_checks[_clave][grupo][fila_padre][1] += '  ' + pregunta + ' ' + respuesta
					else:
						a = _checks[_clave][grupo]
						_checks[_clave][grupo][fila_ns][1][fila_padre][1] += '\n' + pregunta + ' ' + respuesta'''
					if grupo == 'BOLEANOS':
						_checks[_clave][grupo][fila_padre][1] += '\n' + pregunta + ' ' + respuesta
					else:
						a = _checks[_clave][grupo]
						_checks[_clave][grupo][fila_ns][1][fila_padre][1] += '\n' + pregunta + ' ' + respuesta

					continue

				grupo = 'OTROS'
				linea = [numero, pregunta, respuesta]
				if tipo in 'XB':
					grupo = 'BOLEANOS'
					linea = [numero, pregunta, 0, 0, 0]

				if grupo == 'BOLEANOS':
					fila = Trae_Fila(_checks[_clave][grupo], numero, clb=0, clr=-2)
					if fila is None:
						fila = len(_checks[_clave][grupo])
						_checks[_clave][grupo].append(linea)

					if respuesta == 'SI':
						_checks[_clave][grupo][fila][2] += 1
					elif respuesta == 'N/A':
						_checks[_clave][grupo][fila][3] += 1
					elif respuesta == 'NO':
						_checks[_clave][grupo][fila][4] += 1
				else:
					fila = Trae_Fila(_checks[_clave][grupo], cd_numero_serie, clb=0, clr=-2)
					if fila is None:
						fila = len(_checks[_clave][grupo])
						_checks[_clave][grupo].append([cd_numero_serie, []])

					_checks[_clave][grupo][fila][1].append(linea)

			if rg_accion['ACC_OBS']:
				if articulo['AR_TIPO'] != 'CC':
					_observaciones[_clave].append(cd_numero_serie)
				_observaciones[_clave].append(rg_accion['ACC_OBS'])

			for ln_tec in rg_accion['ACC_TNCS']:
				cd_tecnico = ln_tec[0]
				estado = ln_tec[1]

				dc_tecnicos[cd_tecnico] = dc_tecnicos.get(cd_tecnico, lee_dc(lee_dc, gpx, 'personal', cd_tecnico))
				if dc_tecnicos[cd_tecnico] == 1:
					error(cl, "No existe el técnico '%s'." % cd_tecnico)
				rgt = dc_tecnicos[cd_tecnico]

				if rgt['PE_DENO'] not in _tecnicos:
					_tecnicos.append(rgt['PE_DENO'])

			first_action[_clave] = False
		return [_checks, _contratos_checks, _tecnicos, _observaciones, _tipo_elementos, periodicidad]

	##

	def LeeParte(cd_parte, cl=cl, gpx=gpx):
		dc = {}
		parte = lee_dc(lee_dc, gpx, 'partes', cd_parte)
		cliente = lee_dc(lee_dc, gpx, 'clientes', parte['PT_CCL']['IDX'])
		if cliente == 1:
			error(cl, "No existe el cliente '%s'." % parte['PT_CCL']['IDX'])
		parte.update(cliente)

		delegacion = lee_dc(lee_dc, gpx, 'delegaciones', parte['PT_CCL']['IDX'] + parte['PT_DEL']['IDX'])
		if delegacion == 1:
			error(cl,
			      "No existe la delegación '%s' del cliente '%s'." % (parte['PT_DEL']['IDX'], parte['PT_CCL']['IDX']))
		parte.update(delegacion)

		contrato = lee_dc(lee_dc, gpx, 'contratos', parte['PT_CON']['IDX'])
		ls_partes = i_selec(cl, gpx, 'partes', 'PT_CON', parte['PT_CON']['IDX'], parte['PT_CON']['IDX'])
		parte.update(contrato)
		parte['CN_FECU'] = ''
		if ls_partes:
			parte_ = lee_dc(cl, gpx, 'partes', ls_partes[-1], rels='n')
			parte['FECU'] = Num_aFecha(parte_['PT_FECPA'])
		parte['CN_FEC'] = Num_aFecha(parte['CN_FEC'])
		tipo_contrato = lee_dc(lee_dc, gpx, 'contratos_clases', parte['PT_CON']['CN_TIPO'])
		parte.update(tipo_contrato)
		parte['PT_DIREC/1/2'] = ''
		if len(parte['PT_DIREC']) > 1:
			parte['PT_DIREC/1/2'] = parte['PT_DIREC'][1][2]
		fecr = Num_aFecha(parte['PT_FECR'])
		if fecr is None:
			fecr = ''
		else:
			fecr = fecr[3:]
		parte['PT_FECR'] = fecr
		return [dc, parte]

	##

	def FormateaTablaPrincipal(idioma, tabla, color_primario, color_secundario, header=True):

		tabla.set_spacing({'after': '60', 'before': '60'})
		tabla.get_properties().set_cell_margin(
			{'start': {'w': '60'}, 'end': {'w': '60'}, 'top': {'w': '30'}, 'bottom': {'w': '30'}})

		tabla.set_font_size(idioma['PTCI_FSIZE'])
		if header:
			tabla.get_row(0).set_background_colour(color_primario)
			tabla.get_row(0).set_foreground_colour(color_secundario)
			tabla.get_row(0).set_font_format('b')
		for row in tabla.get_rows():
			row.get_cell(0).set_font_format('b')
			for cell in row.get_cells():
				cell.get_properties().set_vertical_alignment('center')
				for p in cell.elements:
					for t in p.elements:
						t.set_font(idioma['PTCI_FONT'])

	##

	def FormateaTitulo(idioma, paragraph):

		paragraph.set_font_format('b')
		paragraph.get_properties().set_keep_next(True)
		paragraph.set_font_size(idioma['PTCI_FSIZE'] + 4)
		paragraph.set_spacing({'before': '180', 'after': '80'})
		for t in paragraph.elements:
			t.set_font(idioma['PTCI_FONT'])

	##

	def FormateaCapitulo(idioma, paragraph):
		paragraph.set_font_format('b')
		paragraph.set_font_size(idioma['PTCI_FSIZE'] + 1)
		paragraph.set_spacing({'before': '180', 'after': '80'})
		for t in paragraph.elements:
			t.set_font(idioma['PTCI_FONT'])

	##

	def FormateaLista(idioma, paragraph):
		paragraph.set_font_size(idioma['PTCI_FSIZE'])
		for t in paragraph.elements:
			t.set_font(idioma['PTCI_FONT'])

	##

	def FormateaElemento(idioma, paragraph):
		paragraph.set_font_format('b')
		paragraph.set_font_size(idioma['PTCI_FSIZE'])
		paragraph.set_spacing({'before': '120', 'after': '120'})
		for t in paragraph.elements:
			t.set_font(idioma['PTCI_FONT'])

	##

	def Footer(doc_word, idioma, parte, _path_s):
		footer = doc_word.get_DefaultFooter()

		#-footer.add_rtf(idioma['PTCI_LOPD'])

	##

	def Header(header, doc_word, idioma, _path_i, _path_d, merge_vars=merge_vars, horizontal=False):
		num_pag = document.new_page_number(header, idioma['PTCI_SUFPAG'])
		num_pag.set_text_separator(idioma['PTCI_SEPPAG'])
		'''p = doc_word.new_paragraph(header)
		p.set_horizontal_alignment('r')'''

		paragraph_i = doc_word.new_paragraph(header, None)
		paragraph_i.AddPicture(header, _path_i, 1800, 1200)
		if _path_d:
			paragraph_d = doc_word.new_paragraph(header, None)
			paragraph_d.AddPicture(header, _path_d, 1800, 1200)

			table = header.add_table(
				[
					[paragraph_i, None, paragraph_d],
					[None, num_pag]
				],
				column_width=[2000, 6000, 2000],
				horizontal_alignment=['l', 'l', 'r'],
				# borders={'all': {'sz': 4}}
			)

			table.get_row(1).get_cell(0).get_properties().set_grid_span(2)
		else:
			table = header.add_table(
				[
					[paragraph_i, None],
					[None, num_pag]
				],
				column_width=[2000, 8000],
				horizontal_alignment=['l', 'r'],
				# borders={'all': {'sz': 4}}
			)

		font_size = idioma['PTCI_FSIZE']
		heigth_line = font_size * 20 + 40
		for ln_data in idioma['PTCI_TITULO']:
			paragraph = table.get_row(1).get_cell(0).add_paragraph(merge_vars(ln_data, parte), font_format='b')
			paragraph.set_spacing({'after': '60', 'before': '60', 'line': heigth_line})
			paragraph.set_font_size(font_size + 2)
			for t in paragraph.elements:
				t.set_font(idioma['PTCI_FONT'])

		table.get_row(1).get_cell(0).set_font_format('b')
		table.get_row(1).get_cell(0).set_font_size(font_size + 4)
		table.get_row(1).get_cell(0).get_properties().set_table_cell_width(20000)
		table.get_row(1).get_cell(1).add_paragraph(
			merge_vars('Nº Certificado ' + parte['PT_NUMCERT'], parte),
			horizontal_alignment='r',
			font_size=font_size + 1,
			font_format='b'
		)
		ls = []
		for line in idioma['PTCI_HEAD']:
			ha = 'l'
			if not _path_d:
				ha = 'r'
			paragraph = table.get_row(0).get_cell(1).add_paragraph(line[0], horizontal_alignment=ha, font_format='b')
			paragraph.set_spacing({'after': '60', 'before': '60', 'line': heigth_line})
			paragraph.set_font_size(font_size)
			for t in paragraph.elements:
				t.set_font(idioma['PTCI_FONT'])

		pos = (-5013, 8984)
		size = (10946, 428)
		if horizontal:
			pos = (-2700, 6120)
			size = (6800, 650)
		reg_mercantil = shape.TextBox(
			header,
			text=idioma['PTCI_REGM'],
			size=size,
			rotation=270,
			r_position=[
				{'orientation': 'horizontal', 'position': pos[0], 'relative': 'page'},
				{'orientation': 'vertical', 'position': pos[1], 'relative': 'page'}
			],
			background_color='FFFFFF',
			horizontal_alignment='c',
			font_format='b',
			font_size=8
		)

		p = header.add_paragraph(reg_mercantil)
		p.set_spacing({'after': '0', 'before': '0', 'line': '10'})

	##

	def firma_sello(doc_word, body, _path_s, parte, idioma):
		ls = []
		font_size = idioma['PTCI_FSIZE']
		body.add_paragraph('')
		tec_firma = parte['PT_TCF']['IDX']
		deno_tec = parte['PT_TCF'].get('PE_DENO', '')
		deno_tec += ' ' + parte['PT_TCF'].get('PE_DNI', '')
		deno_tec += ' ' + parte['PT_TCF'].get('PE_NCOL', '')
		sello = doc_word.new_image(body, _path_s, 1500, 1000, anchor='inline', horizontal_alignment='c')
		d_sello = ''  # doc_word.new_image(body, _path_s, 1500, 1000, anchor='inline', horizontal_alignment='c')

		representante = parte['PT_REPR']
		table_sellos = doc_word.new_table(
			body,
			[
				[idioma['PTCI_TITSEL'], '', idioma['PTCI_TITCLI']],
				[sello, '', d_sello],
				[idioma['PTCI_PIESEL'] + deno_tec, '', idioma['PTCI_PIECLI'] + representante]
			],
			horizontal_alignment=['c', 'c', 'c'],
			column_width=[3000, 4000, 3000]
		)
		table_sellos.set_font_format({(0,): 'b', (2,): 'b'})
		table_sellos.get_row(0).set_font_size(font_size)
		table_sellos.get_row(2).set_font_size(font_size)

		table_bloc = body.add_table(
			[[table_sellos]],
			horizontal_alignment=['c'],
			column_width=[10000]
		)
		table_bloc.get_row(0).get_properties().cantSplit = True
		# TODO cargar firma técnico
		img_f = 1  # lee(cl,gpx,'imagenes-t',tec_firma)
		if img_f not in [1, '']:
			_path_f = path_temp + tec_firma
			open(_path_f, 'wb').write(img_f)

	##

	def Portada(body, idioma, parte, numero_norma, numero_capitulo, section_margins, FormateaTitulo=FormateaTitulo,
	            merge_vars=merge_vars,
	            FormateaTablaPrincipal=FormateaTablaPrincipal):

		# Texto inicial
		if idioma['PTCI_TXTINI']:
			#-body.add_rtf(merge_vars(idioma['PTCI_TXTINI'], parte))
			numero_norma += 1

		# Apartado 1
		titulo_elemento = '%d. %s' % (numero_norma, merge_vars(idioma['PTCI_TITDP'], parte))
		numero_norma += 1
		paragraph_1 = body.add_paragraph(titulo_elemento)
		FormateaTitulo(idioma, paragraph_1)
		grid_span = []
		lineas_1 = []
		e = []
		for i in range(len(idioma['PTCI_DP'])):
			etiqueta, variable = idioma['PTCI_DP'][i][:2]
			e.append([i, variable])
			if variable:
				lineas_1.append([merge_vars(etiqueta, parte), merge_vars(variable, parte)])
			else:
				grid_span.append(i)
				lineas_1.append([merge_vars(etiqueta, parte)])
		tabla_1 = body.add_table(lineas_1, column_width=['25%', '75%'], borders=borders)

		for i in grid_span:
			tabla_1.get_row(i).get_cell(0).get_properties().set_grid_span(2)
			tabla_1.get_row(i).get_cell(0).get_properties().set_table_cell_width('100%')
		FormateaTablaPrincipal(idioma, tabla_1, color_primario, color_secundario, False)

		# Apartado 2
		titulo_elemento = '%d. %s' % (numero_norma, merge_vars(idioma['PTCI_TITDI'], parte))
		numero_norma += 1
		paragraph_1 = body.add_paragraph(titulo_elemento)
		FormateaTitulo(idioma, paragraph_1)
		grid_span = []
		lineas_1 = []
		for i in range(len(idioma['PTCI_DI'])):
			etiqueta, variable = idioma['PTCI_DI'][i][:2]
			if variable:
				lineas_1.append([merge_vars(etiqueta, parte), merge_vars(variable, parte)])
			else:
				grid_span.append(i)
				lineas_1.append([merge_vars(etiqueta, parte)])
		tabla_1 = body.add_table(lineas_1, column_width=['25%', '75%'], borders=borders)
		for i in grid_span:
			tabla_1.get_row(i).get_cell(0).get_properties().set_grid_span(2)
			tabla_1.get_row(i).get_cell(0).get_properties().set_table_cell_width('100%')
		FormateaTablaPrincipal(idioma, tabla_1, color_primario, color_secundario, False)

		_section = body.add_section()
		_section.SetMargins(section_margins)
		# Apartado 3
		titulo_elementos = '%d. %s' % (numero_norma, merge_vars(idioma['PTCI_TITEI'], parte))
		FormateaTitulo(idioma, body.add_paragraph(titulo_elementos))
		numero_norma += 1

		if idioma['PTCI_TXTEI']:
			#-body.add_rtf(idioma['PTCI_TXTEI'])
			pass

		t = 1
		for ln in tipo_elementos:
			s = 1
			deno_grupo, familias = ln[:3]
			r = ' '
			if r > 9:
				r = ''
			FormateaLista(idioma, body.add_paragraph('%d. %s%s' % (t, r, deno_grupo)))
			for deno_familia in familias:
				FormateaLista(idioma, body.add_paragraph('    %d.%d. %s' % (t, s, deno_familia)))
				s += 1
			t += 1

		# Textos contrato
		for cd_text in parte['PT_CON']['CN_TXT']:
			body.add_section().SetMargins(section_margins)
			_text = lee_dc(lee_dc, gpx, 'fcartas', cd_text)

			_text['FA_TXT'] = merge_vars(_text['FA_TXT'], parte)
			FormateaTitulo(idioma, body.add_paragraph(str(numero_norma) + '. ' + _text['FA_DENO']))
			#print '88888888888888888'
			body.add_rtf(_text['FA_TXT'])
			numero_norma += 1

		lista_checks_c = checks.keys()
		lista_checks_c.sort()
		_nor = ''
		nn = n_capitulo = 1

		for ln in lista_checks_c:
			_norma, _capitulo = ln
			if _norma > 1:
				continue
			cd_normativa, nombre_normativa, nombre_capitulo, _texto_antes, _texto_despues = checks[ln]['DATA']
			if not _nor:
				body.add_section().SetMargins(section_margins)

			if not nombre_normativa:
				nombre_normativa = 'DATOS GENERALES'
			if not _nor or _nor != _norma:
				_nor = str(numero_norma) + '. ' + nombre_normativa
				nn = numero_norma
				numero_norma += 1
				n_capitulo = 1
				paragraph_elemento = body.add_paragraph(_nor)
				FormateaTitulo(idioma, paragraph_elemento)

			paragraph_elemento = body.add_paragraph('%d.%d. %s' % (nn, n_capitulo, nombre_capitulo))
			FormateaCapitulo(idioma, paragraph_elemento)

			datos_generales = copia_rg(checks[ln].get('BOLEANOS', []))
			otros_datos_generales = copia_rg(checks[ln].get('OTROS', []))
			del checks[ln]

			if _texto_antes:
				rg_txt = lee_dc(lee_dc, gpx, 'fcartas', _texto_antes)
				if rg_txt == 1:
					error(cl, "No existe el texto '%s'" % _texto_antes)
				txt_antes = rg_txt['FA_TXT']
				txt_antes = merge_vars(txt_antes, parte)
				#-body.add_rtf(txt_antes)
			if datos_generales:
				# #$>datos_generales
				titulo_datos_generales = idioma['PTCI_TBOO']
				for j in range(len(datos_generales)):
					datos_generales[j][0] = "%d.%d.%d" % (nn, n_capitulo, j + 1)
					if '\n' in datos_generales[j][1]:
						datos_generales[j][1] = datos_generales[j][1].split('\n')

				tabla_datos_generales = body.add_table(datos_generales,
				                                       titulo_datos_generales,
				                                       column_width=columnas_checks,
				                                       borders=borders_checks,
				                                       horizontal_alignment=['r', 'j', 'c', 'c', 'c']
				                                       )
				FormateaTablaPrincipal(idioma, tabla_datos_generales, color_primario, color_secundario)

			if otros_datos_generales:
				if datos_generales:
					body.add_paragraph('')

				for i in range(len(otros_datos_generales)):
					titulo, lineas = otros_datos_generales[i]

					for j in range(len(lineas)):
						lineas[j][0] = "%d.%d.%d" % (nn, n_capitulo, j + 1)
						if '\n' in lineas[j][1]:
							lineas[j][1] = lineas[j][1].split('\n')

					_pie = body.add_table(lineas, idioma['PTCI_TNOR'],
					                      horizontal_alignment=['r', 'l', 'l'],
					                      column_width=columnas_others,
					                      borders=borders_checks)
					FormateaTablaPrincipal(idioma, _pie, color_primario, color_secundario)
			n_capitulo += 1

			if _texto_despues:
				body.add_paragraph('')
				rg_txt = lee_dc(lee_dc, gpx, 'fcartas', _texto_despues)
				if rg_txt == 1:
					error(cl, "No existe el texto '%s'" % _texto_despues)
				txt_despues = rg_txt['FA_TXT']
				txt_despues = merge_vars(txt_despues, parte)
				#-body.add_rtf(txt_despues)
			else:
				body.add_paragraph('')

			if not dc_observaciones.get(ln, []):
				observaciones = ['']
			else:
				observaciones = [''] * len(dc_observaciones[ln])
			_tabla_obs = body.add_table(observaciones,
			                            [idioma['PTCI_OBS']],
			                            horizontal_alignment=['j'],
			                            column_width=['100%'],
			                            borders=borders_obs
			                            )
			for i in range(len(dc_observaciones.get(ln, []))):
				_tabla_obs.get_row(i + 1).get_cell(0).elements = []
				if dc_observaciones[ln][i].startswith('{\\rtf'):
					#-_tabla_obs.get_row(i + 1).get_cell(0).add_rtf(dc_observaciones[ln][i])
					pass
				else:
					_tabla_obs.get_row(i + 1).get_cell(0).add_paragraph(dc_observaciones[ln][i])
			FormateaTablaPrincipal(idioma, _tabla_obs, color_primario, color_secundario)

			if otros_datos_generales and datos_generales:
				firma_sello(doc_word, body, _path_s, parte, idioma)
		return numero_norma, numero_capitulo

	##

	idioma = lee_dc(lee_dc, gpx, 'partes_certificado_idioma', '000')
	path_temp = GS_INS + '/temp/'
	if not os.path.exists(path_temp):
		os.makedirs(path_temp)

	parametros = lee_dc(lee_dc, gpx, 'parametros', '0')

	# Se recuperan los colores para las cabeceras de la tabla
	color = lista(parametros['P_COLPRI'], ':', 3)
	rgb = (Int(color[0]), Int(color[1]), Int(color[2]))
	color_primario = '%02x%02x%02x' % rgb
	if not parametros['P_COLSEC']:
		parametros['P_COLSEC'] = '255:255:255'
	color = lista(parametros['P_COLSEC'], ':', 3)
	rgb = (Int(color[0]), Int(color[1]), Int(color[2]))
	color_secundario = '%02x%02x%02x' % rgb

	imd = idioma['PTCI_LOGOD']

	_path_d = ''
	if imd:
		img_d = lee(cl, gpx, 'imgs_v', imd)
		if img_d == 1:
			error(cl, "No existe el logo " + imd)
		_path_d = path_temp + imd

		open(_path_d, 'wb').write(img_d)

	imi = idioma['PTCI_LOGOI']

	img_i = lee(cl, gpx, 'imgs_v', imi)
	if img_i == 1:
		error(cl, "No existe el logo " + imi)
	_path_i = path_temp + imi
	open(_path_i, 'wb').write(img_i)

	im_sello = idioma['PTCI_IMGSEL']
	img_sello = lee(cl, gpx, 'imgs_v', im_sello)
	if img_i == 1:
		error(cl, "No existe el logo " + im_sello)
	_path_s = path_temp + im_sello
	open(_path_s, 'wb').write(img_sello)

	accion = args.get('accion', '')
	impresora = args.get('desti', '')

	borders_checks = {'all': {'sz': 4, 'color': color_primario, 'space': 0}}
	borders_obs = copia_rg(borders_checks)
	borders_obs['insideH'] = {'sz': 0, 'color': color_primario, 'space': 0}
	columnas_checks = [750, 7450, 600, 600, 600]
	columnas_others = [750, 7450, 1800]
	section_margins = {'left': 953, 'right': 953, 'top': 1000, 'header': 600, 'footer': 400}

	documentos_generados = []
	borders = {'all': {'sz': 4, 'color': color_primario, 'space': 0},
	           'insideV': {'value': 'nil'}}

	for cd_parte in partes:
		dc_parte, parte = LeeParte(cd_parte)
		parte.update(parametros)
		if parte['PT_NUMCERT'] and False:
			rgcertificado = lee_dc(lee_dc, gpx, 'partes_certificado', parte['PT_NUMCERT'])
			documentos_generados.append(rgcertificado['PTC_DOC'])
			continue

		serie_cer = parte['PT_SERC']['IDX']
		ser_cert_complete = Serie(serie_cer, parte['PT_FECR'])
		if ser_cert_complete not in u_libres.keys():
			u_libres[ser_cert_complete] = u_libre(gpx, 'partes_certificado', ser_cert_complete)
		idx_cert = u_libres[ser_cert_complete]
		parte['PT_NUMCERT'] = idx_cert
		r = GetAcciones(cd_parte, parte, idioma)
		checks, contratos_checks, tecnicos, dc_observaciones, tipo_elementos, periodicidad_revision = r
		if periodicidad_revision == 'M':
			parte['PT_PERIODICIDAD'] = 'TRIMESTRAL'
		else:
			parte['PT_PERIODICIDAD'] = 'ANUAL'

		# r = open('c:/users/jonathan/desktop/data_parte.txt', 'r').read()
		# dc_parte, parte, checks, tecnicos, observaciones = eval(r)
		checks_sin_normativa = []
		numero_norma = 1
		numero_capitulo = 1

		for clave in checks.keys():
			for i in range(len(checks[clave]['BOLEANOS'])):
				si, na, no = '', '', ''
				if checks[clave]['BOLEANOS'][i][4] > 0:
					si, na, no = '', '', 'X'
				elif checks[clave]['BOLEANOS'][i][3] > 0:
					si, na, no = '', 'X', ''
				elif checks[clave]['BOLEANOS'][i][2] > 0:
					si, na, no = 'X', '', ''
				checks[clave]['BOLEANOS'][i][2] = si
				checks[clave]['BOLEANOS'][i][3] = na
				checks[clave]['BOLEANOS'][i][4] = no

			if clave[0] == 0:
				try:
					checks_sin_normativa = copia_rg(checks[clave])
					del checks[clave]
				except:
					pass
				continue
		##

		# Se crea un documento en blanco
		f = cd_parte + '.docx'
		if True:
			f = cd_parte + Fecha('hms').replace(':', '') + '.docx'

		doc_word = document.Document(path_temp, f)
		doc_word.empty_document()
		# doc_word._debug = True

		# Body 1- Portada
		body = doc_word.get_body()
		section = body.get_active_section()
		# Modifico los márgenes de la página para hacerlo mas estrecho
		section.SetMargins(section_margins)
		# Header
		header = doc_word.get_DefaultHeader()
		Header(header, doc_word, idioma, _path_i, _path_d)
		# footer
		Footer(doc_word, idioma, parte, _path_s)

		if idioma['PTCI_TITULO1']:
			titulo = '%d. %s' % (numero_capitulo, merge_vars(idioma['PTCI_TITULO1'], parte))
			numero_capitulo += 1

		p_titulo = body.add_paragraph(titulo)
		FormateaTitulo(idioma, p_titulo)

		lista_checks = checks.keys()
		lista_checks.sort()
		# Se renumeran las preguntas
		for ln in lista_checks:
			if ln[0] == numero_norma and ln[1] == numero_capitulo:
				titulo_elemento = str(numero_capitulo) + '. ' + ln[3]
				dc_checks = copia_rg(checks[ln])

		numero_norma, numero_capitulo = Portada(body, idioma, parte, numero_norma, numero_capitulo, section_margins)

		# Body 2- Elementos

		change_header = False
		_nor = ''
		nn = 0
		cn = 0
		er = []
		for ln in lista_checks:
			# Cada grupo de elementos empezará en una nueva sección y en una nueva página
			n_norma, n_capitulo = ln
			if n_norma == 1:
				continue
			cd_check_, titulo_norma, titulo_elemento, texto_antes, texto_despues = checks[ln]['DATA']
			sect = body.add_section(margin_rigth=953, margin_left=953, margin_footer=400, orient='')
			if change_header:
				h = doc_word.new_header(sect)
				Header(h, doc_word, idioma, _path_i, _path_d)
				change_header = False

			if not cn or cn != n_norma:
				_nor = str(numero_norma) + '. ' + titulo_norma
				nn = numero_norma
				cn = n_norma
				numero_norma += 1
				n_capitulo = 1
				paragraph_elemento = body.add_paragraph(_nor)
				FormateaTitulo(idioma, paragraph_elemento)

			paragraph_1 = body.add_paragraph('%d.%d. %s' % (nn, n_capitulo, titulo_elemento))
			FormateaCapitulo(idioma, paragraph_1)

			if texto_antes:
				rg_txt = lee_dc(lee_dc, gpx, 'fcartas', texto_antes)
				if rg_txt == 1:
					error(cl, "No existe el texto '%s'" % texto_antes)
				txt_antes = rg_txt['FA_TXT']
				#-body.add_rtf(txt_antes)

			boolean_data = checks[ln].get('BOLEANOS', [])
			if boolean_data:
				for i in range(len(boolean_data)):
					boolean_data[i][0] = "%d.%d.%d" % (nn, numero_capitulo, i + 1)
					if '\n' in boolean_data[i][0]:
						boolean_data[i][0] = boolean_data[i][0].split('\n')
				# #$>boolean_data
				encabezado = body.add_table(boolean_data,
				                            idioma['PTCI_TBOO'],
				                            horizontal_alignment=['r', 'l', 'c', 'c', 'c'],
				                            column_width=columnas_checks,
				                            borders=borders_checks)
				FormateaTablaPrincipal(idioma, encabezado, color_primario, color_secundario)

			body.add_paragraph('')

			other_data = checks[ln].get('OTROS', [])
			if other_data:
				for i in range(len(other_data)):
					titulo, lineas = other_data[i]
					p_od = body.add_paragraph(titulo)
					FormateaElemento(idioma, p_od)
					p_od.get_properties().set_keep_next(True)

					for j in range(len(lineas)):
						lineas[j][0] = "%d.%d.%d" % (nn, numero_capitulo, j + 1)
						if '\n' in lineas[j][0]:
							lineas[j][0] = lineas[j][0].split('\n')
					pie = body.add_table(lineas,
					                     idioma['PTCI_TNOR'],
					                     horizontal_alignment=['r', 'l', 'l'],
					                     column_width=columnas_others,
					                     borders=borders_checks)
					FormateaTablaPrincipal(idioma, pie, color_primario, color_secundario)

			n_capitulo += 1

			body.add_paragraph('')
			numero_capitulo += 1

			if not dc_observaciones.get(ln, []):
				observaciones = ['']
			else:
				observaciones = [''] * len(dc_observaciones[ln])
			tabla_obs = body.add_table(
				observaciones,
				[idioma['PTCI_OBS']],
				horizontal_alignment=['j'],
				column_width=['100%'],
				borders=borders_obs
			)
			for i in range(len(dc_observaciones.get(ln, []))):

				# tabla_obs.get_row(i+1).get_cell(0).elements=[]
				if dc_observaciones[ln][i].startswith('{\\rtf'):
					pass
					#-tabla_obs.get_row(i + 1).get_cell(0).add_rtf(dc_observaciones[ln][i])
				else:
					tabla_obs.get_row(i + 1).get_cell(0).add_paragraph(dc_observaciones[ln][i])

			FormateaTablaPrincipal(idioma, tabla_obs, color_primario, color_secundario)

			if texto_despues:
				body.add_paragraph('')
				rg_txt = lee_dc(lee_dc, gpx, 'fcartas', texto_despues)
				if rg_txt == 1:
					error(cl, "No existe el texto '%s'" % texto_despues)
				txt_despues = rg_txt['FA_TXT']
				#-body.add_rtf(txt_despues)

			#firma_sello(doc_word, body, _path_s, parte, idioma)

			tabla_resumen = checks[ln].get('RESUMEN', {})
			if tabla_resumen.get('lineas', []):
				imprimir_horizontal = tabla_resumen['horizontal']
				orient = ''
				ml = 953
				if imprimir_horizontal:
					orient = 'landscape'
					ml = 1253
				body.add_section(margin_rigth=953, margin_left=ml, margin_footer=400, orient=orient)
				new_section = body.get_active_section()
				if imprimir_horizontal:
					h = doc_word.new_header(new_section)
					Header(h, doc_word, idioma, _path_i, _path_d, horizontal=True)
					change_header = True

				v = new_section.get_width() - new_section.get_margin_rigth() - new_section.get_margin_left()

				if tabla_resumen.get('texto', ''):
					#-body.add_rtf(tabla_resumen['texto'])
					pass
				titulo_tabla = tabla_resumen['titulos']
				anchos_tabla = tabla_resumen['anchos']
				for i in range(len(anchos_tabla)):
					anchos_tabla[i] = int(v * (Num(anchos_tabla[i].replace('%', '')) / 100.))

				h_align_tabla = tabla_resumen['h_align']
				lineas_tabla = tabla_resumen['lineas']

				tabla_res = body.add_table(lineas_tabla, titulo_tabla, column_width=anchos_tabla,
				                           borders=borders_checks)
				FormateaTablaPrincipal(idioma, tabla_res, color_primario, color_secundario)

		doc_word.set_variables({})
		doc_word.save()

		'''file_ = open(path_temp + f, 'rb').read()
		documentos_generados.append(file_)
		rg_certificado = rg_vacio(gpx[1], 'partes_certificado')
		rg_certificado < PTC_NPAR > = cd_parte
		rg_certificado < PTC_DOC > = file_
		serie_cer = parte['PT_SERC']['IDX']
		ser_cert_complete = Serie(serie_cer, parte['PT_FECR'])
		if ser_cert_complete not in u_libres.keys():
			u_libres[ser_cert_complete] = u_libre(gpx, 'partes_certificado', ser_cert_complete)
		idx_cert = u_libres[ser_cert_complete]
		rgparte = lee_dc(None, gpx, 'partes', cd_parte, rels='')
		rgparte['PT_NUMCERT'] = idx_cert
		# p_actu(cl, gpx, 'partes', cd_parte, rgparte, a_graba='', log='')
		u_libres[ser_cert_complete] = Busca_Prox(u_libres[ser_cert_complete])'''
		# p_actu(cl, gpx, 'partes_certificado', idx_cert, rg_certificado, a_graba='', log='')
		#del file_

		os.system('start ' + path_temp + f)
	return documentos_generados

if __name__ == '__main__':
	Abre_Aplicacion('sat')
	Abre_Empresa(gpx[0], gpx[1], gpx[2])
	CertificadoSAT(['0000004555'], {})


from collections import namedtuple, defaultdict
from itertools import combinations, product
from math import sqrt
from typing import List

INPUTTEST = 'inputtest.txt'
INPUTREAL = 'input.txt'

def getLines(fileName):
    file = open(fileName,'r')
    lines = file.read().splitlines()
    file.close()
    return lines

class Point3(namedtuple('Point', 'x y z')):
    def __repr__(self):
        return f'{self.x},{self.y},{self.z}'

# performed x y z rotations in a loop and stored in a set
rotations = [([2, 0, 1], [-1, -1, 1]), ([0, 1, 2], [1, -1, -1]), ([2, 1, 0], [-1, -1, -1]), ([2, 1, 0], [1, -1, 1]),
            ([0, 2, 1], [-1, -1, -1]), ([1, 2, 0], [1, -1, -1]), ([1, 0, 2], [-1, -1, -1]), ([1, 2, 0], [1, 1, 1]),
            ([0, 2, 1], [-1, 1, 1]), ([0, 1, 2], [-1, 1, -1]), ([0, 2, 1], [1, -1, 1]), ([2, 0, 1], [-1, 1, -1]),
            ([1, 0, 2], [1, 1, -1]), ([2, 1, 0], [1, 1, -1]), ([2, 0, 1], [1, 1, 1]), ([2, 1, 0], [-1, 1, 1]),
            ([0, 1, 2], [1, 1, 1]), ([1, 0, 2], [1, -1, 1]), ([1, 0, 2], [-1, 1, 1]), ([0, 1, 2], [-1, -1, 1]),
            ([1, 2, 0], [-1, 1, -1]), ([1, 2, 0], [-1, -1, 1]), ([0, 2, 1], [1, 1, -1]), ([2, 0, 1], [1, -1, -1])]

def formatInput(lines):
    scanners = {}
    scannerCurrent = []
    i = 0
    lines.append("")
    for line in filter(lambda x: not x.startswith("---"), lines):
        if len(line) == 0 and len(scannerCurrent) > 0:
            scanners[i] = scannerCurrent
            scannerCurrent = []
            i += 1
        else:
            scannerCurrent.append([int(t) for t in line.split(",")])
    return scanners

def partOne(scanners):
    intersects = getIntersects(scanners)
    mapping_dict = createMappings(intersects, scanners)
    beacons = set(toPoint(p) for p in scanners[0])
    used_mappings = set()
    transformed_scanners = {0}
    scanner_origins = [[0, 0, 0]]
    while len(transformed_scanners) < len(scanners):
        queue = [k for k in mapping_dict.keys() if k[0] in transformed_scanners and k[1] not in transformed_scanners]
        while len(queue) > 0:
            el = queue.pop()
            if el[1] in transformed_scanners:
                continue
            p_transpose = list(zip(*scanners[el[1]]))
            centroid = list(zip([0, 0, 0]))  # origin relative to scanner itself is 0, 0, 0
            use_mapping = el
            while True:
                centroid = transform(centroid, *mapping_dict[use_mapping])
                p_transpose = transform(p_transpose, *mapping_dict[use_mapping])
                new_points = set(toPoint(p) for p in zip(*p_transpose))
                if use_mapping[0] == 0:
                    break
                for mapping in used_mappings:
                    if mapping[1] == use_mapping[0]:
                        use_mapping = mapping
                        break
            scanner_origins.append([centroid[0][0], centroid[1][0], centroid[2][0]])
            transformed_scanners.add(el[1])
            beacons.update(new_points)
            used_mappings.add(el)
    return len(beacons), scanner_origins

def partTwo(scanner_origins):
    return max(sum(map(lambda x: abs(x[0] - x[1]), zip(*p))) for p in combinations(scanner_origins, 2))

def createMappings(intersects, scanners):
    mappingDict = {}
    for i in intersects:
        pointToDistA = defaultdict(set)
        for p in combinations(scanners[i[0]], 2):
            dist = euclidDist(*p)
            pointToDistA[toPoint(p[0])].add(dist)
            pointToDistA[toPoint(p[1])].add(dist)
        pointToDistB = defaultdict(set)
        for p in combinations(scanners[i[1]], 2):
            dist = euclidDist(*p)
            pointToDistB[toPoint(p[0])].add(dist)
            pointToDistB[toPoint(p[1])].add(dist)
        pointsA = []
        pointsB = []
        for p in product(pointToDistA.keys(), pointToDistB.keys()):
            intersect = pointToDistA[p[0]].intersection(pointToDistB[p[1]])
            if len(intersect) >= 11:  # 12 common beacons 1 src and 11 dst for distance
                pointsA.append(pointToList(p[0]))
                pointsB.append(pointToList(p[1]))
        mappingDict[i] = mapScannerAToB(pointsA, pointsB)
    return mappingDict

def mapScannerAToB(pointsA, pointsB):
    aTranspose = list(zip(*pointsA))
    bTranspose = list(zip(*pointsB))
    for perms, signs in rotations:
        rotated = rotate(bTranspose, perms, signs)
        offset = []
        for p in zip(rotated, aTranspose):
            points = set([x[1] - x[0] for x in zip(p[0], p[1])])
            if len(points) == 1:
                offset.append(points.pop())
            if len(offset) == 3:
                return offset, perms, signs
    return None

def transform(itemToTransform, centerOfTarget, transformPerm, transformSign):
    rotated = rotate(itemToTransform, transformPerm, transformSign)
    return [list(map(lambda x: centerOfTarget[i] + x, p)) for i, p in enumerate(rotated)]

def getIntersects(scanners):
    intersections = []
    distDict = {i: set(euclidDist(*p) for p in combinations(scanners[i], 2)) for i in scanners.keys()}
    for i in combinations(range(len(scanners)), 2):
        if len(distDict[i[0]].intersection(distDict[i[1]])) >= 66:
            intersections.append(i)
            intersections.append((i[1], i[0]))
    return intersections

def rotate(point, perms, signs):
    return map(lambda n: n * signs[0], point[perms[0]]), \
           map(lambda n: n * signs[1], point[perms[1]]), \
           map(lambda n: n * signs[2], point[perms[2]])

def euclidDist(a, b):
    return sqrt(sum(map(lambda x: pow(x[0] - x[1], 2), zip(a, b))))

def toPoint(plist):
    if len(plist) == 3:
        return Point3(plist[0], plist[1], plist[2])
    else:
        raise Exception("Can't cover to point")

def pointToList(p):
    return [p.x, p.y, p.z]

lines = getLines(INPUTREAL)
scanners = formatInput(lines)
part1, centroids = partOne(scanners)
'''Part One'''
print(part1)
'''Part Two'''
print(partTwo(centroids))


from functools import update_wrapper
import logging

from .action import FunctionAction
from .request import Request
from .traject import Traject
from .config import Configurable
from .settings import SettingSectionContainer
from .converter import ConverterRegistry
from .predicate import PredicateRegistry
from .tween import TweenRegistry
from . import generic
from reg import Registry as RegRegistry, CachingKeyLookup
import venusian
from . import compat
from .compat import with_metaclass
from .implicit import set_implicit
from .mount import MountRegistry
from .reify import reify
from .template import TemplateEngineRegistry

COMPONENT_CACHE_SIZE = 5000
ALL_CACHE_SIZE = 5000
FALLBACK_CACHE_SIZE = 5000

class Registry(Configurable, RegRegistry, MountRegistry, PredicateRegistry,
               ConverterRegistry, TweenRegistry, TemplateEngineRegistry):
    """A registry holding an application's configuration.
    """
    app = None  # app this registry belongs to. set later during scanning

    def __init__(self, name, bases, testing_config):
        self.name = name
        bases = [base.registry for base in bases if hasattr(base, 'registry')]
        RegRegistry.__init__(self)
        MountRegistry.__init__(self)
        PredicateRegistry.__init__(self)
        Configurable.__init__(self, bases, testing_config)
        ConverterRegistry.__init__(self)
        TweenRegistry.__init__(self)
        TemplateEngineRegistry.__init__(self)
        self.settings = SettingSectionContainer()
        self.clear()

    def actions(self):
        yield FunctionAction(self, generic.settings), lambda: self.settings

    def clear(self):
        """Clear all registrations in this application.
        """
        RegRegistry.clear(self)
        MountRegistry.clear(self)
        PredicateRegistry.clear(self)
        Configurable.clear(self)
        ConverterRegistry.clear(self)
        TweenRegistry.clear(self)
        TemplateEngineRegistry.clear(self)
        self.traject = Traject()

    @reify
    def lookup(self):
        return CachingKeyLookup(
            self,
            COMPONENT_CACHE_SIZE,
            ALL_CACHE_SIZE,
            FALLBACK_CACHE_SIZE).lookup()

def callback(scanner, name, obj):
    obj.registry.app = obj
    scanner.config.configurable(obj.registry)

class AppMeta(type):
    def __new__(cls, name, bases, d):
        testing_config = d.get('testing_config')
        d['registry'] = Registry(name, bases, testing_config)
        result = super(AppMeta, cls).__new__(cls, name, bases, d)
        venusian.attach(result, callback)
        return result

class App(with_metaclass(AppMeta)):
    """A Morepath-based application object.

    You subclass App to create a morepath application class. You can
    then configure this class using Morepath decorator directives.

    An application can extend one or more other applications, if
    desired, by subclassing them. By subclassing App itself, you get
    the base configuration of the Morepath framework itself.

    Conflicting configuration within an app is automatically
    rejected. An subclass app cannot conflict with the apps it is
    subclassing however; instead configuration is overridden.

    You can turn your app class into a WSGI application by instantiating
    it. You can then call it with the ``environ`` and ``start_response``
    arguments.
    """
    testing_config = None
    parent = None
    """The parent in which this app was mounted."""

    request_class = Request
    """The class of the Request to create. Must be a subclass of
    :class:`morepath.Request`.
    """

    def __init__(self):
        pass

    @reify
    def lookup(self):
        """Get the :class:`reg.Lookup` for this application.

        :returns: a :class:`reg.Lookup` instance.
        """
        return self.registry.lookup

    def set_implicit(self):
        set_implicit(self.lookup)

    @reify
    def traject(self):
        return self.registry.traject

    def request(self, environ):
        """Create a :class:`Request` given WSGI environment for this app.

        :param environ: WSGI environment
        :returns: :class:`morepath.Request` instance
        """
        return self.request_class(environ, self)

    def __call__(self, environ, start_response):
        """This app as a WSGI application.
        """
        request = self.request(environ)
        response = self.publish(request)
        return response(environ, start_response)

    def ancestors(self):
        """Return iterable of all ancestors of this app.

        Includes this app itself as the first ancestor, all the way
        up to the root app in the mount chain.
        """
        app = self
        while app is not None:
            yield app
            app = app.parent

    @reify
    def root(self):
        """The root application.
        """
        return list(self.ancestors())[-1]

    def child(self, app, **variables):
        """Get app mounted in this app.

        Either give it an instance of the app class as the first
        parameter, or the app class itself (or name under which it was
        mounted) as the first parameter and as ``variables`` the
        parameters that go to its ``mount`` function.

        Returns the mounted application object, with its ``parent``
        attribute set to this app object, or ``None`` if this
        application cannot be mounted in this one.
        """
        if isinstance(app, App):
            result = app
            # XXX assert that variables is empty

            # XXX do we need to deal with subclasses of apps?
            if app.__class__ not in self.registry.mounted:
                return None
        else:
            if isinstance(app, compat.string_types):
                factory = self.registry.named_mounted.get(app)
            else:
                factory = self.registry.mounted.get(app)
            if factory is None:
                return None
            result = factory(**variables)
        result.parent = self
        return result

    def sibling(self, app, **variables):
        """Get app mounted next to this app.

        Either give it an instance of the app class as the first
        parameter, or the app class itself (or name under which it was
        mounted) as the first parameter and as ``variables`` the
        parameters that go to its ``mount`` function.

        Returns the mounted application object, with its ``parent``
        attribute set to the same parent as this one, or ``None`` if such
        a sibling application does not exist.
        """
        parent = self.parent
        if parent is None:
            return None
        return parent.child(app, **variables)

    @reify
    def publish(self):
        # XXX import cycles...
        from .publish import publish
        result = publish
        for tween_factory in reversed(self.registry.sorted_tween_factories()):
            result = tween_factory(self, result)
        return result

    @classmethod
    def directive(cls, name):
        """Decorator to register a new directive with this application class.

        You use this as a class decorator for a :class:`morepath.Directive`
        subclass::

           @App.directive('my_directive')
           class FooDirective(morepath.Directive):
               ...

        This needs to be executed *before* the directive is being used
        and thus might introduce import dependency issues unlike
        normal Morepath configuration, so beware! An easy way to make
        sure that all directives are installed before you use them is
        to make sure you define them in the same module as where you
        define the application class that has them.
        """
        return DirectiveDirective(cls, name)

    @classmethod
    def dotted_name(cls):
        return '%s.%s' % (cls.__module__, cls.__name__)

class DirectiveDirective(object):
    def __init__(self, cls, name):
        self.cls = cls
        self.name = name

    def __call__(self, directive):
        directive_name = self.name

        def method(self, *args, **kw):
            result = directive(self, *args, **kw)
            result.directive_name = directive_name
            result.argument_info = args, kw
            result.logger = logging.getLogger('morepath.directive.%s' %
                                              directive_name)
            return result

        # this is to help morepath.sphinxext to do the right thing
        method.actual_directive = directive
        update_wrapper(method, directive.__init__)
        setattr(self.cls, self.name, classmethod(method))
        return directive


import sys
import xbmc, xbmcgui
import torrentitem

#enable localization
getLS   = sys.modules[ "__main__" ].__language__
__cwd__ = sys.modules[ "__main__" ].__cwd__

# Actions ids
ACTION_PARENT_DIR = 9
ACTION_PREVIOUS_MENU = 10
ACTION_MOVE_LEFT = 1
ACTION_MOVE_RIGHT = 2
ACTION_MOVE_UP = 3
ACTION_MOVE_DOWN = 4
ACTION_NAV_BACK = 92

def log(txt):
  xbmc.log(msg = "[SCRIPT] 'torrentrss.trackergui': %s" % (txt, ), level=xbmc.LOGDEBUG)

##########################################
class TrackerGUI(xbmcgui.WindowXML):
  "GUI for tracker search results listing"

  # Declare this to handle events before control init
  control_list_id=-1

  def __init__(self, *args, **kwargs):
    # Init window
    xbmcgui.WindowXML.__init__(self, *args, **kwargs)
    self.trackerMgr = kwargs['trackerMgr']
    self.filterlist = []
    self.loaded = 0
    self.results = []
    self.busyWindow = xbmcgui.WindowXMLDialog("DialogBusy.xml", __cwd__, "default")

  def __del__(self):
    "Destructor"
    pass

  def onInit(self):
    "Secondary constructor called after window xml is loaded"

    # Init gui
    self.defineControls()

    if (self.loaded == 0):
      # Feed name/id link list
      self.feedmap = {}
      self.feedmap['41010'] = getLS(50102)
      self.feedmap['41011'] = getLS(55101)
      self.feedmap['41012'] = getLS(55102)
      self.getControl(self.control_leftFrame_liststart_id).setSelected(True)
      self.filterlist.append(self.feedmap['41010'])

    # Clear gui list
    self.refreshListItem(self.filterlist)
    self.loaded = 1

  def defineControls(self):
    "Initialize controls and link to gui widgets"
    # actions
    self.action_cancel_dialog = (ACTION_PARENT_DIR, ACTION_PREVIOUS_MENU, ACTION_NAV_BACK)
    self.action_up_down = (ACTION_MOVE_UP, ACTION_MOVE_DOWN)

    # Control ids
    self.control_list_id =              504
    self.control_rightFrame_title_id =  40001
    self.control_rightFrame_info_id =   40002
    self.control_rightFrame_list_id =   40010
    self.control_rightFrame_imgbox_id = 40005
    self.control_leftFrame_sortorder_id = 4
    self.control_leftFrame_filter_id =  19
    self.control_leftFrame_refresh_id = 41004
    self.control_leftFrame_sortby_id = 41005
    self.control_leftFrame_liststart_id = 41010
    self.control_leftFrame_listend_id = 41012

    # Controls
    self.list = self.getControl(self.control_list_id)
    self.rightFrame_title = self.getControl(self.control_rightFrame_title_id)
    self.rightFrame_info = self.getControl(self.control_rightFrame_info_id)
    self.rightFrame_list = self.getControl(self.control_rightFrame_list_id)
    self.rightFrame_imgbox = self.getControl(self.control_rightFrame_imgbox_id)
    self.leftFrame_refresh = self.getControl(self.control_leftFrame_refresh_id)
    self.leftFrame_sortby = self.getControl(self.control_leftFrame_sortby_id)
    #self.leftFrame_sortorder = self.getControl(self.control_leftFrame_sortorder_id)
    #self.leftFrame_filter = self.getControl(self.control_leftFrame_filter_id)

  def showBusyWindow(self):
    " Display a 'working' window"
    self.busyWindow = xbmcgui.WindowXMLDialog("DialogBusy.xml", __cwd__, "default")
    self.busyWindow.show()

  def closeBusyWindow(self):
    " Close the 'working' window"
    self.busyWindow.close()

  def doModalSearch(self, keywords):

    # Show busy dialog
    self.showBusyWindow()

    # Run a sequential search on all trackers
    self.results = self.trackerMgr.search(keywords)

    # Close busy dialog
    self.closeBusyWindow()

    # Display results or error
    self.selectedlink = None
    if (len(self.results) > 0): self.doModal()
    else: xbmcgui.Dialog().ok(getLS(56001), getLS(56002), getLS(56003))
    return self.selectedlink

  def refreshListItem(self, filterfeed=None):
    "Refresh GUI content"
    # Update feed list
    self.list.reset()
    i=0
    alltxt=getLS(50102)
    for entry in self.results:
      #log(entry)
      if (filterfeed == None) or (alltxt in filterfeed) or (entry.tracker in filterfeed):
        item = xbmcgui.ListItem(entry.seeds, entry.title)
        item.setProperty('size', entry.size)
        item.setProperty('peers', entry.peers)
        item.setProperty('vip', 'p'+entry.vip)
        item.setProperty('pos', str(i))
        self.list.addItem(item)
      i=i+1
    self.list.selectItem(0)
    self.onSelected(self.list.getSelectedItem())

  def clear(self):
    "Clear the all feed items after user confirmation"
    self.list.reset()
    self.trackerMgr.reset()

  def onClick(self, controlId):
    "React on mouse clicks/select key"
    if controlId == self.control_list_id:
      item = self.list.getSelectedItem()
      torrent = self.results[int(item.getProperty('pos'))]
      self.selectedlink = None
      if (xbmcgui.Dialog().yesno(torrent.title, getLS(56011))):
        if (len(torrent.magnet) > 0): self.selectedlink = torrent.magnet
        elif (len(torrent.torrent) > 0): self.selectedlink = torrent.torrent
        self.close()
    elif controlId == self.control_leftFrame_refresh_id:
      self.showBusyWindow()
      self.list.reset()
      self.clearRightFrame()
      self.results = self.trackerMgr.search(self.trackerMgr.getLastKeywords())
      self.refreshListItem(self.filterlist)
      self.closeBusyWindow()
    elif controlId >= self.control_leftFrame_liststart_id and controlId <= self.control_leftFrame_listend_id:
      item = self.getControl(controlId)
      label = self.feedmap[str(controlId)]
      if item.isSelected(): self.filterlist.append(label)
      else: self.filterlist.remove(label)
      self.refreshListItem(self.filterlist)

  def onAction(self, action):
    "React on actions"
    if (action in self.action_cancel_dialog):
      self.close()
    elif (self.getFocusId() == self.control_list_id) and (action in self.action_up_down):
      item = self.list.getSelectedItem()
      self.onSelected(item)

  def onFocus(self, controlId):
    "React on focus"
    if controlId == self.control_list_id:
      item = self.list.getSelectedItem()
      self.onSelected(item)

  def onSelected(self, item):
    "Action when a new list item is selected (custom)"
    if (item):
      self.updateRightFrame(item)

  def updateRightFrame(self, item):
    "Update the right frame of the gui with given feed info"
    self.rightFrame_list.reset()
    srcfeed = self.results[int(item.getProperty('pos'))]
    self.rightFrame_info.setLabel(srcfeed.title)
    if srcfeed.trackerlogo != None: self.rightFrame_imgbox.setImage(srcfeed.trackerlogo)
    else: self.rightFrame_imgbox.setImage("Fanart_Fallback_Small.jpg")

    self.rightFrame_list.addItem(xbmcgui.ListItem(getLS(56202), srcfeed.seeds))
    self.rightFrame_list.addItem(xbmcgui.ListItem(getLS(56203), srcfeed.peers))
    self.rightFrame_list.addItem(xbmcgui.ListItem(getLS(56204), srcfeed.size))
    self.rightFrame_list.addItem(xbmcgui.ListItem(getLS(56205), srcfeed.date))
    self.rightFrame_list.addItem(xbmcgui.ListItem(getLS(56206), srcfeed.srcurl))
    if (srcfeed.vip == "true"): self.rightFrame_list.addItem(xbmcgui.ListItem(getLS(56207), "Yes"))
    else: self.rightFrame_list.addItem(xbmcgui.ListItem(getLS(56207), "No"))
    if (len(srcfeed.magnet) >0): self.rightFrame_list.addItem(xbmcgui.ListItem(getLS(56208), "Yes"))
    else: self.rightFrame_list.addItem(xbmcgui.ListItem(getLS(56208), "No"))
    if (len(srcfeed.torrent) >0): self.rightFrame_list.addItem(xbmcgui.ListItem(getLS(56209), "Yes"))
    else: self.rightFrame_list.addItem(xbmcgui.ListItem(getLS(56209), "No"))

  def clearRightFrame(self):
    "Clear right frame with default values"
    self.rightFrame_info.setLabel(xbmc.getLocalizedString(416))
    self.rightFrame_list.reset()
    self.rightFrame_imgbox.setImage("Fanart_Fallback_Small.jpg")


import os
import sys
import json
import unittest
import numpy as np

import luigi
import z5py
import cluster_tools.utils.volume_utils as vu
from sklearn.metrics import adjusted_rand_score
from elf.segmentation.mutex_watershed import mutex_watershed
from elf.segmentation.watershed import apply_size_filter

try:
    from ..base import BaseTest
except Exception:
    sys.path.append(os.path.join(os.path.split(__file__)[0], ".."))
    from base import BaseTest

class TestMws(BaseTest):
    input_key = "volumes/affinities"
    output_key = "data"
    offsets = [[-1, 0, 0], [0, -1, 0], [0, 0, -1],
               [-2, 0, 0], [0, -3, 0], [0, 0, -3],
               [-3, 0, 0], [0, -9, 0], [0, 0, -9],
               [-4, 0, 0], [0, -27, 0], [0, 0, -27]]
    strides = [4, 12, 12]

    def _check_result(self, size_filter):
        # load affs and compare
        with z5py.File(self.input_path, "r") as f:
            ds = f[self.input_key]
            ds.n_threads = 4
            affs = vu.normalize(ds[:])
            shape = affs.shape[1:]

        with z5py.File(self.output_path, "r") as f:
            res = f[self.output_key][:]
        self.assertEqual(res.shape, shape)

        exp = mutex_watershed(affs, self.offsets, self.strides)
        if size_filter > 0:
            exp, _ = apply_size_filter(exp.astype("uint32"), np.max(affs[:3], axis=0), size_filter)
        score = adjusted_rand_score(exp.ravel(), res.ravel())
        expected_score = 0.1
        self.assertLess(1. - score, expected_score)

    def test_mws(self):
        from cluster_tools.mutex_watershed import MwsWorkflow

        config = MwsWorkflow.get_config()["mws_blocks"]
        config["strides"] = self.strides
        size_filter = config["size_filter"]
        with open(os.path.join(self.config_folder, "mws_blocks.config"), "w") as f:
            json.dump(config, f)

        task = MwsWorkflow(tmp_folder=self.tmp_folder, config_dir=self.config_folder,
                           max_jobs=self.max_jobs, target=self.target,
                           input_path=self.input_path, input_key=self.input_key,
                           output_path=self.output_path, output_key=self.output_key,
                           offsets=self.offsets)
        ret = luigi.build([task], local_scheduler=True)
        self.assertTrue(ret)
        self._check_result(size_filter)

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


from scipy.io import loadmat
import numpy as np
import xlrd as x
import pandas as pd

def run(file, delimiter):
    file_name = file["file"]

    file_type_list = file_name.split(".")
    file_type = file_type_list[len(file_type_list) - 1]

    if file_type == 'mat':
        key = file["key"]
        array = read_mat(file_name, key)
    elif file_type == 'csv':
        array = read_csv(file_name, delimiter)
    elif file_type == 'txt':
        array = read_csv(file_name, delimiter)
    elif file_type == 'xlsx':
        array = read_xls(file_name)
    elif file_type == 'xls':
        array = read_xls(file_name)
    else:
        array = np.array([[]])

    return {"array": array.tolist()}

def read_mat(file, matKey):
    dict = loadmat(file)
    return dict[matKey]

def read_csv(file, delimiter):
    array = np.loadtxt(file, delimiter=delimiter)
    return np.array(array, dtype=float)

def read_xls(file):
    array = pd.read_excel(file, sheet_name=0, header=None)
    return np.array(array, dtype=float)


import cv2
import os

cam = cv2.VideoCapture("video.avi")

values = []

def discrimator(frame):
    return frame[0][0][1] != 253

# Read each frame. Use discriminator on each frame to output a zero or one.
while True:
    ret, f = cam.read()
    if not ret:
        break
    values.append(
        discrimator(f)
    )

ones_and_zeroes = "".join(str(int(x)) for x in values)
byte_string = int(ones_and_zeroes, 2).to_bytes(len(ones_and_zeroes) // 8, byteorder='big')
os.write(1, byte_string)


import matplotlib.pyplot as plt
import pandas as pd

def main():
    # Charger les données à partir du fichier CSV
    data = pd.read_csv("Parcoursup 2023 - Total.csv", delimiter=";")

    # Extraire les colonnes nécessaires
    dates = pd.to_datetime(data["Date"], format="%d/%m") # type: ignore
    en_attente = data[
        "Candidats n'ayant pas encore reçu de proposition ou en attente de place"
    ]

    # Créer les limites des bacs pour l'histogramme en escalier
    x = range(len(dates) + 1)
    y = list(en_attente) + [en_attente.iloc[-1]]  # Candidats en attente

    # Créer le graphique avec la courbe en rouge pour les candidats en attente
    plt.figure(figsize=(8, 6))
    plt.step(x, y, where="post", color="orange", linewidth=2, alpha=0.7)
    plt.xlabel("Date")
    plt.ylabel(
        "Candidats n'ayant pas encore reçu de\nproposition ou en attente de place"
    )
    plt.title(
        "Évolution en fonction du temps du nombre de\ncandidats sans affectation sur Parcoursup en 2023"
    )
    x_ticks = range(0, len(dates), 3)
    x_labels = dates[x_ticks].dt.strftime("%d/%m") # type: ignore
    plt.xticks(x_ticks, x_labels, rotation=45)

    # Ajuster les limites de l'axe x pour supprimer l'espace blanc à gauche
    plt.xlim(0, len(dates) - 1)

    plt.ylim(0, 400000)
    plt.twinx()
    plt.ylim(0, (400000 / 827271) * 100)
    plt.ylabel("Pourcentage en fonction du nombre de candidats")
    plt.tight_layout()
    plt.savefig(
        "Évolution en fonction du temps du nombre de candidats sans affectation sur Parcoursup en 2023.svg"
    )
    print(
        "Le graphique a été enregistré dans le fichier 'Évolution en fonction du temps du nombre de candidats sans affectation sur Parcoursup en 2023.svg'."
    )
    plt.close()

if __name__ == "__main__":
    main()


from Player import Player

# Asks user to input number of players, and creates as many player objects
def initialisePlayers(players):

    noOfPlayers = int(input("How many players are there? "))
    print()

    try:
        if noOfPlayers < 2:
            print("That's too few players! Please enter a number between 2-6.")
            initialisePlayers()
        elif noOfPlayers > 6:
            print("That's too many players! Please enter a number between 2-6.")
            initialisePlayers()
        else:
            # Creating player objects until user input, number of players, is reached
            # Player hand set to null until cards are dealt
            for n in range(1, noOfPlayers + 1):
                p = Player(n, None)
                players.append(p)
    except ValueError:
        print("That's not a number! Please enter a number between 2-6.")
        initialisePlayers()

# Displays active player's hand, and determines playable cards
def displayHand(p, upcard):

    # Temporary list to store playable cards
    playableCards = []

    print("Your cards are:")

    for c in p.hand:

        print(str(c.rank) + " of " + c.suit)

        # If a card matches the upcard in rank or suit, it is a playable card
        if (c.rank == upcard.rank or c.suit == upcard.suit):

            playableCards.append(c)

    return playableCards


from django.contrib.contenttypes.models import ContentType
from django_filters import rest_framework as filters

from music_app.models import Artist, Track, Album
from music_app.apps import MusicAppConfig

_content_types_id = {
    'artist': ContentType.objects.get(app_label=MusicAppConfig.name, model='artist').id,
    'album': ContentType.objects.get(app_label=MusicAppConfig.name, model='album').id,
    'track': ContentType.objects.get(app_label=MusicAppConfig.name, model='track').id,
}

class BaseSpotifyFilterSet(filters.FilterSet):
    name = filters.CharFilter(
        field_name='name',
        lookup_expr='icontains',
        label='Name',
    )
    spotify_id = filters.CharFilter(
        field_name='spotify_id',
        lookup_expr='exact',
        label='Spotify ID',
    )
    spotify_uri = filters.CharFilter(
        field_name='spotify_uri',
        lookup_expr='exact',
        label='Spotify URI',
    )

class ArtistFilterSet(BaseSpotifyFilterSet):
    class Meta:
        model = Artist
        fields = []

class TrackFilterSet(BaseSpotifyFilterSet):
    class Meta:
        model = Track
        fields = []

class AlbumFilterSet(BaseSpotifyFilterSet):
    class Meta:
        model = Album
        fields = []

class CommentFilterSet(filters.FilterSet):
    creator = filters.NumberFilter(
        field_name='creator_id',
        lookup_expr='exact',
        label='Creator ID',
    )
    content_type = filters.ChoiceFilter(
        choices=[
            (_content_types_id['artist'], 'artist'),
            (_content_types_id['album'], 'album'),
            (_content_types_id['track'], 'track')
        ],
        field_name='content_type',
        lookup_expr='exact',
        label='Type of model'
    )


import pytest

from xdlang.structures import XDType, ast
from xdlang.visitors.parser import parse_text, transform_parse_tree

def parse_and_transform_expr(program_text: str):
    parsed = parse_text(program_text, start="expr")
    ast = transform_parse_tree(parse_tree=parsed)
    return ast

@pytest.mark.parametrize(
    "text,type,value",
    [
        ("42", XDType.INT, 42),
        ("17.00", XDType.FLOAT, 17.0),
        ("'Q'", XDType.CHAR, "Q"),
        ("false", XDType.BOOL, False),
        ("true", XDType.BOOL, True),
    ],
)
def test_literal(text, type, value):
    node: ast.LiteralNode = parse_and_transform_expr(text)
    assert isinstance(node, ast.LiteralNode)
    assert node.type == type
    assert node.value == value


import hide
headers = hide.headers
TOKEN = hide.TOKEN
tell_token = hide.tell_token
chat_id = hide.chat_id
import http.client
import mimetypes
import ssl
import json
import time
from time import localtime, strftime
from datetime import datetime
import requests
import json

# mac has some issue with SLL this fixes it
try:
    _create_unverified_https_context = ssl._create_unverified_context
except AttributeError:
    # Legacy Python that doesn't verify HTTPS certificates by default
    pass
else:
    # Handle target environment that doesn't support HTTPS verification
    ssl._create_default_https_context = _create_unverified_https_context

def send_to_telegram(message):
    url = 'https://api.telegram.org/bot'+tell_token+'/sendMessage'
    for i in chat_id:
        data = {'chat_id': i, 'text': message}
        try:
            requests.post(url, data).json()
            print("Message sent to Telegram")
        except:
            print("message did not send")

print("start")
send_to_telegram("Start - The code has started")

time_for_active_6 = 0
time_for_active_7 = 0
while True:
    try:
        conn = http.client.HTTPSConnection("apiv4.olarm.co")
        payload = ''
        conn.request("GET", "/api/v4/devices/2731071d-a487-44e8-bb29-fb9a189f6e72/events?pageLength=40", payload, headers)
        res = conn.getresponse()
        data = res.read()

        my_json = data.decode('utf8').replace("'", '"')
        jdata = json.loads(my_json)
        for i in jdata['data'][::-1]:
            if i['eventNum'] == 6 and i['eventState'] == 'active':
                time_for_active_6 = i['eventTime']

            if i['eventNum'] == 7 and i['eventState'] == 'active':
                time_for_active_7 = i['eventTime']

            if i['eventNum'] == 6 and i['eventState'] == 'closed':
                time_for_active_6 = 0
            if i['eventNum'] == 7 and i['eventState'] == 'closed':
                time_for_active_7 = 0
        # Function to find the diffrence between two dates.
        def time_between(d1, d2):
            d1 = datetime.strptime(d1, "%Y-%m-%d %H:%M:%S")
            d2 = datetime.strptime(d2, "%Y-%m-%d %H:%M:%S")
            #return d2-d1
            return abs((d2 - d1).seconds/60)

        if time_for_active_6 != 0:
            time_from_the_gararge = (time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time_for_active_6/1000)))
            current = ( strftime("%Y-%m-%d %H:%M:%S", localtime() ) )
            elapsed = time_between(time_from_the_gararge, current)
            if  elapsed > 10:
                print("The Gararge (orange car) has been open for longer then ",elapsed , "mins" )
                send_to_telegram("The door (orange car) has been open for " + str(elapsed) + " mins")
                time.sleep(120)

        if time_for_active_7 != 0:
            time_from_the_gararge = (time.strftime('%Y-%m-%d %H:%M:%S', time.localtime(time_for_active_7/1000)))
            current = ( strftime("%Y-%m-%d %H:%M:%S", localtime() ) )
            elapsed = time_between(time_from_the_gararge, current)
            if  elapsed > 10:
                print("the Gararge (blue car) has been open for longer then ",elapsed , "mins" )
                send_to_telegram("The door (blue car) has been open for " + str(elapsed) + " mins")
                time.sleep(120)
        # finaly we wait for 2 mins and then we do the whole process again
        time.sleep(120)
    except:
        print("An error occurred try again")
        try:
            send_to_telegram("ERROR - Somthing went wrong - check the terminal")
        except:
            print("push bullet / telei is not working")
        time.sleep(10)


import shlex

import django_filters
from django.core.exceptions import FieldError
from django.db.models import Q

# The function and Classes in this file are from https://github.com/nexB/scancode.io/blob/main/scanpipe/filters.py

def parse_query_string_to_lookups(query_string, default_lookup_expr, default_field):
    """Parse a query string and convert it into queryset lookups using Q objects."""
    lookups = Q()
    terms = shlex.split(query_string)

    lookup_types = {
        "=": "iexact",
        "^": "istartswith",
        "$": "iendswith",
        "~": "icontains",
        ">": "gt",
        "<": "lt",
    }

    for term in terms:
        lookup_expr = default_lookup_expr
        negated = False

        if ":" in term:
            field_name, search_value = term.split(":", maxsplit=1)
            if field_name.endswith(tuple(lookup_types.keys())):
                lookup_symbol = field_name[-1]
                lookup_expr = lookup_types.get(lookup_symbol)
                field_name = field_name[:-1]

            if field_name.startswith("-"):
                field_name = field_name[1:]
                negated = True

        else:
            search_value = term
            field_name = default_field

        lookups &= Q(**{f"{field_name}__{lookup_expr}": search_value}, _negated=negated)

    return lookups

class QuerySearchFilter(django_filters.CharFilter):
    """Add support for complex query syntax in search filter."""

    def filter(self, qs, value):
        if not value:
            return qs

        lookups = parse_query_string_to_lookups(
            query_string=value,
            default_lookup_expr=self.lookup_expr,
            default_field=self.field_name,
        )

        try:
            return qs.filter(lookups)
        except FieldError:
            return qs.none()

class PackageSearchFilter(QuerySearchFilter):
    def filter(self, qs, value):
        if not value:
            return qs

        if value.startswith("pkg:"):
            return qs.for_package_url(value)

        if "://" not in value and ":" in value:
            return super().filter(qs, value)

        search_fields = ["type", "namespace", "name", "version", "download_url"]
        lookups = Q()
        for field_names in search_fields:
            lookups |= Q(**{f"{field_names}__{self.lookup_expr}": value})

        return qs.filter(lookups)


#!/usr/bin/env python

import rospy

from std_msgs.msg import Bool
from audio_common_msgs.msg import AudioData

import os
import argparse

import pyaudio
import wave
import datetime

class AudioCapture:

    def __init__(
            self,
            is_record_topic,
            audio_data_topic,
            num_channels,
            sample_rate,
            chunk_size,
            format_size,
            file_name_prefix='',
            out_file_directory='audio',
    ):

        rospy.init_node('audio_recorder', anonymous=True)

        self._is_record_subscriber = rospy.Subscriber(is_record_topic, Bool, self._record_callback, queue_size=1)
        self._audio_data_topic = rospy.Subscriber(audio_data_topic, AudioData, self._audio_data_callback, queue_size=1)

        self._num_channels = num_channels
        self._sample_rate = sample_rate
        self._chunk_size = chunk_size
        self._format_size = format_size
        self._file_name_prefix = file_name_prefix
        if len(self._file_name_prefix) > 0:
            self._file_name_prefix += '_'
        rospy.loginfo(self._file_name_prefix)
        self._out_directory = out_file_directory

        self._start_record_datetime = None
        self._audio_data = None

    def _record_callback(self, data):

        is_record = data.data
        self._record(is_record)

    def _record(self, is_record):

        if is_record:
            if self._is_recording():
                rospy.logerr("Already recording audio")
            else:
                rospy.loginfo("Starting to record audio")
                self._audio_data = []
                self._start_record_datetime = datetime.datetime.now()
        else:
            if self._is_recording():

                rospy.loginfo("Stopped recording audio")
                self._save_recording(self._audio_data)

                # Clean up
                self._audio_data = None
                self._start_record_datetime = None
            else:
                rospy.logerr("No recording in progress")

    def _audio_data_callback(self, data):
        if self._is_recording():
            self._audio_data.append(data.data)

    def _is_recording(self):
        return self._start_record_datetime is not None

    def _save_recording(self, audio_data):

        if not os.path.exists(self._out_directory):
            os.makedirs(self._out_directory)
        file_name = "{prefix}{date_str}.{ext}".format(
            prefix=self._file_name_prefix,
            date_str=datetime.datetime.now().strftime('%Y-%m-%d_%H-%M-%S'),
            ext='wav'
        )
        file_path = os.path.join(self._out_directory, file_name)

        wf = wave.open(file_path, 'wb')
        wf.setnchannels(self._num_channels)
        wf.setsampwidth(pyaudio.PyAudio().get_sample_size(self._format_size))
        wf.setframerate(self._sample_rate)
        wf.setnframes(self._chunk_size)
        wf.writeframes(b''.join(audio_data))
        wf.close()

if __name__ == "__main__":

    # Getting the instance_id for the parameters
    parser = argparse.ArgumentParser(description='instance_id for audio recording')
    parser.add_argument('--instance_id', help='instance_id for parameters namespace', default="1")
    args, _ = parser.parse_known_args()

    # Getting the values as params
    is_record_topic = rospy.get_param("/data_capture/"+args.instance_id+"/audio_capture/is_record_topic", "audio_capture/is_record")
    audio_topic = rospy.get_param("/data_capture/"+args.instance_id+"/audio_capture/audio_topic", "audio/audio")
    output_directory = rospy.get_param("/data_capture/"+args.instance_id+"/audio_capture/output_directory", "/root/audio")
    num_channels = rospy.get_param("/data_capture/"+args.instance_id+"/audio_capture/num_channels", 1)
    sample_rate = rospy.get_param("/data_capture/"+args.instance_id+"/audio_capture/sample_rate", 16000)
    chunk_size = rospy.get_param("/data_capture/"+args.instance_id+"/audio_capture/chunk_size", 1024)
    format_type = rospy.get_param("/data_capture/"+args.instance_id+"/audio_capture/format_type", "wave")
    format_size = eval(rospy.get_param("/data_capture/"+args.instance_id+"/audio_capture/format_size", "pyaudio.paInt16"))
    file_name_prefix = rospy.get_param("/data_capture/"+args.instance_id+"/audio_capture/file_name_prefix", '')

    assert format_type == "wave"

    AudioCapture(
        is_record_topic=is_record_topic,
        audio_data_topic=audio_topic,
        out_file_directory=output_directory,
        num_channels=num_channels,
        sample_rate=sample_rate,
        chunk_size=chunk_size,
        format_size=format_size,
        file_name_prefix=file_name_prefix
    )
    rospy.spin()


# Same as second example, but using F1 (ALM)
import casadi.casadi as cs
import opengen as og
import json

nu = 3
np = 1
u = cs.SX.sym("u", nu)
p = cs.SX.sym("p", np)

f = cs.dot(u, u)
for i in range(nu):
    f += p * u[i]

F1 = cs.sin(u[0]) - 0.3
C = og.constraints.Zero()

U = og.constraints.Ball2(None, 0.5)

problem = og.builder.Problem(u, p, f)         \
    .with_constraints(U)                      \
    .with_aug_lagrangian_constraints(F1, C)

meta = og.config.OptimizerMeta()                \
    .with_version("0.0.0")                      \
    .with_authors(["Shane Trimble"])            \
    .with_licence("CC4.0-By")                   \
    .with_optimizer_name("shane")

build_config = og.config.BuildConfiguration()  \
    .with_build_directory("python_build")      \
    .with_build_mode("debug")                  \
    .with_tcp_interface_config()

solver_config = og.config.SolverConfiguration()   \
            .with_tolerance(1e-5)                 \
            .with_initial_tolerance(1e-5)         \
            .with_initial_penalty(10)             \
            .with_penalty_weight_update_factor(2) \
            .with_max_outer_iterations(20)

builder = og.builder.OpEnOptimizerBuilder(problem,
                                          metadata=meta,
                                          build_configuration=build_config,
                                          solver_configuration=solver_config)
builder.build()

mng = og.tcp.OptimizerTcpManager('python_build/shane')
mng.start()

pong = mng.ping()                 # check if the server is alive
print(pong)
solution = mng.call([1.0])  # call the solver over TCP
print(json.dumps(solution, indent=4, sort_keys=False))

mng.kill()


import math

import torch
import torch.nn as nn
from torch.nn.parameter import Parameter

import util as u

def reset_param(t):
    stdv = 2. / math.sqrt(t.size(0))
    t.data.uniform_(-stdv,stdv)

class GCN_LSTM(nn.Module):
    def __init__(self, args, activation, device='cpu'):
        super().__init__()
        self.lstm=nn.LSTM(
            input_size=args.layer_2_feats,
            hidden_size=args.lstm_feats,
            num_layers=args.num_lstm_layers
        )
        # self.lstm = nn.GRU(
        #         input_size=args.layer_2_feats,
        #         hidden_size=args.lstm_l2_feats,
        #         num_layers=args.lstm_l2_layers
        # )
        self.device=device
        self.activation=activation
        self.num_layers=args.num_gcn_layers
        self.choose_top_k=TopK(args.layer_2_feats, args.k)
        self.w_list=nn.ParameterList()
        for i in range(self.num_layers):
            if i==0:
                w_i=Parameter(torch.Tensor(args.feats_per_node, args.layer_1_feats))
                reset_param(w_i)
            else:
                w_i=Parameter(torch.Tensor(args.layer_1_feats, args.layer_2_feats))
                reset_param(w_i)
            self.w_list.append(w_i)
    def forward(self, A_list, node_feats, mask_list):
        last_l_seq=[]
        for t, Ahat in enumerate(A_list):
            idx=mask_list[t]
            Ahat, x=Ahat.to(self.device), node_feats.to(self.device)
            x=x.matmul(self.w_list[0])
            x[idx]=self.activation(Ahat.matmul(x[idx]))
            for i in range(1, self.num_layers):
                x=x.matmul(self.w_list[i])
                x[idx]=self.activation(Ahat.matmul(x[idx]))
            last_l_seq.append(x)

        last_l_seq=torch.stack(last_l_seq)

        out, _=self.lstm(last_l_seq, None)
        return out[-1]

class TopK(torch.nn.Module):
    def __init__(self,feats,k):
        super().__init__()
        self.scorer = Parameter(torch.Tensor(feats,1))
        self.reset_param(self.scorer)
        self.k = k

    def reset_param(self,t):
        #Initialize based on the number of rows
        stdv = 1. / math.sqrt(t.size(0))
        t.data.uniform_(-stdv,stdv)

    def forward(self,node_embs):
        scores = node_embs.matmul(self.scorer) / self.scorer.norm()
        ll=node_embs.shape[0]
        tanh = torch.nn.Tanh()
        out=node_embs * tanh(scores.view(-1,1))
        if ll<self.k:
            t=node_embs[-1] * tanh(scores[-1])
            t=t.unsqueeze(0).repeat(self.k-ll,1)
            out =torch.cat([out, t], 0)
        out=out[:self.k]

        #we need to transpose the output
        return out


# Prueba

#
# _nombreVariable = "platano-ðŸ˜¸"
#
# print(_nombreVariable) #Comentario de 1 Linea
#
# """
# Patos
# Todos
#
# queso
# ...
# """

"""Prueba 01"""
# cars = ["Ford","Volvo","BMW"]
#
# for x in cars:
#    print(x)
#
"""Prueba 02"""
# cars = ["Ford","Volvo","BMW"]
# cars.append("PurosðŸ˜¨")
# for x in cars:
#    print(x)V
#

# cars = ["Ford","Volvo","BMW"]
# cars.append("Vamos")
# print(cars)
# cars.pop()
# print(cars)
# cars.remove("Ford")
# print(cars)
# print(len(cars))

fruits = ["apple", "banana", "cherry", "kiwi", "mango"]
# newlist = [x for x in fruits if "a" in x]
# print(newlist)

"""Funciones"""
# x = "Awesome"
#
# def myfunc():
#    global x
#    x = "fantastic"
#    print("python is " + x)
#    pass
# myfunc()
#
# print("Python is "+x)

"""Funciones If"""
#
# x=41
#
# if x > 10:
#    print("Mayor a 10")
#    if x > 20:
#        print("mayor a 20")
#    else :
#        print("Nada")
# else:
#    print("Menor a 41")

"""TryExcept"""
# try:
#    print("Hola Mundo")
# except NameError:
#    print("Hubo un error")
# else:
#    print("FinalizadoðŸ˜ˆ")

"""Switch"""
# variable = "ðŸ˜²"
# if variable == "Flauta":
#    print("Resultado esperado")
# elif variable == "":
#    print("Putos")
# elif variable == "ðŸ˜²":
#    print("Tonto ese es un emogi")
# else:
#    print("NADA")

"""Bucles"""
# i=1
# while i<=6:
#    print(i)
#    i +=1
# else:
#    print("CUMPLIDO")

# i = 0
#
# while i < 10:
#
#    i+=1
#    if i == 5:
#        break
#    print(i)

# print(fruits)
# for x in fruits:
#    print(x)
#    if x == "banana":
#        break
#

"""ESPECIALES"""

"""E - Interpolacion"""
# name = input("Introduce nombre")
# print(f'God asss {name}')

"""E - Operador Ternario"""
# a = 100
# b = 200
# print(a)if a > b else print(b) if a < b else print("Putos")

# _user = False
# _msg = 'Usuario Logado' if _user else 'Usuario Estupido'
# print(_msg)

"""E - Recursiva"""

def factorial(n):
    if n == 1:
        return 1
    else:
        return n * factorial(n - 1)

z = factorial(5)
#
#
# print(z)

"""E - Spread"""

"""FUNCIONES PYTHON"""

x = min(1, 2, 34, 5)
print(x)


# -*- coding: utf-8 -*-
#electrical calculator
import math
import cmath
import numpy as np
import matplotlib.pyplot as plot
from matplotlib.offsetbox import AnchoredText

#three phase power calculations
def singlePhaseLoad( powerConsumed, powerFactor, leadLag):
    #powerConsumed in kW
    #power factor
    #leadLag = 0 - lead, 1 - lag

    #get the angle from the pf
    angle = math.acos(powerFactor)

    #change angle depending on leading or lagging pf.
    if(leadLag == 1):
        angle = 0-angle;

    #calculate the apparent power
    #S*pf = P
    apparentPower = powerConsumed/powerFactor;

    #get reactive Power
    reactivePower = apparentPower*math.sin(angle);

    #display values
    print("Angle is: {} rad / {} degrees").format(angle, math.degrees(angle))
    print("Apparent Power: {} VA").format(apparentPower)
    print("Reactive Power is: {} VAR").format(reactivePower);

def threePhaseLoad( powerConsumed, powerFactor, leadLag, voltagel2l):
    """
    Para: powerConsumed - power consumed by the 3phase load in W
          powerFactor - pf
          leadLag - leading pf - 0, lagging pf - 1
          voltage121 - line to line voltage across the 3 phase load
    """

    #powerConsumed in kW
    #power factor
    #leadLag = 0 - lead, 1 - lag

    #get the angle from the pf
    angle = math.acos(powerFactor)

    #change angle depending on leading or lagging pf.
    if(leadLag == 1):
        angle = 0-angle;

    #calculate the apparent power
    #S*pf = P
    apparentPower = powerConsumed/powerFactor;

    #get reactive Power
    reactivePower = apparentPower*math.sin(angle);

    #get the line to line current
    currentl2l = apparentPower/(math.sqrt(3)*voltagel2l);
    #display values
    print("Angle is: {} rad / {} degrees").format(angle, math.degrees(angle))
    print("Apparent Power: {} VA").format(apparentPower)
    print("Reactive Power is: {} VAR").format(reactivePower);
    print("l2l Current is: {} A").format(currentl2l);

def polarRec(mod, angleDeg):
    """
       Converts from polar to rectangular coordinates
       return complexNumber
    """
    return cmath.rect(mod,math.radians(angleDeg))

def recPolar(complexNumber):
    """
       Converts from rectangular to polar coordinates.
       return (mod, angle in deg)
    """
    ans = cmath.polar(complexNumber)
    return (ans[0], math.degrees(ans[1]))

def paraImp(number1, number2):
    """
        Calculates the total impedence of 2 impedences in parallel
    """
    return (number1*number2)/(number1 + number2)

def impBaseConv(voltageRating, powerRating, voltageBase, powerBase, impedenceValue):
    """
        Parameters of equipment are given using the power rating of the equipment as the MVA base.
        This function converts Z values from old rating to new rating
        voltageRating - voltage rating of the equipment
        powerRating - powerRating of the equipment
        powerBase - the power base of where the equipment is being used
        voltageBase - the voltage base of where the equipmment is being used
        impedenceValue - the value to be converted between bases

        The formula for Zbase = Vbase**2/Sbase

    """
    return impedenceValue*((voltageRating**2/powerRating)/(voltageBase**2/powerBase))

def smibTransCalc(Egen, Vpoc, Xeq, EgenPost, VpocPost, XeqPost):

    #pre fault graph
    delta = np.arange(0, 3.14, 0.1);
    Pe = (abs(Egen)*abs(Vpoc)*np.sin(delta))/abs(Xeq)

    #post fault graph
    Pepost = (abs(EgenPost)*abs(VpocPost)*np.sin(delta))/abs(XeqPost)

    f,ax = plot.subplots(1,1)
    ax.plot(delta, Pe) #pre fault
    ax.plot(delta, Pepost) #post fault
    ax.plot(delta, [ abs(Vpoc) for i in delta]) #mechanical power input

    plot.title("Power Curve")
    plot.xlabel("Power Angle Delta (rad)")
    plot.ylabel("Power (p.u or W)")
    plot.grid(True, which='both')
    #plot.text("Pe = {}sin(del)").format((abs(Egen)*abs(Vpoc))/abs(Xeq))

    anchored_text = AnchoredText("Pe = {}sin(del)".format((abs(Egen)*abs(Vpoc))/abs(Xeq)), loc=2)
    ax.add_artist(anchored_text)

    d0 = math.asin(Vpoc/((abs(Egen)*abs(Vpoc))/abs(Xeq)))
    d1 = math.asin(Vpoc/((abs(EgenPost)*abs(VpocPost))/abs(XeqPost)))
    print(d0)
    print(d1)

    plot.show()


NUM_ROWS = 5
NUM_COLS = 9

# construct a matrix
my_matrix = {}
for row in range(NUM_ROWS):
    row_dict = {}
    for col in range(NUM_COLS):
        row_dict[col] = row * col
    my_matrix[row] = row_dict

# print(my_matrix)
d_frmt = '{:<4} {:<4}'
for k,v in my_matrix.items():
    print("{", k, "}", "\t", v)

frmt = '{:<4}'
# print the matrix
for row in range(NUM_ROWS):
    for col in range(NUM_COLS):
        print(frmt.format(my_matrix[row][col]), end='')
    print()

2. Python - Rice/c3-dataAnalysis/week1/ex.py


'''
Script for building and visualization of v(x) function for fixed x0 and gamma
(OSCILLATING case of eigenfunction)
'''

import numpy as np
import matplotlib.pyplot as plt
import pandas as pd
import utils

x0 = 0.41
gamma = 6.0

AFTER_TANGENT = False
SUFFIX_NAME = '_after_tangent' if AFTER_TANGENT else ''
CSV_FILE = f'../Tracer/Results/x0={x0:.2f}/x0={x0:.2f}_analytical' + SUFFIX_NAME + '.csv'

def get_omega(g):
    '''
    Return omega(gamma) value
    :param g: gamma value
    :return: omega(gamma) value
    '''
    df = pd.read_csv(CSV_FILE, sep=';')
    return df.loc[(df['gamma'] < g+utils.EPS) & (df['gamma'] > g-utils.EPS)]['w'].values[0]

def get_v_func_val(g, w, x):
    '''
    Calculate and return value of v(x) for fixed gamma
    :param g: fixed gamma value
    :param g: fixed omega value
    :param x: x value
    :return: v(x) for fixed gamma
    '''
    if g <= 0:
        mu = np.sqrt(-g + w*1.0j)
        return np.cosh(mu*x)
    else:
        mu = np.sqrt(g + w*1.0j)
        return np.cos(mu*x)

def draw_v_func_components(xs, vs):
    '''
    Draw 2 graphics: Re(v(x)) dependency and Im(v(x)) dependency
    :param xs: x values
    :param vs: v(x) values
    '''
    f = plt.figure(figsize=(10, 4))
    f.canvas.set_window_title('x0={:.2}__g={:.4}'.format(x0, gamma))
    f.subplots_adjust(left=0.07, bottom=0.1, right=0.97, top=0.97, hspace=0.5)
    ax1 = f.add_subplot(121)
    ax2 = f.add_subplot(122)
    ax1.set_xlabel('x')
    ax1.set_ylabel('Re v', rotation='horizontal', position=(0.0, 0.53))
    ax1.grid()
    ys = [v.real for v in vs]
    ax1.plot(xs, ys, color='seagreen', linewidth=2, zorder=3)
    ax1.axhline(y=0.0, linewidth=2, color='grey', zorder=2)
    ax1.axvline(x=0.0, linewidth=2, color='grey', zorder=2)
    ax2.set_xlabel('x')
    ax2.set_ylabel('Im v', rotation='horizontal', position=(0.0, 0.53))
    ax2.grid()
    ys = [v.imag for v in vs]
    ax2.plot(xs, ys, color='peru', linewidth=2, zorder=3)
    ax2.axhline(y=0.0, linewidth=2, color='grey', zorder=2)
    ax2.axvline(x=0.0, linewidth=2, color='grey', zorder=2)
    plt.show()

if __name__ == '__main__':
    w = get_omega(gamma)
    xs = np.linspace(0, 1, 10000)
    vs = [get_v_func_val(gamma, w, x) for x in xs]
    draw_v_func_components(xs, vs)


import mimetypes
import os

from bonobo.nodes import (
    CsvReader, CsvWriter, FileReader, FileWriter, JsonReader, JsonWriter, PickleReader, PickleWriter
)

FILETYPE_CSV = "text/csv"
FILETYPE_JSON = "application/json"
FILETYPE_PICKLE = "pickle"
FILETYPE_PLAIN = "text/plain"

READER = "reader"
WRITER = "writer"

class Registry:
    ALIASES = {
        "csv": FILETYPE_CSV,
        "json": FILETYPE_JSON,
        "pickle": FILETYPE_PICKLE,
        "plain": FILETYPE_PLAIN,
        "text": FILETYPE_PLAIN,
        "txt": FILETYPE_PLAIN,
    }

    FACTORIES = {
        READER: {
            FILETYPE_JSON: JsonReader,
            FILETYPE_CSV: CsvReader,
            FILETYPE_PICKLE: PickleReader,
            FILETYPE_PLAIN: FileReader,
        },
        WRITER: {
            FILETYPE_JSON: JsonWriter,
            FILETYPE_CSV: CsvWriter,
            FILETYPE_PICKLE: PickleWriter,
            FILETYPE_PLAIN: FileWriter,
        },
    }

    def get_factory_for(self, kind, name, *, format=None):
        if not kind in self.FACTORIES:
            raise KeyError("Unknown factory kind {!r}.".format(kind))

        if format is None and name is None:
            raise RuntimeError("Cannot guess factory without at least a filename or a format.")

        # Guess mimetype if possible
        if format is None:
            format = mimetypes.guess_type(name)[0]

        # Guess from extension if possible
        if format is None:
            _, _ext = os.path.splitext(name)
            if _ext:
                format = _ext[1:]

        # Apply aliases
        if format in self.ALIASES:
            format = self.ALIASES[format]

        if format is None or not format in self.FACTORIES[kind]:
            raise RuntimeError(
                "Could not resolve {kind} factory for {name} ({format}).".format(kind=kind, name=name, format=format)
            )

        return self.FACTORIES[kind][format]

    def get_reader_factory_for(self, name, *, format=None):
        """
        Returns a callable to build a reader for the provided filename, eventually forcing a format.

        :param name: filename
        :param format: format
        :return: type
        """
        return self.get_factory_for(READER, name, format=format)

    def get_writer_factory_for(self, name, *, format=None):
        """
        Returns a callable to build a writer for the provided filename, eventually forcing a format.

        :param name: filename
        :param format: format
        :return: type
        """
        return self.get_factory_for(WRITER, name, format=format)

default_registry = Registry()

def create_reader(name, *args, format=None, registry=default_registry, **kwargs):
    """
    Create a reader instance, guessing its factory using filename (and eventually format).

    :param name:
    :param args:
    :param format:
    :param registry:
    :param kwargs:

    :return: mixed
    """
    return registry.get_reader_factory_for(name, format=format)(name, *args, **kwargs)

def create_writer(name, *args, format=None, registry=default_registry, **kwargs):
    """
    Create a writer instance, guessing its factory using filename (and eventually format).

    :param name:
    :param args:
    :param format:
    :param registry:
    :param kwargs:

    :return: mixed
    """
    return registry.get_writer_factory_for(name, format=format)(name, *args, **kwargs)