""" ---- IMPORT LIBRARIES ---- """
from tkinter import *
import serial_config
import db
import sys
""" ---- VARIABLE DECLARATION ---- """

try:
	argv_sys=int(sys.argv[1])

	p_argv=argv_sys % 10
	m_argv=argv_sys // 10

except:
	p_argv=0
	m_argv=0
print(p_argv)
print(m_argv)
#DABATASE INITIALIZATION
DB=db.Database()

#ALL VARIABLE INITIALIZATION
if p_argv in range(1,10):
	program="prog"+str(p_argv)
else:
	program=DB.rprogram()

if m_argv==1 :
	mode=1
else:
	mode=0

auto_proram_cycles=DB.rdata(program,'program')[0]
auto_steps=DB.rdata(program,'program')[1]
auto_point1_w8=DB.rdata(program,'program')[2]
auto_point2_w8=DB.rdata(program,'program')[3]
auto_point3_w8=DB.rdata(program,'program')[4]
auto_point4_w8=DB.rdata(program,'program')[5]
auto_point5_w8=DB.rdata(program,'program')[6]
auto_point6_w8=DB.rdata(program,'program')[7]
auto_point7_w8=DB.rdata(program,'program')[8]
auto_point8_w8=DB.rdata(program,'program')[9]
auto_point9_w8=DB.rdata(program,'program')[10]
auto_point10_w8=DB.rdata(program,'program')[11]

speed_manu= DB.rdata(program,"speed") ;
increment_manu =DB.rdata(program,"step") ;
point1=DB.rdata(program,'point1')
point2=DB.rdata(program,'point2')
point3=DB.rdata(program,'point3')
point4=DB.rdata(program,'point4')
point5=DB.rdata(program,'point5')
point6=DB.rdata(program,'point6')
point7=DB.rdata(program,'point7')
point8=DB.rdata(program,'point8')
point9=DB.rdata(program,'point9')
point10=DB.rdata(program,'point10')

point1_str=str(point1)
point2_str=str(point2)
point3_str=str(point3)
point4_str=str(point4)
point5_str=str(point5)
point6_str=str(point6)
point7_str=str(point7)
point8_str=str(point8)
point9_str=str(point9)
point10_str=str(point10)

auto_count=0
base_read=0.0
shoulder_read=0.0
elbow_read=0.0
elbow_read=0.0
vwrist_read=0.0
rwrist_read=0.0
gripper_read=0.0

print(point1_str)

# MAIN CLASS TO WRITE A POINT ON SERIAL
class point():
	def __init__(self,arr):

		self.base=arr[0]
		self.shoulder=arr[1]
		self.elbow=arr[2]
		self.vwrist=arr[3]
		self.rwrist=arr[4]
		self.gripper=arr[5]

	def sttr(self,numar):
		a=numar//100
		if numar>100 :
			b=(numar-(a*100))//10
		else :
			b=numar//10
		c=numar%10
		return(str(a)+str(b)+str(c))

	def s_base(self):
		numar=self.base
		snumar=self.sttr(numar)
		return snumar

	def s_shoulder(self):
		numar=self.shoulder
		snumar=self.sttr(numar)
		return snumar

	def s_elbow(self):
		numar=self.elbow
		snumar=self.sttr(numar)
		return snumar

	def s_vwrist(self):
		numar=self.vwrist
		snumar=self.sttr(numar)
		return snumar

	def s_rwrist(self):
		numar=self.rwrist
		snumar=self.sttr(numar)
		return snumar

	def s_gripper(self):
		numar=self.gripper
		snumar=self.sttr(numar)
		return snumar

""" DECODARE TELEGRAMA """
def decodare_char(input_char):
  if (chr(input_char)=='0') :
  	return 0
  elif (chr(input_char)=='1'):
  	return 1
  elif (chr(input_char)=='2'):
  	return 2
  elif (chr(input_char)=='3'):
  	return 3
  elif (chr(input_char)=='4'):
  	return 4
  elif (chr(input_char)=='5'):
  	return 5
  elif (chr(input_char)=='6'):
  	return 6
  elif (chr(input_char)=='7'):
  	return 7
  elif (chr(input_char)=='8'):
  	return 8
  elif (chr(input_char)=='9'):
  	return 9

#DECLARING MAIN ROOT AND FRAMES
root=Tk() # declaring the main window , root window
frame0 = Frame(root,width=200, height=400,borderwidth=1,relief='sunken',bg='grey',padx=5,pady=5)
frame1 = Frame(root,width=200, height=400,borderwidth=1,relief='sunken',bg='grey',padx=5,pady=5)
frame2 = Frame(root,width=492, height=400,borderwidth=1,relief='sunken',bg='grey',padx=5,pady=5)
frame3 = Frame(root,width=492, height=400,borderwidth=1,relief='sunken',bg='grey',padx=5,pady=5)
frame4 = Frame(root,width=492, height=400,borderwidth=1,relief='sunken',bg='grey',padx=5,pady=5)
frame5 = Frame(root,width=492, height=400,borderwidth=1,relief='sunken',bg='grey',padx=5,pady=5)
root.geometry("492x975")

""" SERIAL READ """

""" ---- CREATING EVENTS ----  """
#UPDATE DEGREES ON SCREEN

def set_prog_d():
	global program
	program=clicked.get()
	com=clicked2.get()
	print(program);
	print(com);
	point1=DB.rdata(program,"point1")
	point2=DB.rdata(program,"point2")
	point3=DB.rdata(program,"point3")
	point4=DB.rdata(program,"point4")
	point5=DB.rdata(program,"point5")
	point6=DB.rdata(program,"point6")
	point7=DB.rdata(program,"point7")
	point8=DB.rdata(program,"point8")
	point9=DB.rdata(program,"point9")
	point10=DB.rdata(program,"point10")
	DB.wdata(program,"port",com)
	program_req=DB.rdata(program,"program")

	Point1_value.config(text=str([point1[0],point1[1],point1[2],point1[3],point1[4],point1[5]]))
	Point2_value.config(text=str([point2[0],point2[1],point2[2],point2[3],point2[4],point2[5]]))
	Point3_value.config(text=str([point3[0],point3[1],point3[2],point3[3],point3[4],point3[5]]))
	Point4_value.config(text=str([point4[0],point4[1],point4[2],point4[3],point4[4],point4[5]]))
	Point5_value.config(text=str([point5[0],point5[1],point5[2],point5[3],point5[4],point5[5]]))
	Point6_value.config(text=str([point6[0],point6[1],point6[2],point6[3],point6[4],point6[5]]))
	Point7_value.config(text=str([point7[0],point7[1],point7[2],point7[3],point7[4],point7[5]]))
	Point8_value.config(text=str([point8[0],point8[1],point8[2],point8[3],point8[4],point8[5]]))
	Point9_value.config(text=str([point9[0],point9[1],point9[2],point9[3],point9[4],point9[5]]))
	Point10_value.config(text=str([point10[0],point10[1],point10[2],point10[3],point10[4],point10[5]]))

	NR_OF_CYCLES_D1.config(text=str(program_req[0]))
	NR_OF_STEPS_D1.config(text=str(program_req[1]))
	P1_W8_TIME_D1.config(text=str(program_req[2]))
	P2_W8_TIME_D1.config(text=str(program_req[3]))
	P3_W8_TIME_D1.config(text=str(program_req[4]))
	P4_W8_TIME_D1.config(text=str(program_req[5]))
	P5_W8_TIME_D1.config(text=str(program_req[6]))
	P6_W8_TIME_D1.config(text=str(program_req[7]))
	P7_W8_TIME_D1.config(text=str(program_req[8]))
	P8_W8_TIME_D1.config(text=str(program_req[9]))
	P9_W8_TIME_D1.config(text=str(program_req[10]))
	P10_W8_TIME_D1.config(text=str(program_req[11]))

def get_speed_d():
	global speed_manu
	loc_speed_manu=get_speed.get()
	try:
		speed_manu_int=int(loc_speed_manu)
		a=speed_manu_int//100
		if speed_manu_int>100 :
			b=(speed_manu_int-(a*100))//10
		else :
			b=speed_manu_int//10
		c=speed_manu_int%10
		speed_manu=str(a)+str(b)+str(c)
		print(speed_manu)
	except:
		speed_manu='020'
		print(speed_manu)

def get_step_d():
	global increment_manu
	loc_step_manu=get_step.get()
	if int(loc_step_manu)>20 :
		increment_manu=20
	else:
		increment_manu=int(loc_step_manu)
	print(increment_manu)

def update_degrees():
	message=''
	sute=0
	zeci=0
	unitati=0
	global base_read
	global shoulder_read
	global elbow_read
	global elbow_read
	global vwrist_read
	global rwrist_read
	global gripper_read
	message=serial_config.serial_read()
	if message[0]==48:
		print("citit")
		sute=decodare_char(message[1])
		zeci=decodare_char(message[2])
		unitati=decodare_char(message[3])
		base_read = sute *100.0 + zeci * 10.0 + unitati
		sute=decodare_char(message[4])
		zeci=decodare_char(message[5])
		unitati=decodare_char(message[6])
		shoulder_read = sute *100.0 + zeci * 10.0 + unitati
		sute=decodare_char(message[7])
		zeci=decodare_char(message[8])
		unitati=decodare_char(message[9])
		elbow_read = sute *100.0 + zeci * 10.0 + unitati
		sute=decodare_char(message[10])
		zeci=decodare_char(message[11])
		unitati=decodare_char(message[12])
		vwrist_read = sute *100.0 + zeci * 10.0 + unitati
		sute=decodare_char(message[13])
		zeci=decodare_char(message[14])
		unitati=decodare_char(message[15])
		rwrist_read = sute *100.0 + zeci * 10.0 + unitati
		sute= decodare_char(message[16])
		zeci=decodare_char(message[17])
		unitati=decodare_char(message[18])
		gripper_read = sute *100.0 + zeci * 10.0 + unitati
		print(base_read)
		print(shoulder_read)
		print(elbow_read)
		print(vwrist_read)
		print(rwrist_read)
		print(gripper_read)
		current_point_base.config(text=str(base_read))
		current_point_shoulder.config(text=str(shoulder_read))
		current_point_elbow.config(text=str(elbow_read))
		current_point_vwrist.config(text=str(vwrist_read))
		current_point_rwrist.config(text=str(rwrist_read))
		current_point_gripper.config(text=str(gripper_read))

def increment_joint(joint):
	update_degrees()
	global base_read
	global shoulder_read
	global elbow_read
	global vwrist_read
	global rwrist_read
	global gripper_read
	base_read_i=int(base_read)
	shoulder_read_i=int(shoulder_read)
	elbow_read_i=int(elbow_read)
	vwrist_read_i=int(vwrist_read)
	rwrist_read_i=int(rwrist_read)
	gripper_read_i=int(gripper_read)
	if joint==1 :
		to_comanda='3'
		if (base_read_i)<300:
			base_read_i=int(base_read)+increment_manu
	if joint==2 :
		to_comanda='4'
		if (shoulder_read_i)<120:
			shoulder_read_i=int(shoulder_read)+increment_manu
	if joint==3 :
		to_comanda='5'
		if (elbow_read_i)<210:
			elbow_read_i=int(elbow_read)+increment_manu
	if joint==4 :
		to_comanda='6'
		if (vwrist_read_i)<220:
			vwrist_read_i=int(vwrist_read)+increment_manu
	if joint==5 :
		to_comanda='7'
		if (rwrist_read_i)<270:
			rwrist_read_i=int(rwrist_read)+increment_manu
	if joint==6 :
		to_comanda='8'
		if (gripper_read_i)<220:
			gripper_read_i=int(gripper_read)+increment_manu
	point_arr=[base_read_i,shoulder_read_i,elbow_read_i,vwrist_read_i,rwrist_read_i,gripper_read_i]
	point_to=point(point_arr)
	to_grade_base=point_to.s_base()
	to_grade_shoulder=point_to.s_shoulder()
	to_grade_elbow=point_to.s_elbow()
	to_grade_vwrist=point_to.s_vwrist()
	to_grade_rwrist=point_to.s_rwrist()
	to_grade_gripper=point_to.s_gripper()
	to_speed=speed_manu

	serial_config.serial_write(to_comanda,to_grade_base,to_grade_shoulder,to_grade_elbow,to_grade_vwrist,to_grade_rwrist,to_grade_gripper,to_speed)

def decrement_joint(joint):
	update_degrees()
	global base_read
	global shoulder_read
	global elbow_read
	global vwrist_read
	global rwrist_read
	global gripper_read
	base_read_i=int(base_read)
	shoulder_read_i=int(shoulder_read)
	elbow_read_i=int(elbow_read)
	vwrist_read_i=int(vwrist_read)
	rwrist_read_i=int(rwrist_read)
	gripper_read_i=int(gripper_read)
	if joint==1 :
		to_comanda='3'
		if (base_read_i)>=20:
			base_read_i=int(base_read)-increment_manu
		else:
			base_read_i=22
	if joint==2 :
		to_comanda='4'
		if (shoulder_read_i)>=20:
			shoulder_read_i=int(shoulder_read)-increment_manu
		else:
			shoulder_read_i=22
	if joint==3 :
		to_comanda='5'
		if (elbow_read_i)>=90:
			elbow_read_i=int(elbow_read)-increment_manu
		else:
			elbow_read_i=92
	if joint==4 :
		to_comanda='6'
		if (vwrist_read_i)>=60:
			vwrist_read_i=int(vwrist_read)-increment_manu
		else:
			vwrist_read_i=62
	if joint==5 :
		to_comanda='7'
		if (rwrist_read_i)>=20:
			rwrist_read_i=int(rwrist_read)-increment_manu
		else:
			rwrist_read_i=22
	if joint==6 :
		to_comanda='8'
		if (gripper_read_i)>=160:
			gripper_read_i=int(gripper_read)-increment_manu
		else:
			gripper_read_i=162
	point_arr=[base_read_i,shoulder_read_i,elbow_read_i,vwrist_read_i,rwrist_read_i,gripper_read_i]
	point_to=point(point_arr)
	to_grade_base=point_to.s_base()
	to_grade_shoulder=point_to.s_shoulder()
	to_grade_elbow=point_to.s_elbow()
	to_grade_vwrist=point_to.s_vwrist()
	to_grade_rwrist=point_to.s_rwrist()
	to_grade_gripper=point_to.s_gripper()
	to_speed=speed_manu

	serial_config.serial_write(to_comanda,to_grade_base,to_grade_shoulder,to_grade_elbow,to_grade_vwrist,to_grade_rwrist,to_grade_gripper,to_speed)

def sincronizare():
	to_comanda='1' ;
	to_grade_base='180' ;
	to_grade_shoulder='120' ;
	to_grade_elbow='150' ;
	to_grade_vwrist='110' ;
	to_grade_rwrist='050' ;
	to_grade_gripper='230' ;
	to_speed='030' ;
	serial_config.serial_write(to_comanda,to_grade_base,to_grade_shoulder,to_grade_elbow,to_grade_vwrist,to_grade_rwrist,to_grade_gripper,to_speed)

def teach_point(p_teach):
	update_degrees()
	global program
	global base_read
	global shoulder_read
	global elbow_read
	global vwrist_read
	global rwrist_read
	global gripper_read
	base_int=int(base_read)
	shoulder_i=int(shoulder_read)
	elbow_i=int(elbow_read)
	vwrist_i=int(vwrist_read)
	rwrist_i=int(rwrist_read)
	gripper_i=int(gripper_read)

	if p_teach==1 :
		DB.wdata(program,"point1",[base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i])
		Point1_value.config(text=str([base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i]))
	elif p_teach==2 :
		DB.wdata(program,"point2",[base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i])
		Point2_value.config(text=str([base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i]))
	elif p_teach==3 :
		DB.wdata(program,"point3",[base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i])
		Point3_value.config(text=str([base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i]))
	elif p_teach==4 :
		DB.wdata(program,"point4",[base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i])
		Point4_value.config(text=str([base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i]))
	elif p_teach==5 :
		DB.wdata(program,"point5",[base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i])
		Point5_value.config(text=str([base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i]))
	elif p_teach==6 :
		DB.wdata(program,"point6",[base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i])
		Point6_value.config(text=str([base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i]))
	elif p_teach==7 :
		DB.wdata(program,"point7",[base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i])
		Point7_value.config(text=str([base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i]))
	elif p_teach==8 :
		DB.wdata(program,"point8",[base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i])
		Point8_value.config(text=str([base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i]))
	elif p_teach==9 :
		DB.wdata(program,"point9",[base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i])
		Point9_value.config(text=str([base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i]))
	elif p_teach==10 :
		DB.wdata(program,"point10",[base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i])
		Point10_value.config(text=str([base_int,shoulder_i,elbow_i,vwrist_i,rwrist_i,gripper_i]))

def save_program():
	global program
	global auto_proram_cycles
	global auto_steps
	global auto_point1_w8
	global auto_point2_w8
	global auto_point3_w8
	global auto_point4_w8
	global auto_point5_w8
	global auto_point6_w8
	global auto_point7_w8
	global auto_point8_w8
	global auto_point9_w8
	global auto_point10_w8

	try:
		auto_proram_cycles=int(NR_OF_CYCLES_E.get())
	except:
		auto_proram_cycles=0

	try:
		auto_steps=int(NR_OF_STEPS_E.get())
	except:
		auto_steps=0

	try:
		auto_point1_w8=int(P1_W8_TIME_E.get())
	except:
		auto_point1_w8=0

	try:
		auto_point2_w8=int(P2_W8_TIME_E.get())
	except:
		auto_point2_w8=0

	try:
		auto_point3_w8=int(P3_W8_TIME_E.get())
	except:
		auto_point3_w8=0
	try:
		auto_point4_w8=int(P4_W8_TIME_E.get())
	except:
		auto_point4_w8=0

	try:
		auto_point5_w8=int(P5_W8_TIME_E.get())
	except:
		auto_point5_w8=0

	try:
		auto_point6_w8=int(P6_W8_TIME_E.get())
	except:
		auto_point6_w8=0

	try:
		auto_point7_w8=int(P7_W8_TIME_E.get())
	except:
		auto_point7_w8=0

	try:
		auto_point8_w8=int(P8_W8_TIME_E.get())
	except:
		auto_point8_w8=0

	try:
		auto_point9_w8=int(P9_W8_TIME_E.get())
	except:
		auto_point9_w8=0
	try:
		auto_point10_w8=int(P10_W8_TIME_E.get())
	except:
				auto_point10_w8=0

	program_arr=[auto_proram_cycles,auto_steps,auto_point1_w8,auto_point2_w8,auto_point3_w8,auto_point4_w8,auto_point5_w8,auto_point6_w8,auto_point7_w8,auto_point8_w8,auto_point9_w8,auto_point10_w8]

	DB.wdata(program,"program",program_arr)
	NR_OF_CYCLES_D1.config(text=str(auto_proram_cycles)+" cycles")
	NR_OF_STEPS_D1.config(text=str(auto_steps)+" steps")
	P1_W8_TIME_D1.config(text=str(auto_point1_w8)+" sec")
	P2_W8_TIME_D1.config(text=str(auto_point2_w8)+" sec")
	P3_W8_TIME_D1.config(text=str(auto_point3_w8)+" sec")
	P4_W8_TIME_D1.config(text=str(auto_point4_w8)+" sec")
	P5_W8_TIME_D1.config(text=str(auto_point5_w8)+" sec")
	P6_W8_TIME_D1.config(text=str(auto_point6_w8)+" sec")
	P7_W8_TIME_D1.config(text=str(auto_point7_w8)+" sec")
	P8_W8_TIME_D1.config(text=str(auto_point8_w8)+" sec")
	P9_W8_TIME_D1.config(text=str(auto_point9_w8)+" sec")
	P10_W8_TIME_D1.config(text=str(auto_point10_w8)+" sec")

def start_auto():
	global auto_count
	global mode
	program_r=DB.rdata(program,"program")
	auto_count=program_r[0]
	mode=1

	root.after(program_r[2]*1000,start_goto_p1)

def start_manual():

	global mode
	mode=0

def start_goto_p1():
	global program
	global speed_manu
	global auto_point1_w8
	global auto_steps
	global auto_count

	if auto_count>0 and mode==1 :
		point1=point(DB.rdata(program,"point1"))
		serial_config.serial_write('2',point1.s_base(),point1.s_shoulder(),point1.s_elbow(),point1.s_vwrist(),point1.s_rwrist(),point1.s_gripper(),speed_manu)
		if auto_steps>=2 :
			root.after(auto_point1_w8*1000,start_goto_p2)
		else :
			auto_count-=1
			root.after(auto_point1_w8*1000,start_goto_p1)
	else:
			root.after(auto_point1_w8*1000,sincronizare)

def start_goto_p2():
	global program
	global speed_manu
	global auto_point2_w8
	global auto_steps
	global auto_count
	global mode
	if auto_count>0 and mode==1 :
		point1=point(DB.rdata(program,"point2"))
		serial_config.serial_write('2',point1.s_base(),point1.s_shoulder(),point1.s_elbow(),point1.s_vwrist(),point1.s_rwrist(),point1.s_gripper(),speed_manu)

		if auto_steps>=3 :
			root.after(auto_point2_w8*1000,start_goto_p3)
		else :
			auto_count-=1
			root.after(auto_point2_w8*1000,start_goto_p1)

def start_goto_p3():
	global program
	global speed_manu
	global auto_point3_w8
	global auto_steps
	global auto_count
	global mode
	if auto_count>0 and mode==1 :
		point1=point(DB.rdata(program,"point3"))
		serial_config.serial_write('2',point1.s_base(),point1.s_shoulder(),point1.s_elbow(),point1.s_vwrist(),point1.s_rwrist(),point1.s_gripper(),speed_manu)

		if auto_steps>=4 :
			root.after(auto_point3_w8*1000,start_goto_p4)
		else :
			auto_count-=1
			root.after(auto_point3_w8*1000,start_goto_p1)

def start_goto_p4():
	global program
	global speed_manu
	global auto_point4_w8
	global auto_steps
	global auto_count
	global mode
	if auto_count>0 and mode==1 :
		point1=point(DB.rdata(program,"point4"))
		serial_config.serial_write('2',point1.s_base(),point1.s_shoulder(),point1.s_elbow(),point1.s_vwrist(),point1.s_rwrist(),point1.s_gripper(),speed_manu)

		if auto_steps>=5 :
			root.after(auto_point4_w8*1000,start_goto_p5)
		else :
			auto_count-=1
			root.after(auto_point4_w8*1000,start_goto_p1)

def start_goto_p5():
	global program
	global speed_manu
	global auto_point5_w8
	global auto_steps
	global auto_count
	global mode
	if auto_count>0 and mode==1 :
		point1=point(DB.rdata(program,"point5"))
		serial_config.serial_write('2',point1.s_base(),point1.s_shoulder(),point1.s_elbow(),point1.s_vwrist(),point1.s_rwrist(),point1.s_gripper(),speed_manu)

		if auto_steps>=6 :
			root.after(auto_point5_w8*1000,start_goto_p6)
		else :
			auto_count-=1
			root.after(auto_point5_w8*1000,start_goto_p1)

def start_goto_p6():
	global program
	global speed_manu
	global auto_point6_w8
	global auto_steps
	global auto_count
	global mode
	if auto_count>0 and mode==1:
		point1=point(DB.rdata(program,"point6"))
		serial_config.serial_write('2',point1.s_base(),point1.s_shoulder(),point1.s_elbow(),point1.s_vwrist(),point1.s_rwrist(),point1.s_gripper(),speed_manu)

		if auto_steps>=7 :
			root.after(auto_point6_w8*1000,start_goto_p7)
		else :
			auto_count-=1
			root.after(auto_point6_w8*1000,start_goto_p1)

def start_goto_p7():
	global program
	global speed_manu
	global auto_point7_w8
	global auto_steps
	global auto_count
	global mode
	if auto_count>0 and mode==1:
		point1=point(DB.rdata(program,"point7"))
		serial_config.serial_write('2',point1.s_base(),point1.s_shoulder(),point1.s_elbow(),point1.s_vwrist(),point1.s_rwrist(),point1.s_gripper(),speed_manu)

		if auto_steps>=8 :
			root.after(auto_point7_w8*1000,start_goto_p8)
		else :
			auto_count-=1
			root.after(auto_point7_w8*1000,start_goto_p1)

def start_goto_p8():
	global program
	global speed_manu
	global auto_point8_w8
	global auto_steps
	global auto_count
	global mode
	if auto_count>0 and mode==1 :
		point1=point(DB.rdata(program,"point8"))
		serial_config.serial_write('2',point1.s_base(),point1.s_shoulder(),point1.s_elbow(),point1.s_vwrist(),point1.s_rwrist(),point1.s_gripper(),speed_manu)

		if auto_steps>=9 :
			root.after(auto_point8_w8*1000,start_goto_p9)
		else :
			auto_count-=1
			root.after(auto_point8_w8*1000,start_goto_p1)

def start_goto_p9():
	global program
	global speed_manu
	global auto_point9_w8
	global auto_steps
	global auto_count
	global mode
	if auto_count>0 and mode==1 :
		point1=point(DB.rdata(program,"point9"))
		serial_config.serial_write('2',point1.s_base(),point1.s_shoulder(),point1.s_elbow(),point1.s_vwrist(),point1.s_rwrist(),point1.s_gripper(),speed_manu)

		if auto_steps>=9 :
			root.after(auto_point9_w8*1000,start_goto_p10)
		else :
			auto_count-=1
			root.after(auto_point9_w8*1000,start_goto_p1)

def start_goto_p10():
	global program
	global speed_manu
	global auto_point10_w8
	global auto_steps
	global auto_count
	global mode
	if auto_count>0 and mode==1:
		point1=point(DB.rdata(program,"point10"))
		serial_config.serial_write('2',point1.s_base(),point1.s_shoulder(),point1.s_elbow(),point1.s_vwrist(),point1.s_rwrist(),point1.s_gripper(),speed_manu)

		auto_count-=1
		root.after(auto_point9_w8*1000,start_goto_p1)

""" ---------------------------------------GENERAL USER INTERFACE----------------------------"""

""" ---- LABELS ---- """

mySection1=Button(frame0 , text='Teach Mode',width=21, command=start_manual)
mySection2=Button(frame0 , text='Auto Mode',width=22 ,command=start_auto)
mySection3=Button(frame0 , text='Synchronize',command= sincronizare,width=21)

""" --- MANUAL --- """

current_point_base_text=Label(frame1,text='Base',width=15,bg='grey')
current_point_shoulder_text=Label(frame1,text='Shoulder',width=15,bg='grey')
current_point_elbow_text=Label(frame1,text='Elbow',width=15,bg='grey')
current_point_vwrist_text=Label(frame1,text='VWrist',width=15,bg='grey')
current_point_rwrist_text=Label(frame1,text='RWrist',width=15,bg='grey')
current_point_gripper_text=Label(frame1,text='Gripper',width=15,bg='grey')

inc_base=Button(frame1 , text='+',command= lambda:increment_joint(1))
dec_base=Button(frame1 , text='-',command= lambda:decrement_joint(1))

inc_shoulder=Button(frame1 , text='+',command= lambda:increment_joint(2))
dec_shoulder=Button(frame1 , text='-',command= lambda:decrement_joint(2))

inc_elbow=Button(frame1 , text='+',command= lambda:increment_joint(3))
dec_elbow=Button(frame1 , text='-',command= lambda:decrement_joint(3))

inc_vwrist=Button(frame1 , text='+',command= lambda:increment_joint(4))
dec_vwrist=Button(frame1 , text='-',command= lambda:decrement_joint(4))

inc_rwrist=Button(frame1 , text='+',command= lambda:increment_joint(5))
dec_rwrist=Button(frame1 , text='-',command= lambda:decrement_joint(5))

inc_gripper=Button(frame1 , text='+',command= lambda:increment_joint(6))
dec_gripper=Button(frame1 , text='-',command= lambda:decrement_joint(6))

current_points=Label(frame1,text='Current Position',width=15)
limita_inf=Label(frame1,text='Min Limit',width=15)
limita_sup=Label(frame1,text='Max Limit',width=15)
current_point_base=Label(frame1,text=str(base_read),width=15)
current_point_shoulder=Label(frame1,text=str(shoulder_read),width=15)
current_point_elbow=Label(frame1,text=str(elbow_read),width=15)
current_point_vwrist=Label(frame1,text=str(vwrist_read),width=15)
current_point_rwrist=Label(frame1,text=str(rwrist_read),width=15)
current_point_gripper=Label(frame1,text=str(gripper_read),width=15)

min_base=Label(frame1,text='20',width=5)
min_shoulder=Label(frame1,text='20',width=5)
min_elbow=Label(frame1,text='90',width=5)
min_vwrist=Label(frame1,text='60',width=5)
min_rwrist=Label(frame1,text='20',width=5)
min_gripper=Label(frame1,text='160',width=5)

max_base=Label(frame1,text='300',width=5)
max_shoulder=Label(frame1,text='120',width=5)
max_elbow=Label(frame1,text='210',width=5)
max_vwrist=Label(frame1,text='220',width=5)
max_rwrist=Label(frame1,text='270',width=5)
max_gripper=Label(frame1,text='220',width=5)

text_speed=Label(frame1,text='Speed',width=15,bg='grey')
text_step=Label(frame1,text='Step',width=15,bg='grey')

get_speed=Entry(frame1,width=10)
get_step=Entry(frame1,width=10)

set_speed=Button(frame1,text='SET',width=5,command=get_speed_d)
set_step=Button(frame1,text='SET',width=5,command=get_step_d)

options=["prog1","prog2","prog3","prog4","prog5","prog6","prog7","prog8","prog9","prog10"]
clicked=StringVar()
clicked.set(options[0])

options2=["COM1","COM2","COM3","COM4","COM5","COM6","COM7","COM8","COM9"]
clicked2=StringVar()
clicked2.set(options2[0])

Point_TEXT1=Label(frame3,text='PROGRAM SELECTION',width=28,height=1)
Point_TEXT2=Label(frame3,text='',width=2,height=1,bg='grey')
Point_TEXT=OptionMenu(frame3,clicked,* options)
Point_TEXT3=Label(frame3,text='',width=2,height=1,bg='grey')
Point_TEXT6=OptionMenu(frame3,clicked2,* options2)
Point_TEXT5=Label(frame3,text='',width=2,height=1,bg='grey')
Point_TEXT4=Button(frame3,text='SET',width=8,command=set_prog_d)

Descr1=Label(frame2,text='POINTS',width=22)
Descr2=Label(frame2,text='COORDINATES',width=22)
Descr3=Label(frame2,text='TEACH NEW POSITION',width=22)

Point1=Label(frame2,text='Point1',width=10)
Point2=Label(frame2,text='Point2',width=10)
Point3=Label(frame2,text='Point3',width=10)
Point4=Label(frame2,text='Point4',width=10)
Point5=Label(frame2,text='Point5',width=10)
Point6=Label(frame2,text='Point6',width=10)
Point7=Label(frame2,text='Point7',width=10)
Point8=Label(frame2,text='Point8',width=10)
Point9=Label(frame2,text='Point9',width=10)
Point10=Label(frame2,text='Point10',width=10)

Point1_value=Label(frame2,text=point1_str,width=20)
Point2_value=Label(frame2,text=point2_str,width=20)
Point3_value=Label(frame2,text=point3_str,width=20)
Point4_value=Label(frame2,text=point4_str,width=20)
Point5_value=Label(frame2,text=point5_str,width=20)
Point6_value=Label(frame2,text=point6_str,width=20)
Point7_value=Label(frame2,text=point7_str,width=20)
Point8_value=Label(frame2,text=point8_str,width=20)
Point9_value=Label(frame2,text=point9_str,width=20)
Point10_value=Label(frame2,text=point10_str,width=20)

Point1_teach=Button(frame2 , text='Teach P1',command= lambda:teach_point(1),width=7)
Point2_teach=Button(frame2 , text='Teach P2',command= lambda:teach_point(2),width=7)
Point3_teach=Button(frame2 , text='Teach P3',command= lambda:teach_point(3),width=7)
Point4_teach=Button(frame2 , text='Teach P4',command= lambda:teach_point(4),width=7)
Point5_teach=Button(frame2 , text='Teach P5',command= lambda:teach_point(5),width=7)
Point6_teach=Button(frame2 , text='Teach P6',command= lambda:teach_point(6),width=7)
Point7_teach=Button(frame2 , text='Teach P7',command= lambda:teach_point(7),width=7)
Point8_teach=Button(frame2 , text='Teach P8',command= lambda:teach_point(8),width=7)
Point9_teach=Button(frame2 , text='Teach P9',command= lambda:teach_point(9),width=7)
Point10_teach=Button(frame2 , text='Teach P10',command= lambda:teach_point(10),width=7)

PROG_TEXT=Label(frame4,text='PROGRAM SEQUENCE',width=68)
PROG_STATE=Label(frame5,text='SAVED PROGRAM STATE',width=18,bg='grey')

NR_OF_CYCLES=Label(frame5,text='NR OF PROGRAM CYCLES ',width=30)
NR_OF_STEPS=Label(frame5,text='NR OF STEPS FROM P1 TO PX',width=30)
P1_W8_TIME=Label(frame5,text='GO TO P1 AND WAIT -->>',width=30)
P2_W8_TIME=Label(frame5,text='GO TO P2 AND WAIT -->>',width=30)
P3_W8_TIME=Label(frame5,text='GO TO P3 AND WAIT -->>',width=30)
P4_W8_TIME=Label(frame5,text='GO TO P4 AND WAIT -->>',width=30)
P5_W8_TIME=Label(frame5,text='GO TO P5 AND WAIT -->>',width=30)
P6_W8_TIME=Label(frame5,text='GO TO P6 AND WAIT -->>',width=30)
P7_W8_TIME=Label(frame5,text='GO TO P7 AND WAIT -->>',width=30)
P8_W8_TIME=Label(frame5,text='GO TO P8 AND WAIT -->>',width=30)
P9_W8_TIME=Label(frame5,text='GO TO P9 AND WAIT -->>',width=30)
P10_W8_TIME=Label(frame5,text='GO TO P10 AND WAIT -->>',width=30)

NR_OF_CYCLES_D=Label(frame5,text='',width=6,bg='grey')
NR_OF_STEPS_D=Label(frame5,text='',width=6,bg='grey')
P1_W8_TIME_D=Label(frame5,text='',width=6,bg='grey')
P2_W8_TIME_D=Label(frame5,text='',width=6,bg='grey')
P3_W8_TIME_D=Label(frame5,text='',width=6,bg='grey')
P4_W8_TIME_D=Label(frame5,text='',width=6,bg='grey')
P5_W8_TIME_D=Label(frame5,text='',width=6,bg='grey')
P6_W8_TIME_D=Label(frame5,text='',width=6,bg='grey')
P7_W8_TIME_D=Label(frame5,text='',width=6,bg='grey')
P8_W8_TIME_D=Label(frame5,text='',width=6,bg='grey')
P9_W8_TIME_D=Label(frame5,text='',width=6,bg='grey')
P10_W8_TIME_D=Label(frame5,text='',width=6,bg='grey')

NR_OF_CYCLES_E=Entry(frame5,width=14)
NR_OF_STEPS_E=Entry(frame5,width=14)
P1_W8_TIME_E=Entry(frame5,width=14)
P2_W8_TIME_E=Entry(frame5,width=14)
P3_W8_TIME_E=Entry(frame5,width=14)
P4_W8_TIME_E=Entry(frame5,width=14)
P5_W8_TIME_E=Entry(frame5,width=14)
P6_W8_TIME_E=Entry(frame5,width=14)
P7_W8_TIME_E=Entry(frame5,width=14)
P8_W8_TIME_E=Entry(frame5,width=14)
P9_W8_TIME_E=Entry(frame5,width=14)
P10_W8_TIME_E=Entry(frame5,width=14)

NR_OF_CYCLES_D1=Label(frame5,text=str(auto_proram_cycles)+" cycles",width=18,bg='grey')
NR_OF_STEPS_D1=Label(frame5,text=str(auto_steps)+" steps",width=18,bg='grey')
P1_W8_TIME_D1=Label(frame5,text=str(auto_point1_w8)+" sec",width=18,bg='grey')
P2_W8_TIME_D1=Label(frame5,text=str(auto_point2_w8)+" sec",width=18,bg='grey')
P3_W8_TIME_D1=Label(frame5,text=str(auto_point3_w8)+" sec",width=18,bg='grey')
P4_W8_TIME_D1=Label(frame5,text=str(auto_point4_w8)+" sec",width=18,bg='grey')
P5_W8_TIME_D1=Label(frame5,text=str(auto_point5_w8)+" sec",width=18,bg='grey')
P6_W8_TIME_D1=Label(frame5,text=str(auto_point6_w8)+" sec",width=18,bg='grey')
P7_W8_TIME_D1=Label(frame5,text=str(auto_point7_w8)+" sec",width=18,bg='grey')
P8_W8_TIME_D1=Label(frame5,text=str(auto_point8_w8)+" sec",width=18,bg='grey')
P9_W8_TIME_D1=Label(frame5,text=str(auto_point9_w8)+" sec",width=18,bg='grey')
P10_W8_TIME_D1=Label(frame5,text=str(auto_point10_w8)+" sec",width=18,bg='grey')

P_TEACH_space=Label(frame5 , text='',bg='grey')
P_TEACH=Button(frame5 , text='SAVE CHANGES',command=save_program,width=22)

""" ---- RENDERING LABELS ---- """

frame0.grid(row=1)
frame1.grid(row=2)
frame2.grid(row=4)
frame3.grid(row=3)
frame4.grid(row=5)
frame5.grid(row=6)

mySection1.grid(row=1,column=0)
mySection2.grid(row=1,column=1)
mySection3.grid(row=1,column=2)

current_point_base_text.grid(row=2,column=0)
current_point_shoulder_text.grid(row=3,column=0)
current_point_elbow_text.grid(row=4,column=0)
current_point_vwrist_text.grid(row=5,column=0)
current_point_rwrist_text.grid(row=6,column=0)
current_point_gripper_text.grid(row=7,column=0)

inc_base.grid(row=2,column=1)
dec_base.grid(row=2,column=3)
inc_shoulder.grid(row=3,column=1)
dec_shoulder.grid(row=3,column=3)
inc_elbow.grid(row=4,column=1)
dec_elbow.grid(row=4,column=3)
inc_vwrist.grid(row=5,column=1)
dec_vwrist.grid(row=5,column=3)
inc_rwrist.grid(row=6,column=1)
dec_rwrist.grid(row=6,column=3)
inc_gripper.grid(row=7,column=1)
dec_gripper.grid(row=7,column=3)

current_points.grid(row=1,column=2)
current_point_base.grid(row=2,column=2)
current_point_shoulder.grid(row=3,column=2)
current_point_elbow.grid(row=4,column=2)
current_point_vwrist.grid(row=5,column=2)
current_point_rwrist.grid(row=6,column=2)
current_point_gripper.grid(row=7,column=2)

limita_inf.grid(row=1,column=4)
limita_sup.grid(row=1,column=5)

min_base.grid(row=2,column=4)
min_shoulder.grid(row=3,column=4)
min_elbow.grid(row=4,column=4)
min_vwrist.grid(row=5,column=4)
min_rwrist.grid(row=6,column=4)
min_gripper.grid(row=7,column=4)

max_base.grid(row=2,column=5)
max_shoulder.grid(row=3,column=5)
max_elbow.grid(row=4,column=5)
max_vwrist.grid(row=5,column=5)
max_rwrist.grid(row=6,column=5)
max_gripper.grid(row=7,column=5)

text_speed.grid(row=8,column=0)
text_step.grid(row=9,column=0)

get_speed.grid(row=8,column=2)
get_step.grid(row=9,column=2)

set_speed.grid(row=8,column=4)
set_step.grid(row=9,column=4)

Descr1.grid(row=1,column=0)
Descr2.grid(row=1,column=1)
Descr3.grid(row=1,column=2)

Point_TEXT.grid(row=0,column=4)
Point_TEXT1.grid(row=0,column=0)
Point_TEXT2.grid(row=0,column=1)
Point_TEXT3.grid(row=0,column=3)
Point_TEXT4.grid(row=0,column=2)
Point_TEXT5.grid(row=0,column=5)
Point_TEXT6.grid(row=0,column=6)

Point1.grid(row=2,column=0)
Point2.grid(row=3,column=0)
Point3.grid(row=4,column=0)
Point4.grid(row=5,column=0)
Point5.grid(row=6,column=0)
Point6.grid(row=7,column=0)
Point7.grid(row=8,column=0)
Point8.grid(row=9,column=0)
Point9.grid(row=10,column=0)
Point10.grid(row=11,column=0)

Point1_value.grid(row=2,column=1)
Point2_value.grid(row=3,column=1)
Point3_value.grid(row=4,column=1)
Point4_value.grid(row=5,column=1)
Point5_value.grid(row=6,column=1)
Point6_value.grid(row=7,column=1)
Point7_value.grid(row=8,column=1)
Point8_value.grid(row=9,column=1)
Point9_value.grid(row=10,column=1)
Point10_value.grid(row=11,column=1)

Point1_teach.grid(row=2,column=2)
Point2_teach.grid(row=3,column=2)
Point3_teach.grid(row=4,column=2)
Point4_teach.grid(row=5,column=2)
Point5_teach.grid(row=6,column=2)
Point6_teach.grid(row=7,column=2)
Point7_teach.grid(row=8,column=2)
Point8_teach.grid(row=9,column=2)
Point9_teach.grid(row=10,column=2)
Point10_teach.grid(row=11,column=2)

PROG_TEXT.grid(row=0,column=0)

PROG_STATE.grid(row=0,column=3)

NR_OF_CYCLES.grid(row=1,column=0)
NR_OF_STEPS.grid(row=2,column=0)
P1_W8_TIME.grid(row=3,column=0)
P2_W8_TIME.grid(row=4,column=0)
P3_W8_TIME.grid(row=5,column=0)
P4_W8_TIME.grid(row=6,column=0)
P5_W8_TIME.grid(row=7,column=0)
P6_W8_TIME.grid(row=8,column=0)
P7_W8_TIME.grid(row=9,column=0)
P8_W8_TIME.grid(row=10,column=0)
P9_W8_TIME.grid(row=11,column=0)
P10_W8_TIME.grid(row=12,column=0)

NR_OF_CYCLES_D.grid(row=1,column=1)
NR_OF_STEPS_D.grid(row=2,column=1)
P1_W8_TIME_D.grid(row=3,column=1)
P2_W8_TIME_D.grid(row=4,column=1)
P3_W8_TIME_D.grid(row=5,column=1)
P4_W8_TIME_D.grid(row=6,column=1)
P5_W8_TIME_D.grid(row=7,column=1)
P6_W8_TIME_D.grid(row=8,column=1)
P7_W8_TIME_D.grid(row=9,column=1)
P8_W8_TIME_D.grid(row=10,column=1)
P9_W8_TIME_D.grid(row=11,column=1)
P10_W8_TIME_D.grid(row=12,column=1)

NR_OF_CYCLES_E.grid(row=1,column=2)
NR_OF_STEPS_E.grid(row=2,column=2)
P1_W8_TIME_E.grid(row=3,column=2)
P2_W8_TIME_E.grid(row=4,column=2)
P3_W8_TIME_E.grid(row=5,column=2)
P4_W8_TIME_E.grid(row=6,column=2)
P5_W8_TIME_E.grid(row=7,column=2)
P6_W8_TIME_E.grid(row=8,column=2)
P7_W8_TIME_E.grid(row=9,column=2)
P8_W8_TIME_E.grid(row=10,column=2)
P9_W8_TIME_E.grid(row=11,column=2)
P10_W8_TIME_E.grid(row=12,column=2)

NR_OF_CYCLES_D1.grid(row=1,column=3)
NR_OF_STEPS_D1.grid(row=2,column=3)
P1_W8_TIME_D1.grid(row=3,column=3)
P2_W8_TIME_D1.grid(row=4,column=3)
P3_W8_TIME_D1.grid(row=5,column=3)
P4_W8_TIME_D1.grid(row=6,column=3)
P5_W8_TIME_D1.grid(row=7,column=3)
P6_W8_TIME_D1.grid(row=8,column=3)
P7_W8_TIME_D1.grid(row=9,column=3)
P8_W8_TIME_D1.grid(row=10,column=3)
P9_W8_TIME_D1.grid(row=11,column=3)
P10_W8_TIME_D1.grid(row=12,column=3)

P_TEACH_space.grid(row=13,column=0,columnspan=4)

P_TEACH.grid(row=14,column=0,columnspan=1)
print("MAIN THREAD STARTED")
""" ---- SYSTEM CALL ---- """
root.after(1000,update_degrees())
if mode==1:
	root.after(1500,start_auto())
root.mainloop() # will continous looping (infinite while)

BRACIO ++ Python Controller/Python PROG/gui_tkinter.py


import datetime as dt
import logging
import re
from functools import wraps
from typing import Callable, Union
from threading import local

g = local()
log = logging.getLogger('alexa')

def statement(s: str, reprompt: str = None, card_title: str = None, should_end_session: bool = True) -> dict:
    '''Return a plain-text statement.

    :param s: the statement itself
    :param reprompt: text for Alexa to issue if response was not understood
    :param card_title: card title for Echo devices with screens
    :param should_end_session: whether to end the current session or not
    '''
    response = {
        'outputSpeech': {
            'type': 'PlainText',
            'text': s
        },
        'shouldEndSession': should_end_session
    }
    if card_title:
        response['card'] = {
            'type': 'Simple',
            'title': card_title,
            'content': s
        }
    if reprompt:
        response['reprompt'] = {
            'outputSpeech': {
                'type': 'PlainText',
                'text': reprompt
            }
        }

    return response

def question(q: str, reprompt: str = None) -> dict:
    '''Return a plain-text question.

    :param q: the question
    :param reprompt: the plain-text for Alexa to issue if response was not
        understood
    '''
    response = {
        'outputSpeech': {
            'type': 'PlainText',
            'text': q,
        },
        'should_end_session': False
    }
    if reprompt:
        response['reprompt'] = {
            'outputSpeech': {
                'type': 'PlainText',
                'text': reprompt,
            }
        }
    return response

class Alexa:
    '''The main application interface.'''

    def __init__(self, name: str):
        self.name = name
        self._launch_func = None
        self._session_ended_func = None
        self._intent_view_funcs = {}

    def launch(self, func: Callable[[], None]) -> None:
        '''Register (or overwrite) a function to be called when the Lambda
        is launched.

        :param func: the function to call when a LaunchRequest event is
            received.'''
        self._launch_func = func

    def session_ended(self, func: Callable[[], None]) -> None:
        '''Register (or overwrite) a function to be called when the session
        is ended.

        :param func: the function to call when a SessionEndedRequest event is
            received.'''
        self._session_ended_func = func

    def intent(self, name: str):
        '''Decorator used to register the response to an intent.

        :param name: the name of the intent (should match what is in the alexa
            console).'''
        def decorator(f):
            self._intent_view_funcs[name] = f
            @wraps(f)
            def wrapper(*args, **kwargs):
                return f(*args, **kwargs)
            return wrapper
        return decorator

    def build_response(self, response: Union[str, dict]):
        global g

        if response is None:
            return None

        if isinstance(response, str):
            response = statement(response)

        return {
            'version': '1.0',
            'sessionAttirbutes': g.session.get('attributes', {}),
            'response': response,
        }

    def handle_lambda_event(self, event: dict, ctx: dict):
        '''Main entry point / handler for an AWS Lambda.

        :param event: the event payload
        :param ctx: the Lambda context'''
        global g
        assert isinstance(event, dict)
        g.session = event['session']
        g.request = event['request']
        g.context = ctx

        rtype = g.request.get('type')
        intent = g.request.get('intent', {})
        intent_name = intent.get('name', '')

        log.info(f'Received {rtype!r} request.')

        response = None
        if rtype == 'LaunchRequest' and self._launch_func:
            response = self._launch_func()
        elif rtype == 'IntentRequest':
            if intent_name not in self._intent_view_funcs:
                raise ValueError(f'No handler for {intent_name!r} intent.')

            kwargs = {k: v.get('value') for k, v in intent.get('slots', {}).items()}
            response = self._intent_view_funcs[intent_name](**kwargs)
        elif rtype == 'SessionEndedRequest' and self._session_ended_func:
            response = self._session_ended_func(request)

        return self.build_response(response)


import paramiko

ssh = paramiko.SSHClient() # 22
ssh.set_missing_host_key_policy(paramiko.AutoAddPolicy())
ssh.connect('xxx.xx.xx.xx', 54321, 'Alex', 'xxxxx!')

stdin, stdout, stderr = ssh.exec_command('df')
print(stdout.read().decode("utf-8"))
ssh.close();


internalActivityTypes = [
    'Admin',
    'Conferences',
    'Demo',
    'Champions - SME program',
    'Internal Enablement',
    'Internal Event Support',
    'Management or Team Activities',
    'Meetings',
    'Paid Time Off, Holiday',
    'POC',
    'Recruiting',
    'Service Learning',
    'Training'
]

internalActivityStatuses = [
    'Not Started',
    'In Progress',
    'Completed'
]


# -*- coding: utf-8 -*-
import scrapy
from datetime import datetime,timedelta
from scrapy.spiders import CrawlSpider
from secondHand.items import SecondhandItem

class dospySpider(CrawlSpider):
    name = 'dospy'
    allowed_domains = ['dospy.com']

    def start_requests(self):
        urls = ['http://bbs.dospy.com/forumdisplay.php?fid=141&orderby=dateline&page=' + str(i)  for i in range(1,2)]
        for url in urls:
            yield scrapy.Request(url=url, callback=self.parse)
    def parse(self,response):
        rx = response.xpath("//table[contains(@class,'word txt_666')]/tr")
        utcTime = datetime.utcnow().replace(second=0,microsecond=0)

        for it in rx:
           replyTime = it.xpath('td[4]/u/text()').extract()
           replyCount = it.xpath('td[3]/a/text()').extract()
           if len(replyCount)==0:
               continue
           else:
               replyCount=replyCount[0]
           if int(replyCount)==0:
               finalTime = datetime.strptime(replyTime[0]+':00','%Y-%m-%d %H:%M:%S')
               finalTime = finalTime + timedelta(hours=-8)
           else:
               finalTime = utcTime

           item = SecondhandItem()
           item['title'] = it.xpath('th/a/text()').extract()
           item['uname'] = it.xpath('td[2]/cite/a/text()').extract()
           item['time'] = finalTime
           item['reply_count'] = replyCount
           item['create_time'] = utcTime
           item['webname'] = self.name
           item['url'] = 'http://bbs.dospy.com/'+it.xpath('th/a/@href').extract()[0]

           item['view_count'] = it.xpath('td[3]/em/text()').extract()
           item['price'] = ''
           item['location'] = ''
           item['ext4'] = ''
           item['ext5'] = ''
           yield item


"""
Escreva um programa que verifique quais números entre 1000 e 9999 (inclusive)
possuem a seguinte propriedade: a soma dos dois dígitos de mais baixa ordem com os dois
digitos de mais alta ordem elevada ao quadrado é igual ao próprio número. Por exemplo,
para o inteiro 3025, temos que:
    30 + 25 = 55
    55² = 3025
"""

soma = 0

for i in range(1000, 10000):
    soma = ((i // 100) + (i % 100))
    if ((soma * soma) == i):
        print(f"Os números entre 1000 e 9999 que possui a mesma propriedade são: {i}")


import os
import os.path as osp

import torch
from torch.utils.data import DataLoader

from byob.config import data_dir, model_dir, DATA_CONFIG
from byob.data_utils import setup_dataset_vec
from byob.models.item2vec import SkipGramModel
from byob.utils import read_pickle, as_tensor

conf = {
    'device': 'cuda' if torch.cuda.is_available() else 'cpu',
    'dataset': 'yoochoose',  # ('movielens', 'yoochoose')
    'context_size': 5,
    'neg_samples': 15,
    'embed_dim': 32,
    'hidden_dim': 64,
    'num_epochs': 10,
    'batch_size': 256,
    'lr': 0.001
}
conf.update(DATA_CONFIG[conf['dataset']])
pkl_file = osp.join(data_dir, conf['dataset'], conf['item_vocab'])
vocab = read_pickle(pkl_file)
conf['vocab_size'] = len(vocab)
assert conf['n_item'] == conf['vocab_size']
print(conf)

# pkl_file = os.path.join(data_dir, conf['dataset'], 'dataset.pkl')
# # write_pickle(pkl_file, dataset)
# dataset = read_pickle(pkl_file)

csv_file = osp.join(data_dir, conf['dataset'], 'seqs.csv')
dataset = setup_dataset_vec(csv_file, vocab, c=conf['context_size'], k=conf['neg_samples'])
loader = DataLoader(dataset, conf['batch_size'], shuffle=True)

model = SkipGramModel(conf).to(conf['device'])
optimizer = torch.optim.SGD(model.parameters(), lr=conf['lr'])

losses = []
for epoch in range(1, conf['num_epochs'] + 1):

    # csv_file = osp.join(data_dir, conf['dataset'], 'seqs.csv')
    # dataset = setup_dataset_vec(csv_file, vocab, c=conf['context_size'], k=conf['neg_samples'])
    # loader = DataLoader(dataset, conf['batch_size'], shuffle=True)

    total_loss = 0.0
    steps_per_epoch = int(len(loader.dataset) / conf['batch_size'])
    for i, batch in enumerate(loader):
        batch = as_tensor(*batch, dtype=torch.long, device=conf['device'])
        # print(batch)
        # model.zero_grad()
        optimizer.zero_grad()
        loss = model(batch)
        loss.backward()
        optimizer.step()
        total_loss += loss.item()
        if i > 0 and i % 1000 == 0:
            print(f'epoch: {epoch}/{conf["num_epochs"]}, iteration: {i}/{len(loader)}, loss: {loss.item()}')

    file_name = '%s-%s-%d.pt' % (conf['dataset'], type(model).__name__, epoch)
    path = os.path.join(model_dir, file_name)
    model.save_model(path)

    file_name = '%s-%s-%d.npy' % (conf['dataset'], type(model).__name__, epoch)
    path = os.path.join(model_dir, file_name)
    model.save_embedding(path)

    losses.append(total_loss / steps_per_epoch)

print(losses)

file_name = '%s-%s.pt' % (conf['dataset'], type(model).__name__)
path = os.path.join(model_dir, file_name)
model.save_model(path)

file_name = '%s-%s.npy' % (conf['dataset'], type(model).__name__)
path = os.path.join(model_dir, file_name)
model.save_embedding(path)


#credits to https://www.geeksforgeeks.org/linear-regression-python-implementation/
# for skeleton of code
import matplotlib.pyplot as plt
import numpy as np
from sklearn import linear_model
import os
import csv
dirname = os.path.dirname(__file__)

relative_path_to_file = '../data/preprocessed_files/rbi/crop_data_pairs.csv'
filename = os.path.join(dirname, relative_path_to_file)
file = open(filename)
csvreader = csv.reader(file)
x_axis_vals = []
y_axis_vals = []

for row in csvreader:

    x_axis_vals.append(row[0:-1])
    y_axis_vals.append(row[-1])
file.close()
X = np.array(x_axis_vals).astype(np.float)
y = np.array(y_axis_vals).astype(np.float)

# splitting X and y into training and testing sets
from sklearn.model_selection import train_test_split
X_train, X_test, y_train, y_test = train_test_split(X, y, test_size=0.4,
													random_state=1)

# create linear regression object
reg = linear_model.LinearRegression()

# train the model using the training sets
reg.fit(X_train, y_train)

# regression coefficients
print('Coefficients: ', reg.coef_)

# variance score: 1 means perfect prediction
print('Variance score: {}'.format(reg.score(X_test, y_test)))

print("printing shape of train data - data first, label 2nd")
print(X_train.shape)
print(y_train.shape)

print("printing shape of test data -data first, label 2nd")
print(X_test.shape)
print(y_test.shape)
# plot for residual error
def plot_variance():
	## setting plot style
	plt.style.use('fivethirtyeight')

	## plotting residual errors in training data
	plt.scatter(reg.predict(X_train), reg.predict(X_train) - y_train,
				color="green", s=10, label='Train data')

	## plotting residual errors in test data
	plt.scatter(reg.predict(X_test), reg.predict(X_test) - y_test,
				color="blue", s=10, label='Test data')

	## plotting line for zero residual error
	# plt.hlines(y=reg.score(X_train, y_train),xmin=0,xmax=3500,linewidth=2,color='b',label='closeness score of train data')
	plt.hlines(y=reg.score(X_test, y_test), xmin=0, xmax=3500, linewidth=2, color='r',
			   label='closeness score of test data')

	## plotting legend
	plt.legend(loc='lower right')

	## plot title
	plt.title("Closeness to true total cereal production in lakh tonnes from 1950-2021")

	## method call for showing the plot
	plt.show()
plot_variance()


# a = 10
# b = 25
# c = 66
#
# x = int(input("Digite um número: "))
#
# #if( x == a or x == b or x == c):
# if(x in [a, b, c]):
#     print("o numero está contido!")
# else:
#     print("O numero não esta contido")

#-------------------------------------------------------------------------

cores = ["Azul", "vermelho", "amarelo", "branco"]

while True:
    cor = input("Digite o nome de uma cor ou 0 para sair: ")

    if(cor == "0"):
        break
    if cor in cores:
        print("A cor esta contida e é a cor: " + cor)
    else:
        print("A cor não esta contida")


# Module Import List
import cv2
import os
import csv
import matplotlib.pyplot as plt
from numpy import*
from sklearn.model_selection import train_test_split
import sklearn
from PIL import Image
import keras.backend as K
from keras.models import Sequential
from keras.layers import Dense, Activation, Flatten, Dropout, Lambda
from keras.layers import Conv2D, MaxPooling2D, convolutional
from keras.layers import Convolution2D, Cropping2D
from keras.callbacks import EarlyStopping # To interrupt if loss not increasing

# Samples list is accumulated from the csv file by opening the file and reading each row
samples = []
with open('/home/carnd/CarND-Behavioral-Cloning-P3/data/driving_log_clean.csv') as csvfile:
    reader = csv.reader(csvfile)
    for line in reader:
        samples.append(line)

# Samples list is split into training and test/validation sample data
train_samples, validation_samples = train_test_split(samples, test_size = 0.2)

# Generator used to batch images and train the model faster by avoiding memory overlaod
def generator(samples, batch_size = 32):
    num_samples = len(samples)
    while 1:
        sklearn.utils.shuffle(samples)
        for offset in range(0, num_samples, batch_size):
            batch_samples = samples[offset:offset+batch_size]

# Lists for collecting image and angles
            images = []
            angles = []
            for batch_sample in batch_samples:

#Center image and angle information extracted
                name_center = '/home/carnd/CarND-Behavioral-Cloning-P3/data/CIMG/' + batch_sample[0].split('/')[-1]
                center_image = cv2.imread(name_center)
                center_angle = float(batch_sample[3])
                images.append(center_image)
                angles.append(center_angle)
                center_image_f = cv2.flip(center_image,1)
                center_angle_f = center_angle*-1.0
                images.append(center_image_f)
                angles.append(center_angle_f)

#Left image and angle information extracted
                name_left = '/home/carnd/CarND-Behavioral-Cloning-P3/data/CIMG/' + batch_sample[1].split('/')[-1]
                left_image = cv2.imread(name_left)
                left_angle = float(batch_sample[3])+0.1
                images.append(left_image)
                angles.append(left_angle)
                left_image_f = cv2.flip(left_image,1)
                left_angle_f = left_angle*-1.0
                images.append(left_image_f)
                angles.append(left_angle_f)

#Right image and angle information extracted
                name_right = '/home/carnd/CarND-Behavioral-Cloning-P3/data/CIMG/' + batch_sample[2].split('/')[-1]
                right_image = cv2.imread(name_right)
                right_angle = float(batch_sample[3])-0.1
                images.append(right_image)
                angles.append(right_angle)
                right_image_f = cv2.flip(right_image,1)
                right_angle_f = right_angle*-1.0
                images.append(right_image_f)
                angles.append(right_angle_f)

# Training data in each batch has 96 samples, 3 times the batch size due
# to addition of left and right images
            X_train = array(images)
            y_train = array(angles)
            yield sklearn.utils.shuffle(X_train,y_train)

# Batch size defined
batch_size = 32

# training and validation generators defined for the fit_generator()
train_generator = generator(train_samples, batch_size)
validation_generator = generator(validation_samples, batch_size)

#NVIDIA CNN used with cropping, mean centralization and normalization
model = Sequential()
model.add(Cropping2D(cropping=((70,25), (0,0)), input_shape=(160,320,3)))
model.add(Lambda(lambda x: (x/255.0) -0.5,input_shape=(55,320,3)))
model.add(Conv2D(24,(5,5),strides = 2,activation='relu'))
model.add(Conv2D(36,(5,5),strides = 2,activation='relu'))
model.add(Conv2D(48,(5,5),strides = 2,activation='relu'))
model.add(Conv2D(64,(3,3),activation='relu'))
#model.add(Conv2D(64,(3,3),activation='relu'))
model.add(Flatten())
model.add(Dense(100))
model.add(Dense(50))
model.add(Dense(10))
model.add(Dense(1))

model.compile(loss = 'mse', optimizer = 'adam')
history_object = model.fit_generator(train_generator, steps_per_epoch = len(train_samples)/batch_size, validation_data = validation_generator, validation_steps = len(validation_samples)/batch_size,epochs=3,verbose = 1)

print(history_object.history.keys())
plt.plot(history_object.history['loss'])
plt.plot(history_object.history['val_loss'])
plt.title('model mean squared error loss')
plt.ylabel('mean squared error loss')
plt.xlabel('epoch')
plt.legend(['training set', 'validation set'], loc='upper right')
plt.show()

model.save('model.h5')


from .db import db
from sqlalchemy.sql import func

project_categories = db.Table(
    "project-categories",
    db.Column("projectId", db.ForeignKey(
        "projects.id"), primary_key=True),
    db.Column("categoryId", db.ForeignKey(
        "categories.id"), primary_key=True),
)

class Category(db.Model):
    __tablename__ = 'categories'

    id = db.Column(db.Integer, primary_key=True)
    name = db.Column(db.String(25), nullable=False, index=True)
    createdAt = db.Column(db.DateTime(timezone=True),
                          nullable=False, server_default=func.now())
    updatedAt = db.Column(db.DateTime(timezone=True),
                          nullable=False, server_default=func.now(), onupdate=func.now())

    projects = db.relationship(
        "Project", secondary=project_categories, back_populates="categories")

    def to_dict(self):
        return {
            'id': self.id,
            'name': self.name,
            "projectIds": [project.id for project in self.projects]
        }


"""
Module to provide a tokenization of a markdown-encoded string.
"""
import logging
import os
from typing import List, Optional, Tuple, cast

from application_properties import ApplicationProperties

from pymarkdown.coalesce.coalesce_processor import CoalesceProcessor
from pymarkdown.container_blocks.container_block_processor import (
    ContainerBlockProcessor,
)
from pymarkdown.container_blocks.parse_block_pass_properties import (
    ParseBlockPassProperties,
)
from pymarkdown.extension_manager.extension_manager import ExtensionManager
from pymarkdown.extensions.front_matter_extension import FrontMatterExtension
from pymarkdown.extensions.pragma_token import PragmaToken
from pymarkdown.general.bad_tokenization_error import BadTokenizationError
from pymarkdown.general.parser_helper import ParserHelper
from pymarkdown.general.parser_logger import ParserLogger
from pymarkdown.general.parser_state import ParserState
from pymarkdown.general.position_marker import PositionMarker
from pymarkdown.general.requeue_line_info import RequeueLineInfo
from pymarkdown.general.source_providers import InMemorySourceProvider, SourceProvider
from pymarkdown.html.html_helper import HtmlHelper
from pymarkdown.inline.inline_character_reference_helper import (
    InlineCharacterReferenceHelper,
)
from pymarkdown.inline.inline_processor import InlineProcessor
from pymarkdown.leaf_blocks.leaf_block_helper import LeafBlockHelper
from pymarkdown.leaf_blocks.leaf_block_processor_paragraph import (
    LeafBlockProcessorParagraph,
)
from pymarkdown.links.link_parse_helper import LinkParseHelper
from pymarkdown.links.link_reference_definition_helper import (
    LinkReferenceDefinitionHelper,
)
from pymarkdown.tokens.blank_line_markdown_token import BlankLineMarkdownToken
from pymarkdown.tokens.block_quote_markdown_token import BlockQuoteMarkdownToken
from pymarkdown.tokens.end_of_stream_token import EndOfStreamToken
from pymarkdown.tokens.list_start_markdown_token import ListStartMarkdownToken
from pymarkdown.tokens.markdown_token import MarkdownToken
from pymarkdown.tokens.stack_token import (
    BlockQuoteStackToken,
    DocumentStackToken,
    ParagraphStackToken,
    StackToken,
)

POGGER = ParserLogger(logging.getLogger(__name__))

class TokenizedMarkdown:
    """
    Class to provide a tokenization of a markdown-encoded string.
    """

    def __init__(self, resource_path: Optional[str] = None) -> None:
        """
        Initializes a new instance of the TokenizedMarkdown class.
        """

        self.__tokenized_document: List[MarkdownToken] = []
        self.__token_stack: List[StackToken] = []
        self.__parse_properties: Optional[ParseBlockPassProperties] = None
        self.__source_provider: Optional[SourceProvider] = None

        if not resource_path:
            resource_path = os.path.join(os.path.split(__file__)[0], "..", "resources")
            resource_path = os.path.abspath(resource_path)
        InlineCharacterReferenceHelper.initialize(resource_path)

    def apply_configuration(
        self,
        application_properties: ApplicationProperties,
        extension_manager: ExtensionManager,
    ) -> None:
        """
        Apply any configuration map.
        """
        _ = application_properties
        self.__parse_properties = ParseBlockPassProperties(extension_manager)

    def transform_from_provider(
        self,
        source_provider: Optional[SourceProvider],
        do_add_end_of_stream_token: bool = False,
    ) -> List[MarkdownToken]:
        """
        Transform the data from the source provider into a Markdown token stream.
        """
        self.__source_provider = source_provider
        return self.__transform(do_add_end_of_stream_token)

    def transform(
        self,
        your_text_string: str,
        show_debug: bool = False,
        do_add_end_of_stream_token: bool = False,
    ) -> List[MarkdownToken]:
        """
        Transform a text string in a Markdown format into a Markdown token stream.
        This function should only be used as a simplified manner of accessing the
        functionality for the purposes of testing.
        """

        logging.getLogger().setLevel(logging.DEBUG if show_debug else logging.WARNING)
        ParserLogger.sync_on_next_call()
        self.__source_provider = InMemorySourceProvider(your_text_string)
        return self.__transform(do_add_end_of_stream_token)

    def __transform(self, do_add_end_of_stream_token: bool) -> List[MarkdownToken]:
        """
        Transform a markdown-encoded string into an array of tokens.
        """
        try:
            self.__tokenized_document = []
            self.__token_stack = []

            InlineProcessor.initialize()
            LinkParseHelper.initialize()

            POGGER.debug("\n\n>>>>>>>parse_blocks_pass>>>>>>")
            first_pass_results = self.__parse_blocks_pass(do_add_end_of_stream_token)

            POGGER.debug("\n\n>>>>>>>coalesce_text_blocks>>>>>>")
            coalesced_results = CoalesceProcessor.coalesce_text_blocks(
                first_pass_results
            )

            POGGER.debug("\n\n>>>>>>>parse_inline>>>>>>")
            final_pass_results = InlineProcessor.parse_inline(coalesced_results)

            POGGER.debug("\n\n>>>>>>>final_pass_results>>>>>>")
            return final_pass_results
        except Exception as this_exception:
            raise BadTokenizationError(
                "An unhandled error occurred processing the document."
            ) from this_exception

    def __parse_blocks_pass(
        self, do_add_end_of_stream_token: bool
    ) -> List[MarkdownToken]:
        """
        The first pass at the tokens is to deal with blocks.
        """

        assert self.__parse_properties is not None
        assert self.__source_provider is not None
        self.__token_stack = [DocumentStackToken()]
        self.__tokenized_document = []
        self.__parse_properties.pragma_lines = {}

        POGGER.debug("---")
        try:
            first_line_in_document, line_number = (
                self.__source_provider.get_next_line(),
                1,
            )
            POGGER.debug("---$---", first_line_in_document)
            (
                first_line_in_document,
                line_number,
                requeue,
            ) = self.__process_front_matter_header_if_present(
                first_line_in_document, line_number, []
            )
            (
                did_start_close,
                did_started_close,
                keep_on_going,
                ignore_link_definition_start,
            ) = (first_line_in_document is None, False, True, False)
            next_line_in_document = first_line_in_document
            while keep_on_going:
                (
                    keep_on_going,
                    did_start_close,
                    did_started_close,
                    ignore_link_definition_start,
                    requeue,
                    line_number,
                    next_line_in_document,
                ) = self.__parse_blocks_pass_next_line(
                    next_line_in_document,
                    line_number,
                    requeue,
                    did_start_close,
                    did_started_close,
                    ignore_link_definition_start,
                )
        except AssertionError as this_exception:
            error_message = f"A project assertion failed on line {line_number} of the current document."
            raise BadTokenizationError(error_message) from this_exception

        if do_add_end_of_stream_token:
            self.__tokenized_document.append(EndOfStreamToken(line_number))

        if self.__parse_properties.pragma_lines:
            self.__tokenized_document.append(
                PragmaToken(self.__parse_properties.pragma_lines)
            )
        return self.__tokenized_document

    # pylint: disable=too-many-arguments
    def __parse_blocks_pass_next_line(
        self,
        next_line_in_document: Optional[str],
        line_number: int,
        requeue: List[str],
        did_start_close: bool,
        did_started_close: bool,
        ignore_link_definition_start: bool,
    ) -> Tuple[bool, bool, bool, bool, List[str], int, Optional[str]]:
        POGGER.debug("next-line>>$", next_line_in_document)
        POGGER.debug("stack>>$", self.__token_stack)
        POGGER.debug("current_block>>$", self.__token_stack[-1])
        POGGER.debug("line_number>>$", line_number)
        POGGER.debug("---")

        parser_state = ParserState(
            self.__token_stack,
            self.__tokenized_document,
            TokenizedMarkdown.__close_open_blocks,
            self.__handle_blank_line,
        )
        keep_on_going = True
        if did_start_close:
            (
                did_started_close,
                did_start_close,
                tokens_from_line,
                line_number,
                keep_on_going,
                requeue_line_info,
            ) = self.__main_pass_did_start_close(parser_state, line_number)
        else:
            assert next_line_in_document is not None
            position_marker = PositionMarker(line_number, 0, next_line_in_document)
            (
                tfl,
                requeue_line_info,
            ) = self.__main_pass_did_not_start_close(
                parser_state,
                position_marker,
                next_line_in_document,
                ignore_link_definition_start,
            )
            assert tfl is not None
            tokens_from_line = tfl

        if keep_on_going:
            (
                line_number,
                ignore_link_definition_start,
                next_line_in_document,
                did_start_close,
                did_started_close,
            ) = self.__main_pass_keep_on_going(
                line_number,
                requeue_line_info,
                requeue,
                tokens_from_line,
                did_start_close,
                did_started_close,
            )
        return (
            keep_on_going,
            did_start_close,
            did_started_close,
            ignore_link_definition_start,
            requeue,
            line_number,
            next_line_in_document,
        )

    # pylint: enable=too-many-arguments

    def __main_pass_did_start_close(
        self, parser_state: ParserState, line_number: int
    ) -> Tuple[bool, bool, List[MarkdownToken], int, bool, Optional[RequeueLineInfo]]:
        POGGER.debug("\n\ncleanup")

        was_link_definition_started_before_close = self.__token_stack[
            -1
        ].was_link_definition_started
        (
            tokens_from_line,
            requeue_line_info,
        ) = TokenizedMarkdown.__close_open_blocks(
            parser_state,
            self.__tokenized_document,
            include_block_quotes=True,
            include_lists=True,
            caller_can_handle_requeue=True,
            was_forced=True,
        )
        if not self.__tokenized_document:
            self.__tokenized_document.extend(tokens_from_line)

        keep_on_going = bool(requeue_line_info and requeue_line_info.lines_to_requeue)
        did_start_close = not keep_on_going
        if keep_on_going:
            assert was_link_definition_started_before_close
            assert requeue_line_info is not None
            assert not requeue_line_info.lines_to_requeue[0]

            del requeue_line_info.lines_to_requeue[0]
            line_number -= 1

            tokens_from_line = []
        return (
            True,
            did_start_close,
            tokens_from_line,
            line_number,
            keep_on_going,
            requeue_line_info,
        )

    def __main_pass_did_not_start_close(
        self,
        parser_state: ParserState,
        position_marker: PositionMarker,
        next_line_in_document: str,
        ignore_link_definition_start: bool,
    ) -> Tuple[Optional[List[MarkdownToken]], Optional[RequeueLineInfo]]:
        POGGER.debug(">>>>$", self.__tokenized_document)

        if not next_line_in_document or not next_line_in_document.strip():
            POGGER.debug("call __parse_blocks_pass>>handle_blank_line")
            (
                tokens_from_line,
                requeue_line_info,
            ) = self.__handle_blank_line(
                parser_state,
                next_line_in_document,
                from_main_transform=True,
                position_marker=position_marker,
            )
        else:
            POGGER.debug("\n\nnormal lines")
            assert self.__parse_properties is not None
            (
                tokens_from_line,
                _,
                _,
                requeue_line_info,
                _,
                _,
            ) = ContainerBlockProcessor.parse_line_for_container_blocks(
                parser_state,
                position_marker,
                ignore_link_definition_start,
                self.__parse_properties,
                0,
            )

        POGGER.debug("<<<<$", self.__tokenized_document)

        return tokens_from_line, requeue_line_info

    # pylint: disable=too-many-arguments
    def __main_pass_keep_on_going(
        self,
        line_number: int,
        requeue_line_info: Optional[RequeueLineInfo],
        requeue: List[str],
        tokens_from_line: List[MarkdownToken],
        did_start_close: bool,
        did_started_close: bool,
    ) -> Tuple[int, bool, Optional[str], bool, bool]:
        (
            line_number,
            ignore_link_definition_start,
        ) = TokenizedMarkdown.__handle_parse_increment_line(
            line_number, requeue_line_info, requeue
        )

        POGGER.debug(
            "---\nbefore>>$",
            self.__tokenized_document,
        )
        POGGER.debug("before>>$", tokens_from_line)
        self.__tokenized_document.extend(tokens_from_line)
        POGGER.debug(
            "after>>$",
            self.__tokenized_document,
        )
        if requeue:
            POGGER.debug("requeue>>$", requeue)
        POGGER.debug("---")

        (
            next_line_in_document,
            did_start_close,
            did_started_close,
        ) = self.__determine_next_line_to_process(
            requeue, did_start_close, did_started_close
        )
        return (
            line_number,
            ignore_link_definition_start,
            next_line_in_document,
            did_start_close,
            did_started_close,
        )

    # pylint: enable=too-many-arguments

    @staticmethod
    def __handle_parse_increment_line(
        line_number: int,
        requeue_line_info: Optional[RequeueLineInfo],
        requeue: List[str],
    ) -> Tuple[int, bool]:
        if requeue_line_info:
            number_of_lines_to_requeue = len(requeue_line_info.lines_to_requeue)
            POGGER.debug("\n\n---lines_to_requeue>>$", number_of_lines_to_requeue)
            line_number -= number_of_lines_to_requeue - 1

            for i in requeue_line_info.lines_to_requeue:
                requeue.insert(0, i)
            ignore_link_definition_start = requeue_line_info.force_ignore_first_as_lrd
        else:
            ignore_link_definition_start = False
            line_number += 1
        POGGER.debug("line_number>>$\n---", line_number)

        return line_number, ignore_link_definition_start

    def __determine_next_line_to_process(
        self, requeue: List[str], did_start_close: bool, did_started_close: bool
    ) -> Tuple[Optional[str], bool, bool]:
        """
        For the parse_blocks_pass function, determine the next token to parse.
        """

        next_line_in_document: Optional[str] = None
        if requeue:
            POGGER.debug(">>Requeues present")
            next_line_in_document = requeue[0]
            del requeue[0]
            POGGER.debug(">>Requeue>>$", next_line_in_document)
            POGGER.debug(">>Requeues left>>$", requeue)
        elif did_started_close:
            did_start_close = True
        else:
            assert self.__source_provider is not None
            next_line_in_document = self.__source_provider.get_next_line()
            if next_line_in_document is None:
                did_start_close = True

        return next_line_in_document, did_start_close, did_started_close

    @staticmethod
    def __close_open_blocks_log_args(
        include_block_quotes: bool,
        include_lists: bool,
        until_this_index: int,
        caller_can_handle_requeue: bool,
        was_forced: bool,
    ) -> None:
        if include_block_quotes:
            POGGER.debug("cob-include_block_quotes>>$", include_block_quotes)
        if include_lists:
            POGGER.debug("cob-include_lists>>$", include_lists)
        if until_this_index != -1:
            POGGER.debug("cob-until_this_index>>$", until_this_index)
        if caller_can_handle_requeue:
            POGGER.debug("cob-caller_can_handle_requeue>>$", caller_can_handle_requeue)
        if was_forced:
            POGGER.debug("cob-was_forced>>$", was_forced)

    # pylint: disable=too-many-arguments
    @staticmethod
    def __close_open_blocks(  # noqa: C901
        parser_state: ParserState,
        destination_array: Optional[List[MarkdownToken]] = None,
        only_these_blocks: Optional[List[type]] = None,
        include_block_quotes: bool = False,
        include_lists: bool = False,
        until_this_index: int = -1,
        caller_can_handle_requeue: bool = False,
        requeue_reset: bool = False,
        was_forced: bool = False,
    ) -> Tuple[List[MarkdownToken], Optional[RequeueLineInfo]]:
        """
        Close any open blocks that are currently on the stack.
        """

        requeue_line_info = None
        new_tokens = destination_array or []
        POGGER.debug("cob-start>>$", parser_state.token_stack)
        POGGER.debug(
            "cob-start>>$",
            parser_state.token_document,
        )
        if only_these_blocks:
            POGGER.debug("cob-only_these_blocks>>$", only_these_blocks)
        TokenizedMarkdown.__close_open_blocks_log_args(
            include_block_quotes,
            include_lists,
            until_this_index,
            caller_can_handle_requeue,
            was_forced,
        )
        while not parser_state.token_stack[-1].is_document:
            was_close_forced = was_forced

            (
                can_continue,
                adjusted_tokens,
                requeue_line_info,
                was_close_forced,
            ) = TokenizedMarkdown.__process_next_close_element(
                parser_state,
                was_close_forced,
                caller_can_handle_requeue,
                until_this_index,
                include_lists,
                include_block_quotes,
                only_these_blocks,
            )
            if not can_continue:
                break

            new_tokens.extend(adjusted_tokens)

        POGGER.debug("cob-end>>$", parser_state.token_stack)
        POGGER.debug("cob-end>>$", parser_state.token_document)
        POGGER.debug("cob-end>>new_tokens>>$", new_tokens)
        if caller_can_handle_requeue:
            TokenizedMarkdown.__log_requeue(
                requeue_line_info, requeue_reset, parser_state
            )
        return new_tokens, requeue_line_info

    # pylint: enable=too-many-arguments
    @staticmethod
    def __log_requeue(
        requeue_line_info: Optional[RequeueLineInfo],
        requeue_reset: bool,
        parser_state: ParserState,
    ) -> None:
        if not requeue_line_info:
            POGGER.debug("requeue_line_info>>no requeue")
            return
        POGGER.debug(
            "cob>>lines_to_requeue>>$",
            requeue_line_info.lines_to_requeue,
        )
        if requeue_reset:
            assert parser_state.original_line_to_parse is not None
            POGGER.debug(
                "cob>>original_line_to_parse>$>", parser_state.original_line_to_parse
            )
            assert not requeue_line_info.lines_to_requeue[0]
            requeue_line_info.lines_to_requeue[0] = parser_state.original_line_to_parse
            POGGER.debug(
                "cob>>(adjusted)lines_to_requeue>>$",
                requeue_line_info.lines_to_requeue,
            )

    # pylint: disable=too-many-arguments
    @staticmethod
    def __process_next_close_element(
        parser_state: ParserState,
        was_close_forced: bool,
        caller_can_handle_requeue: bool,
        until_this_index: int,
        include_lists: bool,
        include_block_quotes: bool,
        only_these_blocks: Optional[List[type]],
    ) -> Tuple[bool, List[MarkdownToken], Optional[RequeueLineInfo], bool]:
        requeue_line_info = None

        POGGER.debug("cob>>$", parser_state.token_stack)
        can_continue, was_close_forced = TokenizedMarkdown.__can_close_continue(
            parser_state,
            only_these_blocks,
            include_block_quotes,
            include_lists,
            until_this_index,
            was_close_forced,
        )
        POGGER.debug("can_continue>>$", can_continue)
        POGGER.debug("was_close_forced>>$", was_close_forced)
        if can_continue:
            if parser_state.token_stack[-1].was_link_definition_started:
                (
                    can_continue,
                    adjusted_tokens,
                    requeue_line_info,
                ) = TokenizedMarkdown.__close_open_blocks_lrd(
                    parser_state, caller_can_handle_requeue
                )
            else:
                adjusted_tokens = TokenizedMarkdown.__close_open_blocks_normal(
                    parser_state, was_close_forced
                )
        else:
            adjusted_tokens = []
        return can_continue, adjusted_tokens, requeue_line_info, was_close_forced

    # pylint: enable=too-many-arguments

    # pylint: disable=too-many-arguments
    @staticmethod
    def __can_close_continue(
        parser_state: ParserState,
        only_these_blocks: Optional[List[type]],
        include_block_quotes: bool,
        include_lists: bool,
        until_this_index: int,
        was_close_forced: bool,
    ) -> Tuple[bool, bool]:
        can_continue = True
        if only_these_blocks:
            POGGER.debug("cob-only-type>>$", only_these_blocks)
            POGGER.debug("cob-only-type>>$", type(parser_state.token_stack[-1]))
            can_continue = type(parser_state.token_stack[-1]) in only_these_blocks
            if not can_continue:
                POGGER.debug("cob>>not in only")
        elif not include_block_quotes and parser_state.token_stack[-1].is_block_quote:
            POGGER.debug("cob>>not block quotes")
            can_continue = False
        elif not include_lists and parser_state.token_stack[-1].is_list:
            POGGER.debug("cob>>not lists")
            can_continue = False
        elif until_this_index != -1:
            token_stack_size = len(parser_state.token_stack)
            POGGER.debug(
                "NOT ME!!!!$<<$<<",
                until_this_index,
                token_stack_size,
            )
            if until_this_index >= token_stack_size:
                can_continue = False
            else:
                was_close_forced = True

        POGGER.debug("cob>>can_continue=$", can_continue)
        POGGER.debug("cob>>was_close_forced=$", was_close_forced)
        return can_continue, was_close_forced

    # pylint: enable=too-many-arguments

    @staticmethod
    def __close_open_blocks_normal(
        parser_state: ParserState, was_close_forced: bool
    ) -> List[MarkdownToken]:
        POGGER.debug(
            "cob-rem>>$",
            parser_state.token_document,
        )
        adjusted_tokens = TokenizedMarkdown.__remove_top_element_from_stack(
            parser_state, was_close_forced
        )
        POGGER.debug(
            "cob-rem<<$",
            parser_state.token_document,
        )
        POGGER.debug("cob-adj<<$", adjusted_tokens)
        return adjusted_tokens

    @staticmethod
    def __close_open_blocks_lrd(
        parser_state: ParserState, caller_can_handle_requeue: bool
    ) -> Tuple[bool, List[MarkdownToken], Optional[RequeueLineInfo]]:
        POGGER.debug("cob->process_link_reference_definition>>stopping link definition")
        empty_position_marker = PositionMarker(-1, 0, "")
        (
            outer_processed,
            did_complete_lrd,
            did_pause_lrd,
            requeue_line_info,
            adjusted_tokens,
        ) = LinkReferenceDefinitionHelper.process_link_reference_definition(
            parser_state, empty_position_marker, "", "", "", 0, 0, "", 1
        )

        POGGER.debug("BOOOM: caller_can_handle_requeue=$", caller_can_handle_requeue)
        can_continue = not (
            caller_can_handle_requeue
            and requeue_line_info
            and requeue_line_info.lines_to_requeue
        )
        if not can_continue:
            POGGER.debug("BOOOM-->break")
        else:
            assert not (requeue_line_info and requeue_line_info.lines_to_requeue)
            POGGER.debug(
                "cob->process_link_reference_definition>>outer_processed>>$",
                outer_processed,
            )
            POGGER.debug(
                "cob->process_link_reference_definition>>did_complete_lrd>>$",
                did_complete_lrd,
            )
            POGGER.debug(
                "cob->process_link_reference_definition>>adjusted_tokens>>$",
                adjusted_tokens,
            )
            assert not did_pause_lrd
        return can_continue, adjusted_tokens, requeue_line_info

    @staticmethod
    def __remove_top_element_from_stack(
        parser_state: ParserState, was_forced: bool
    ) -> List[MarkdownToken]:
        """
        Once it is decided that we need to remove the top element from the stack,
        make sure to do it uniformly.
        """

        POGGER.debug("cob->top_element->$", parser_state.token_stack[-1])
        POGGER.debug("cob->was_forced->$", was_forced)
        extra_elements = []
        extra_end_data = None
        if parser_state.token_stack[-1].is_indented_code_block:
            extra_elements.extend(
                LeafBlockHelper.extract_markdown_tokens_back_to_blank_line(
                    parser_state, was_forced
                )
            )
        elif parser_state.token_stack[-1].is_fenced_code_block:
            extra_end_data = ":"

        new_tokens = [
            parser_state.token_stack[-1].generate_close_markdown_token_from_stack_token(
                was_forced=was_forced, extra_end_data=extra_end_data
            ),
            *extra_elements,
        ]

        del parser_state.token_stack[-1]
        return new_tokens

    @staticmethod
    def __handle_blank_line_init(
        from_main_transform: bool, input_line: str
    ) -> Tuple[Optional[List[type]], bool, int, str]:
        do_include_block_quotes = from_main_transform
        close_only_these_blocks: Optional[List[type]] = (
            None if from_main_transform else [ParagraphStackToken]
        )

        POGGER.debug("hbl>>from_main_transform>>$", from_main_transform)
        POGGER.debug("hbl>>close_only_these_blocks>>$", close_only_these_blocks)
        POGGER.debug("hbl>>do_include_block_quotes>>$", do_include_block_quotes)

        non_whitespace_index, extracted_whitespace = ParserHelper.extract_spaces(
            input_line, 0
        )
        assert extracted_whitespace is not None
        assert non_whitespace_index is not None
        return (
            close_only_these_blocks,
            do_include_block_quotes,
            non_whitespace_index,
            extracted_whitespace,
        )

    @staticmethod
    def __handle_blank_line(
        parser_state: ParserState,
        input_line: str,
        from_main_transform: bool,
        position_marker: Optional[PositionMarker] = None,
    ) -> Tuple[Optional[List[MarkdownToken]], Optional[RequeueLineInfo]]:
        """
        Handle the processing of a blank line.
        """

        (
            close_only_these_blocks,
            do_include_block_quotes,
            non_whitespace_index,
            extracted_whitespace,
        ) = TokenizedMarkdown.__handle_blank_line_init(from_main_transform, input_line)

        (
            new_tokens,
            force_default_handling,
            requeue_line_info,
        ) = TokenizedMarkdown.__handle_blank_line_token_stack(parser_state)

        if requeue_line_info:
            return new_tokens, requeue_line_info

        if from_main_transform:
            POGGER.debug("hbl>>__handle_blank_line_in_block_quote")
            TokenizedMarkdown.__handle_blank_line_in_block_quote(
                parser_state, new_tokens
            )

        if force_default_handling or new_tokens is None:
            POGGER.debug("hbl>>default blank handling-->cob")
            n_tokens, _ = TokenizedMarkdown.__close_open_blocks(
                parser_state,
                only_these_blocks=close_only_these_blocks,
                include_block_quotes=do_include_block_quotes,
                was_forced=True,
            )
            if new_tokens:
                new_tokens.extend(n_tokens)
            else:
                new_tokens = n_tokens

        list_stack_index = parser_state.find_last_list_block_on_stack()
        block_stack_index = parser_state.find_last_block_quote_on_stack()
        POGGER.debug("list_stack_index>>$", list_stack_index)
        POGGER.debug("block_stack_index>>$", block_stack_index)
        if list_stack_index > 0 and list_stack_index > block_stack_index:
            list_token = cast(
                ListStartMarkdownToken,
                parser_state.token_stack[list_stack_index].matching_markdown_token,
            )
            POGGER.debug("hbl>>last_block_token>>$", list_token)
            list_token.add_leading_spaces("")
            POGGER.debug("hbl>>last_block_token>>$", list_token)

        POGGER.debug("hbl>>new_tokens>>$", new_tokens)
        assert non_whitespace_index == len(input_line)
        assert not (requeue_line_info and requeue_line_info.force_ignore_first_as_lrd)
        new_tokens.append(BlankLineMarkdownToken(extracted_whitespace, position_marker))
        POGGER.debug("hbl>>new_tokens>>$", new_tokens)

        return new_tokens, requeue_line_info

    @staticmethod
    def __handle_blank_line_token_stack(
        parser_state: ParserState,
    ) -> Tuple[Optional[List[MarkdownToken]], bool, Optional[RequeueLineInfo]]:
        (
            is_processing_list,
            in_index,
        ) = LeafBlockProcessorParagraph.check_for_list_in_process(parser_state)
        POGGER.debug(
            "hbl>>is_processing_list>>$>>in_index>>$>>last_stack>>$",
            is_processing_list,
            in_index,
            parser_state.token_stack[-1],
        )

        requeue_line_info: Optional[RequeueLineInfo] = None
        new_tokens: Optional[List[MarkdownToken]] = None
        force_default_handling: bool = parser_state.token_stack[
            -1
        ].was_link_definition_started
        if force_default_handling:
            POGGER.debug(
                "hbl>>process_link_reference_definition>>stopping link definition"
            )
            empty_position_marker = PositionMarker(-1, 0, "")
            (
                _,
                _,
                did_pause_lrd,
                requeue_line_info,
                new_tokens,
            ) = LinkReferenceDefinitionHelper.process_link_reference_definition(
                parser_state, empty_position_marker, "", "", "", 0, 0, "", 2
            )
            assert not did_pause_lrd
            POGGER.debug(
                "hbl<<process_link_reference_definition>>stopping link definition"
            )
        elif parser_state.token_stack[-1].is_code_block:
            if parser_state.count_of_block_quotes_on_stack():
                POGGER.debug("hbl>>code block within block quote")
            else:
                POGGER.debug("hbl>>code block")
                new_tokens = []
        elif parser_state.token_stack[-1].is_html_block:
            POGGER.debug("hbl>>check_blank_html_block_end")
            new_tokens = HtmlHelper.check_blank_html_block_end(parser_state)
            POGGER.debug("hbl<<check_blank_html_block_end")
        elif (
            is_processing_list
            and parser_state.token_document[-1].is_blank_line
            and parser_state.token_document[-2].is_list_start
        ):
            POGGER.debug("hbl>>double blank in list")
            new_tokens, _ = TokenizedMarkdown.__close_open_blocks(
                parser_state, until_this_index=in_index, include_lists=True
            )
            POGGER.debug("hbl<<double blank in list")
        return new_tokens, force_default_handling, requeue_line_info

    @staticmethod
    def __handle_blank_line_in_block_quote(
        parser_state: ParserState, new_tokens: Optional[List[MarkdownToken]]
    ) -> None:
        stack_index = parser_state.find_last_container_on_stack()
        POGGER.debug_with_visible_whitespace("new_tokens>>$", new_tokens)
        POGGER.debug("stack_index>>$", stack_index)
        if new_tokens and stack_index > 0:
            POGGER.debug_with_visible_whitespace("new_tokens[-1]>>$", new_tokens[-1])
            assert (
                new_tokens[-1].is_html_block_end
                or new_tokens[-1].is_link_reference_definition
            ) and stack_index == (len(parser_state.token_stack) - 1)
            close_tokens, _ = parser_state.close_open_blocks_fn(
                parser_state,
                only_these_blocks=[BlockQuoteStackToken],
                include_block_quotes=True,
            )
            POGGER.debug("close_tokens>>$", close_tokens)
            new_tokens.extend(close_tokens)

        stack_index = parser_state.find_last_container_on_stack()
        POGGER.debug(
            "blank>>bq_start>>$",
            parser_state.token_stack[stack_index],
        )
        if stack_index > 0 and parser_state.token_stack[stack_index].is_block_quote:
            block_quote_token = cast(
                BlockQuoteMarkdownToken,
                parser_state.token_stack[stack_index].matching_markdown_token,
            )
            POGGER.debug("hblibq>>last_block_token>>$", block_quote_token)
            POGGER.debug(
                "hblibq>>leading_text_index>>$", block_quote_token.leading_text_index
            )
            block_quote_token.add_bleading_spaces("")
            POGGER.debug("hblibq>>last_block_token>>$", block_quote_token)
            POGGER.debug(
                "hblibq>>leading_text_index>>$", block_quote_token.leading_text_index
            )

    def __process_front_matter_header_if_present(
        self,
        first_line_in_document: Optional[str],
        line_number: int,
        requeue: List[str],
    ) -> Tuple[Optional[str], int, List[str]]:
        assert self.__source_provider
        assert self.__parse_properties
        POGGER.debug(
            "is_front_matter_enabled>>$",
            self.__parse_properties.is_front_matter_enabled,
        )
        if (
            first_line_in_document is not None
            and self.__parse_properties.is_front_matter_enabled
        ):
            (
                first_line_in_document,
                line_number,
                requeue,
            ) = FrontMatterExtension.process_header_if_present(
                first_line_in_document,
                line_number,
                requeue,
                self.__source_provider,
                self.__tokenized_document,
            )
        return first_line_in_document, line_number, requeue


#!/usr/bin/env python
"""Test file for the physbiblio.bibtexWriter module.

This file is part of the physbiblio package.
"""
import traceback
import unittest

import bibtexparser

try:
    from physbiblio.bibtexWriter import *
    from physbiblio.config import pbConfig
    from physbiblio.setuptests import *
except ImportError:
    print("Could not find physbiblio and its modules!")
    raise
except Exception:
    print(traceback.format_exc())

@unittest.skipIf(skipTestsSettings.long, "Long tests")
@patch("logging.Logger.debug")
@patch("logging.Logger.info")
@patch("logging.Logger.warning")
@patch("logging.Logger.exception")
class TestWebImportMethods(unittest.TestCase):
    """Test the functions that writes bibtexs."""

    def test_properties(self, *args):
        """Test properties of the pbWriter object"""
        self.assertIsInstance(pbWriter, PBBibTexWriter)
        self.assertIsInstance(pbWriter, BibTexWriter)
        self.assertEqual(pbWriter._max_field_width, 13)
        # order of fields in output
        self.assertEqual(
            pbWriter.display_order,
            [
                "author",
                "collaboration",
                "title",
                "booktitle",
                "publisher",
                "journal",
                "volume",
                "year",
                "pages",
                "russian",
                "archiveprefix",
                "primaryclass",
                "eprint",
                "doi",
                "reportNumber",
            ],
        )
        self.assertEqual(
            pbWriter.bracket_fields,
            [
                "title",
                "booktitle",
                "www",
                "note",
                "abstract",
                "comment",
                "article",
                "url",
            ],
        )
        self.assertEqual(
            pbWriter.excluded_fields, ["adsnote", "adsurl", "slaccitation"]
        )
        self.assertEqual(pbWriter.order_entries_by, None)
        self.assertEqual(pbWriter.comma_first, False)

    def test_bibtexWrite(self, *args):
        """Test _entry_to_bibtex"""
        basicEntry = {
            "ID": "test",
            "ENTRYTYPE": "article",
            "author": "me",
            "title": "My title",
        }
        db = bibtexparser.bibdatabase.BibDatabase()
        db.entries = [basicEntry]
        self.assertEqual(
            pbWriter.write(db).strip(),
            '@Article{test,\n        author = "me",\n         '
            + 'title = "{My title}",\n}',
        )
        entry = dict(basicEntry)
        entry["ENTRYTYPE"] = "proceeding"
        entry["eprint"] = "1721"
        entry["slaccitation"] = "1721"
        entry["title"] = "{my title}"
        db.entries = [entry]
        self.assertEqual(
            pbWriter.write(db).strip(),
            '@Proceeding{test,\n        author = "me",\n         '
            + 'title = "{my title}",\n        eprint = "1721",\n}',
        )
        entry = dict(basicEntry)
        entry["ENTRYTYPE"] = "custom"
        entry["myfield"] = "abcd"
        entry["journal"] = "JCAP"
        entry["title"] = "{My} title"
        db.entries = [entry]
        self.assertEqual(
            pbWriter.write(db).strip(),
            '@Custom{test,\n        author = "me",\n         '
            + 'title = "{{My} title}",\n       journal = "JCAP",'
            + '\n       myfield = "abcd",\n}',
        )

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


from random import randint, randrange, choice
import string
import parser
import csv
import mutator

# MAKE REPRODUCIBLE -> DUMP RAND SEED

# When we have time -> extend into object oriented
# parent vanilla mutator

class CsvMutator(mutator.Mutator):
    """
    Mutator(min, max, sample input)
    creates a list Mutator.population of mutated inputs to be passed into the binary

    Do we pass in input here, or provide the input to the harness? Ideally we want to be able to tell this class coverage information for better pop development
    """
    def __init__(self, sample_processed, min=2, max=10):
        # By convention, header is the first row
        self.csv_list = sample_processed
        self.csv_headers = list(self.csv_list[0].keys())
        self.newline = "\n"
        self.delimiter = ","
        mutator.Mutator.__init__(self,None, min,max)
        return
    # ===============================================================
    # Filetype: csv
    # Main strategies: single field mutation

    # why did you have to call it single_mutate
    def single_mutate(self):

        mutators = [self.field_random_row, self.field_append_rows, self.field_single_mutate]

        c = choice(mutators)
        mutated_list = c()
        #print(mutated_list)
        return self.csv_write(mutated_list)

    def complex_mutate(self):
        return self.single_mutate()

    # ==================================================================
    def field_single_mutate(self):
        mutated_list = self.csv_list.copy()
        rand_row = randrange(0, len(self.csv_list))
        rand_key = choice(self.csv_headers)
        # bandaid patch for None
        replace = self.mutate(self.csv_list[rand_row][rand_key])
        if not replace:
            replace = ""
        mutated_list[rand_row][rand_key] = replace
        return mutated_list

    def rand_str(self, n):
        return "".join(choice(string.ascii_lowercase + string.ascii_uppercase) for i in range(n))

    def field_random_row(self):
        n = randrange(1,1000)
        mutated_list = self.csv_list.copy()
        rand_row = randrange(0, len(self.csv_list))
        mutated_list[rand_row] = dict(zip(self.csv_headers, [self.rand_str(n) for i in range(len(self.csv_headers))]))
        return mutated_list

    def field_append_rows(self):
        n = randrange(1,100)
        mutated_list = self.csv_list.copy()
        for i in range(n):
            mutated_list.append(dict(zip(self.csv_headers, [self.rand_str(100) for i in range(len(self.csv_headers))])))
        return mutated_list

    # Write CSV
    def csv_write(self, csv_list):
        # grab headers
        formatted = self.delimiter.join(list(csv_list[0].keys()))
        #print(formatted)
        for row in csv_list[0:]:
            formatted += self.newline + self.delimiter.join(row.values())
        return formatted.encode("utf-8")