# coding=utf-8
#
# Read the holdings section of the excel file from trustee.
#
#

from xlrd import open_workbook
from xlrd.xldate import xldate_as_datetime
import xlrd
import datetime, re
from DIF.utility import get_datemode, retrieve_or_create, get_holding_fx
import logging
logger = logging.getLogger(__name__)

class BadFieldName(Exception):
	pass

class BadAssetClass(Exception):
	pass

class CurrencyNotFound(Exception):
	pass

class SecurityIdNotFound(Exception):
	pass

class InvalidDateValue(Exception):
	pass

def read_holding(ws, port_values):
	"""
	Read the worksheet with portfolio holdings. To retrieve holding,
	we do:

	equity_holding = port_values['equity']
	for equity in equity_holding:
		equity['ticker'], equity['name']
		... retrive equity values using the following key ...

		ticker, isin, accounting_treatment, name, number_of_shares, currency,
		listed_location, fx_on_trade_day, last_trade_date, average_cost, price,
		book_cost, market_value, market_gain_loss, fx_gain_loss

	bond_holding = port_values['bond']
	for bond in bond_holding:
		bond['isin'], bond['name']
		... retrive bond values using the following key ...

		isin, name, accounting_treatment, par_amount, currency, is_listed,
		listed_location, fx_on_trade_day, coupon_rate, coupon_start_date,
		maturity_date, average_cost, amortized_cost, price, book_cost,
		interest_bought, amortized_value, market_value, accrued_interest,
		amortized_gain_loss, market_gain_loss, fx_gain_loss

	Note a bond may not have all of the above fields, depending on
	its accounting treatment. A HTM bond has amortized_cost, amortized_value,
	amortized_gain_loss, while a trading bond has price, market_value,
	market_gain_loss set to zero.

	"""
	logger.debug('in read_holding()')

	"""
	Now trying to read the holdings worksheet. The structure of data is as
	follows:

	Section (bond/equity/forward/xxx):
		sub section:
			holding1
			holding2
			...

		sub section:
			...

	Section
		sub section:

	"""

	row = 0
	while (row < ws.nrows):

		# search the first column
		cell_value = ws.cell_value(row, 0)
		if isinstance(cell_value, str):
			tokens = cell_value.split()

			# if len(tokens) > 1:
			if len(tokens) > 2:

				if tokens[1]+tokens[2] == 'DebtSecurities':	# bond
					logger.debug('bond: {0}'.format(cell_value))

					currency = read_currency(cell_value)
					fields, n = read_bond_fields(ws, row)	# read the bond
					row = row + n							# field names

					n = read_section(ws, row, fields, 'bond', currency, port_values)
					row = row + n

				elif tokens[1] == 'Equities':		# equity
					logger.debug('equity: {0}'.format(cell_value))

					# equity_holding = retrieve_or_create(port_values, 'equity')
					currency = read_currency(cell_value)
					fields, n = read_equity_fields(ws, row)
					row = row + n

					n = read_section(ws, row, fields, 'equity', currency, port_values)
					row = row + n

		# move to next row
		row = row + 1

	logger.debug('out of read_holding()')

def read_currency(cell_value):
	"""
	Read the currency from the cell containing a section start, such as
	'V. Debt Securities - US$  (債務票據- 美元)',
	'V. Debt Securities - SGD  (債務票據- 星加坡元)',
	'X. Equities - USD (股票-美元)'

	From the above strings, the function return USD, SGD, USD
	"""
	# The old implementation
	# temp_list = cell_value.split('-')
	# token = temp_list[1]
	# temp_list = token.split('(')
	# currency = str.strip(temp_list[0])

	# if currency == 'US$':
	# 	currency = 'USD'	# make the correction

	# The new implementation uses regular expression
	# it will match currency symbol US$, USD, HKD, SGD
	pattern = '-\s*(US\$|USD|HK\$|HKD|SGD|CNY|EUR)\s*\(.*\)'
	m = re.search(pattern, cell_value)
	if m is None:	# pattern matching failed
		logger.error('read_currency(): currency not found in string:{0}'.format(cell_value))
		raise CurrencyNotFound()
	else:
		currency = m.group(1)
		# if currency == 'US$':
		# 	currency = 'USD'	# make the correction
		if currency[-1] == '$':
			currency = currency[:-1] + 'D'	# replace $ with D

	return currency

def read_field_name(ws, row, column):
	"""
	Read a field name give its position.
	"""
	fld1 = ws.cell_value(row-1, column)
	fld2 = ws.cell_value(row, column)
	if isinstance(fld1, str) and isinstance(fld2, str):
		field = (str.strip(fld1), str.strip(fld2))
	else:
		logger.error('read_field_name(): invalid type in row {0}, {1} column {2}'.
						format(row-1, row, column))
		raise TypeError('bad field name type {0}, {1}'.format(fld1, fld2))

	# logger.debug(field)
	return field

def read_fields(ws, name_map, row):
	"""
	Read the field names for this bond section, it may be fields for held
	to maturity bond, or for trading bonds.
	"""
	rows_read = 1
	fields = []

	while (row+rows_read < ws.nrows):

		# search the first column
		cell_value = ws.cell_value(row+rows_read, 0)
		# print(cell_value)
		if cell_value == 'Description':
			for i in range(2, 17):
				field_tuple = read_field_name(ws, row+rows_read, i)
				try:
					fields.append(name_map[field_tuple])
				except:
					logger.exception('read_fields(): ')
					logger.error('read_fields(): bad field name at row {0}, column {1}, value = {2} {3}'.
									format(row+rows_read, i, ws.cell_value(row+rows_read-1, i),
											ws.cell_value(row+rows_read, i)))
					raise BadFieldName()

			break	# finished reading the fields

		# move to next row
		rows_read = rows_read + 1
	# end of while loop

	return fields, rows_read

def read_bond_fields(ws, row):
	"""
	Read the field names for this bond section, it may be fields for held
	to maturity bond, or for trading bonds.
	"""
	# rows_read = 1
	# fields = []

	name_map = {
		('', ''):'empty_field',

		# Bond fields section
		('票面值', 'Par Amt'):'par_amount',
		('上市 (是/否)', 'Listed (Y/N)'):'is_listed',
		('Primary', 'Exchange'):'listed_location',
		('(AVG) FX', 'for TXN'):'fx_on_trade_day',
		('Int.', 'Rate (%)'):'coupon_rate',
		('Int.', 'Start Day'):'coupon_start_date',
		('到期日', 'Maturity'):'maturity_date',
		('Cost', '(%)'):'average_cost',
		('Price', '(%)'):'price',
		('(Amortized)', '(%)'):'amortized_cost',
		('成本價', 'Book Cost'):'book_cost',
		('Int.', 'Bought'):'interest_bought',
		('市價', 'M. Value'):'market_value',
		('Adjusted Value', '(Amortized)'):'amortized_value',
		('應收利息', 'Accr. Int.'):'accrued_interest',
		('Year-End', 'Amortization'):'amortized_gain_loss',
		('Gain/(Loss)', 'M. Value'):'market_gain_loss',
		('FX', 'HKD Equiv.'):'fx_gain_loss',

		# for trustee Macau fund
		('', 'Listed (Y/N)'):'is_listed',
		('Location', 'of Listed'):'listed_location',
		('FX', 'MOP Equiv.'):'fx_gain_loss'
	}

	return read_fields(ws, name_map, row)

def read_equity_fields(ws, row):
	"""
	Note the equity section contains listed equity and preferred shares.
	For listed equity we'll see listed_location, but for preferred shares,
	this field is missing.
	"""

	name_map = {
		('', ''):'empty_field',

		('股數', 'Share'):'number_of_shares',
		('幣值', 'CCY'):'currency',
		('Location', 'of Listed'):'listed_location',
		('(AVG) FX', 'for TXN'):'fx_on_trade_day',
		('最後交易日', 'Latest V.D.'):'last_trade_date',
		('Avg.', 'Price'):'average_cost',
		('Market', 'Price'):'price',
		('成本價', 'Book Cost'):'book_cost',
		('市價', 'M. Value'):'market_value',
		('Gain/(Loss)', 'M. Value'):'market_gain_loss',
		('FX', 'HKD Equiv.'):'fx_gain_loss',

		# for trustee Macau fund
		('上市 (是/否)', 'Listed (Y/N)'):'is_listed',
		('FX', 'MOP Equiv.'):'fx_gain_loss'
	}

	return read_fields(ws, name_map, row)

def adjust_fields(port_values, fields, asset_class, accounting_treatment):
	"""
	Sometimes there are missing fields in a section, say SGD bond HTM
	section tends to have empty columns for its data fields. To overcome
	this problem, we reuse the fields for the same type of holding from
	previous sections.
	"""
	# don't touch equity fields, because the fields for real equity and for
	# those preferred shares treated as equity are different.
	if asset_class == 'equity':
		return fields

	if not (asset_class, accounting_treatment) in port_values:
		port_values[(asset_class, accounting_treatment)] = fields
		return fields
	else:
		existing_fields = port_values[(asset_class, accounting_treatment)]
		if len(fields) != len(existing_fields):
			logger.warning('adjust_fields(): existing fields do not match with the fields passed in, reuse existing fields.')
			show_fields(existing_fields, fields)

		else:
			for i in range(len(fields)):
				if fields[i] != existing_fields[i]:
					logger.warning('adjust_fields(): existing fields do not match with the fields passed in, reuse existing fields.')
					show_fields(existing_fields, fields)

		return existing_fields

def show_fields(existing_fields, fields):
	for i in range(max(len(existing_fields), len(fields))):
		logger.info('{0} : {1}, {2}'.format(i, get_value(existing_fields, i), get_value(fields, i)))

def get_value(fields, index):
	try:
		return fields[index]
	except IndexError:
		return '<out of range>'

def read_section(ws, row, fields, asset_class, currency, port_values):
	"""
	Read a section in the worksheet (ws), starting on row number (row).
	fields being the list of fields to read from column C. For example,
	for HTM bond section, we expect to fields in the following order:

		par_amount, currency, is_listed, listed_location, fx_on_trade_day,
		coupon_rate, coupon_start_date, maturity_date, average_cost,
		amortized_cost, book_cost, interest_bought, amortized_value,
		accrued_interest, amortized_gain_loss, fx_gain_loss

	for trading bonds, we expect to see fields in the following order:

		par_amount, currency, is_listed, listed_location, fx_on_trade_day,
		coupon_rate, coupon_start_date, maturity_date, average_cost,
		price, book_cost, interest_bought, market_value, accrued_interest,
		market_gain_loss, fx_gain_loss

	for listed equity, we expect to see fields in the following order:

		number_of_shares, currency, listed_location, fx_on_trade_day,
		empty_field, last_trade_date, empty_field, average_cost, price,
		book_cost, empty_field, market_value, empty_field, market_gain_loss,
		fx_gain_loss

	for equity (preferred shares), we expect to see fields in the following order:
		number_of_shares, currency, empty_field, fx_on_trade_day,
		empty_field, last_trade_date, empty_field, average_cost, price,
		book_cost, empty_field, market_value, empty_field, market_gain_loss,
		fx_gain_loss

	Return the number of rows read in this function
	"""
	logger.debug('read_section() at row {0}, asset class {1}'.format(row, asset_class))

	# currently only handle these two types of asset class
	if not asset_class in ['equity', 'bond']:
		logger.error('read_section(): invalid asset class: {0}'.format(asset_class))
		raise BadAssetClass()

	rows_read = 1
	holding = retrieve_or_create(port_values, asset_class)

	# while (row+rows_read < ws.nrows):
	# 	cell_value = ws.cell_value(row+rows_read, 0)
	# 	if start_of_sub_section(cell_value):
	# 		accounting_treatment = get_accounting_treatment(cell_value)
	# 		fields = adjust_fields(port_values, fields, asset_class, accounting_treatment)
	# 		n = read_sub_section(ws, row+rows_read, accounting_treatment,
	# 								fields, asset_class, currency, holding)
	# 		rows_read = rows_read + n

	# 	# elif end_of_section(cell_value):
	# 	if end_of_section(ws.cell_value(row+rows_read, 0)):
	# 		break

	# 	rows_read = rows_read + 1	# move to next row

	while (row+rows_read < ws.nrows):
		if start_of_sub_section(ws.cell_value(row+rows_read, 0)):
			break
		rows_read = rows_read + 1	# move to next row

	# when the sub section reading ends, we are either at the start of the next
	# sub section or end of the section.
	while start_of_sub_section(ws.cell_value(row+rows_read, 0)):
		accounting_treatment = get_accounting_treatment(ws.cell_value(row+rows_read, 0))
		fields = adjust_fields(port_values, fields, asset_class, accounting_treatment)
		n, fx_rate = read_sub_section(ws, row+rows_read, accounting_treatment,
										fields, asset_class, currency, holding)
		rows_read = rows_read + n
		if fx_rate != 0:
			# print('currency: {0}, fx: {1}'.format(currency, fx_rate))
			get_holding_fx(port_values)[currency] = fx_rate

	return rows_read

def read_sub_section(ws, row, accounting_treatment, fields, asset_class, currency, holding):
	"""
	Read a sub section in the worksheet (ws), starting on row number (row).

	Return the number of rows read in this function
	"""
	rows_read = 1
	end_of_section_reached = False
	fx_rate = 0

	while (row+rows_read < ws.nrows):
		cell_value = ws.cell_value(row+rows_read, 0)

		logger.debug('read_sub_section(): reading row {0}'.format(row+rows_read))
		if is_security_position(cell_value):
			security_id = get_security_id(cell_value)
			security = {}
			# if (asset_class == 'bond'):
			# 	security['isin'] = security_id
			# elif (asset_class == 'equity'):
			# 	if ('listed_location') in fields:	# it's listed equity
			# 		security['ticker'] = security_id
			# 	else:								# it's preferred shares
			# 		security['isin'] = security_id
			m = re.search('^[A-Z]{2}[A-Z0-9]{10}$', security_id)
			if m is not None:
				security['isin'] = security_id
			else:
				m = re.search('^[HN]{1}[0-9]{4}$', security_id)
				if m is not None:
					security['ticker'] = security_id
				else:
					security['security_id'] = security_id

			security['name'] = cell_value.strip()
			security['currency'] = currency
			security['accounting_treatment'] = accounting_treatment

			column = 2	# now start reading fields in column C
			for field in fields:
				cell_value = ws.cell_value(row+rows_read, column)
				if isinstance(cell_value, str):
					cell_value = cell_value.strip()
				# logger.debug('{0},{1},{2}'.format(row+rows_read, column, cell_value))

				if field == 'empty_field':	# ignore this field, move to
											# next column
					column = column + 1
					continue

				field_value = validate_and_convert_field_value(field, cell_value)

				# if already has currency assigned (in the case of listed
				# equity), check whether the currency value is inconsistent
				if field == 'currency' and 'currency'in security \
					and field_value != security['currency']:

					logger.error('read_sub_section(): inconsistent currency value at row {0}, column {1}'.
									format(row+rows_read, column))
					raise ValueError('inconsistent currency value')

				security[field] = field_value

				# if holding amount is zero, stop reading other fields.
				if field in ['par_amount', 'number_of_shares'] and field_value == 0:
					break

				column = column + 1
			# end of for loop to create security

			logger.debug('read_sub_section(): add security {0},{1},{2}'.
							format(security['currency'], security['accounting_treatment'], security['name']))
			holding.append(security)

		# elif start_of_sub_section(cell_value) or end_of_section(cell_value):
		elif start_of_sub_section(cell_value):
			break

		elif end_of_section(cell_value):
			# print('end of section')
			end_of_section_reached = True
			break

		rows_read = rows_read + 1	# move to next row
		# end of while loop

	if end_of_section_reached:
		# FX rate is supposed to be at the next row after section ends
		fx_rate = read_fx_rate(ws, row+rows_read+1)

	return rows_read, fx_rate

def read_fx_rate(ws, row):
	"""
	Read the fx rate after the end of a section.
	"""
	cell_value = ws.cell_value(row, 0)
	if cell_value.startswith('Exchange Rate'):
		for i in range(1, 10):
			cell_value = ws.cell_value(row, i)
			if isinstance(cell_value, float):
				return cell_value
	else:
		logger.error('read_fx_rate(): \"{0}\" is not FX rate cell'.format(cell_value))

	return 0

def get_accounting_treatment(cell_value):
	"""
	Get accounting treatment from the sub section, like

	(i) Adj Price = Amortized Cost, or
	(iv) Held to Maturity
	"""
	pattern = '^\([ivx]{1,5}\)\s*(.*)'
	m = re.search(pattern, cell_value.strip())
	if m is None:
		logger.error('get_accounting_treatment(): failed to get accounting info from string: {0}'.
									format(cell_value))
		raise ValueError('invalid account treatment string')

	else:
		if m.group(1).startswith('Held to Maturity') or \
				m.group(1).startswith('Adj Price = Amortized Cost'):

			return 'HTM'

		elif m.group(1).startswith('Trading') or \
				m.group(1).startswith('Market Value = Market Value') or \
				m.group(1).startswith('Available for Sales'):

			return 'Trading'

		else:
			logger.error('get_accounting_treatment(): unknown accounting treament: {0}'.
									format(cell_value))
			raise ValueError('bad accounting treatment')

def get_security_id(cell_value):
	"""
	Get the security id from its name, like
	(XS1389124774) DEMETER (SWISS RE LTD) 6.05%, or
	(N1530) 3SBio Inc.
	"""
	pattern = '^\(([A-Z0-9]{5,12})\)'
	m = re.search(pattern, cell_value.strip())
	if m is None:
		logger.error('get_security_id(): unable to extract security id from: {0}'.format(cell_value))
		raise SecurityIdNotFound()
	else:
		return m.group(1)

def is_security_position(cell_value):
	if isinstance(cell_value, str):
		pattern = '^\([A-Z0-9]{5,12}\)'	# looks like (DSFXFC07003) xxx
										# or (H0522) xxxx
		m = re.search(pattern, cell_value.strip())
		if m is not None:
			return True

	return False

def start_of_sub_section(cell_value):
	"""
	Tell whether this is the start of a sub section.

	It begins with (i) xxxx
	"""
	if isinstance(cell_value, str):
		pattern = '^\([ivx]{1,5}\)'
		m = re.search(pattern, cell_value.strip())
		if m is not None:
			return True

	return False

def end_of_sub_section(ws, row):
	"""
	Tell whether this is the end of a sub section.

	If the first 4 columns are all empty, then it is a blank line, then
	it is the end of the sub section.
	"""
	for column in range(4):
		if not is_empty_cell(ws, row, column):
			return False

	return True

def end_of_section(cell_value):
	"""
	Tell whether this is the end of the section.
	"""
	if isinstance(cell_value, str) and cell_value.startswith('Total'):
		return True

	return False

def is_empty_cell(ws, row, column):
	"""
	If the cell value is all white space or an empty string, then it is
	an empty cell.
	"""
	cell_value = ws.cell_value(row, column)
	if isinstance(cell_value, str) and str.strip(cell_value) == '':
		return True
	else:
		return False

def validate_and_convert_field_value(field, cell_value):
	"""
	Validate the field value read is of proper type, if yes then convert it
	to a proper value if necessary (e.g., an empty field to zero). If no,
	then raise an exception.
	"""

	field_value = cell_value

	# if the following field value type is not string, then
	# something must be wrong
	if field in ['is_listed', 'listed_location', 'currency'] \
		and not isinstance(cell_value, str):
		logger.error('validate_and_convert_field_value(): field {0} should be a string: {1}'.
						format(field, cell_value))
		raise ValueError('bad field type: not a string')

	elif field in ['fx_on_trade_day', 'coupon_rate', 'average_cost', \
					'amortized_cost', 'price', 'book_cost', 'interest_bought', \
					'amortized_value', 'market_value', 'accrued_interest', \
					'amortized_gain_loss', 'market_gain_loss', 'fx_gain_loss'] \
		and not isinstance(cell_value, float):
		logger.error('validate_and_convert_field_value(): field {0} should be a float: {1}'.
						format(field, cell_value))
		raise ValueError('bad field type: not a float')

	elif field in ['par_amount', 'number_of_shares']:
		if isinstance(cell_value, float):
			# OK, no change
			pass
		elif isinstance(cell_value, str) and str.strip(cell_value) == '':
			# treat an empty holding as zero
			field_value = 0
		else:
			logger.error('validate_and_convert_field_value(): field {0} should be a \
							float or empty string: {1}'.format(field, cell_value))
			raise ValueError('bad field type: not a float or empty string')

	# convert float to python datetime object when necessary
	if field in ['coupon_start_date', 'maturity_date', 'last_trade_date']:
		try:
			datemode = get_datemode()
			field_value = xldate_as_datetime(cell_value, datemode)
		except:
			logger.warning('validate_and_convert_field_value(): convert {0} to excel date failed, value = {1}'.
							format(field, cell_value))

			# treat it as a "dd/mm/yyyy" string and try again
			field_value = convert_date_string(cell_value)

	return field_value

def convert_date_string(date_string):
	"""
	Convert a date_string object in the format of dd/mm/yyyy to a python
	datetime object.
	"""
	try:
		m = re.search('^(\d{2})/(\d{2})/(\d{4})', date_string)
		if m is not None:
			return datetime.datetime(int(m.group(3)), int(m.group(2)), int(m.group(1)))

		logger.error('convert_date_string(): {0} is not a proper date value'.format(date_string))
		raise InvalidDateValue()

	except TypeError:
		logger.error('convert_date_string(): {0} is not of type string'.format(date_string))
		raise


# -*- coding: utf-8 -*-

__author__ = 'Hendrik Folkerts'

import os
import shutil
import subprocess
import csv
import platform

class functionsSimulink():

    #run the system
    def runSimulation(self, modelfilepathname, mAPD):
        #set the system
        syst = platform.system()

        #add necessary parameters to the modelfile
        modelName = os.path.splitext(os.path.basename(modelfilepathname))[0]
        with open(modelfilepathname, "a") as fileobject:
            fileobject.write("\n")
            fileobject.write("try\n")
            fileobject.write("\n")

            #add outports to the signals of interest -> Simulink only returns values that have outports
            #copy the .slx file with the outport to this script
            pathOfThisFile = os.path.dirname(os.path.abspath(__file__))
            pathOfSimulinkOutBlock = os.path.join(pathOfThisFile, 'general_Simulator_files', 'Simulink_OutBlock.slx')
            newPathOfSimulinkOutBlock = os.path.join(os.path.split(modelfilepathname)[0], 'Simulink_OutBlock.slx')
            shutil.copyfile(pathOfSimulinkOutBlock, newPathOfSimulinkOutBlock)
            #add the Out blocks to the signals of interest

            #path = os.path.split(modelfilepathname)[0]
            #fileobject.write("addpath('" + path + "');\n")

            #interprete nsigana -> number of Out blocks and where to connect to
            nsigana = eval(mAPD.get('nsigana'))
            for i in range(len(nsigana)):
                #add the outblock
                sourceblockname = nsigana[i].split(".")[0].replace("-", "_")
                sourceblock = modelName + "/" + sourceblockname
                sourceblockport = nsigana[i].split(".")[-1]  #the name of the sourceport -> find the portnumber
                sinkblockname = sourceblockname + "_" + nsigana[i].split(".")[-1]   #the sink is the Out block
                sinkblock = modelName + "/" + sinkblockname
                sinkblockportnumber = "1"   #the number of the Out block's port -> is has only one, so portnumber "1"
                fileobject.write("%One out block with connection\n")
                #add the block
                fileobject.write("h = add_block('Simulink_OutBlock/Out', '" + sinkblock + "');    %add Simulink Out block from an MB containing only the Simulink Out block\n")
                fileobject.write("set_param(h, 'Port', '" + str(i+1) + "');    %set the number of the Out block\n")
                #add the connection
                if mAPD.get("interface") == "native":
                    fileobject.write("phFrom = get_param('" + sourceblock + "','PortHandles');    %get the port handles of the source block\n")
                else:
                    fileobject.write("phFrom = get_param('" + modelName + "/" + modelName + "','PortHandles');    %get the port handles of the source block\n")
                fileobject.write("phTo = get_param('" + sinkblock + "','PortHandles');    %get the port handles of the sink block\n")
                #port for connection: sourceblock -> out port
                if mAPD.get("interface") == "native":
                    fileobject.write("simBlockHandle = get_param('" + sourceblock + "','Handle');    %get the handle of the source block (which is a subsystem of the functional block(s) and In/Out blocks)\n")
                else:
                    fileobject.write("simBlockHandle = get_param('" + modelName + "/" + modelName + "','Handle');    %get the handle of the source block (which is a subsystem of the model FMU and Out blocks)\n")
                fileobject.write("outportHandles = find_system(simBlockHandle, 'LookUnderMasks', 'on', 'SearchDepth', 2, 'BlockType', 'Outport');    %get the handles to Out blocks in the subsystem\n")
                fileobject.write("outNames = get_param(outportHandles, 'Name');    %get the names of the Out blocks\n")
                fileobject.write("outPorts = get_param(outportHandles, 'Port');    %get the ports of the Out blocks\n")
                fileobject.write("if iscell(outNames)\n")
                if mAPD.get("interface") == "native":
                    fileobject.write("    idx = find(ismember(outNames, '" + sourceblockport + "'));    %If there are several outNames, the values are placed in a cell array outPorts. -> Find the right number to the name.\n")
                else:
                    fileobject.write("    idx = find(ismember(outNames, '" + sourceblockname + "_" + sourceblockport + "_Out'));    %If there are several outNames, the values are placed in a cell array outPorts. -> Find the right number to the name.\n")
                fileobject.write("    pno = str2num(outPorts{idx});\n")
                fileobject.write("else\n")
                fileobject.write("    pno = str2num(outPorts);    %If there is only one outName, the outPorts is a string with value '1'. It can be used directly.\n")
                fileobject.write("end\n")
                #port for connection: sinkblock -> in port -> the Out block -> it is clear which port, so no more code
                fileobject.write("pni = " + sinkblockportnumber + ";    %port of the sinkblock for the connection -> The in port of the Out block -> The port is clear.\n")
                #draw the line
                fileobject.write("add_line('" + modelName + "', phFrom.Outport(pno), phTo.Inport(pni), 'autorouting', 'on');   %draw a connection between the now found outport and inport\n")
                fileobject.write("\n")

            #fileobject.write("rmpath('" + path + "');\n")

            #append simulation information
            fileobject.write("%Simulator run\n")
            fileobject.write("simout = sim('" + modelName + "',...\n")
            fileobject.write("'StartTime', '" + str(mAPD.get("starttime")) + "',...\n")
            fileobject.write("'Solver', '" + mAPD.get("solver") + "',...\n")
            fileobject.write("'StopTime', '" + str(mAPD.get("stoptime")) + "',...\n")
            fileobject.write("'MaxStep', '" + str(mAPD.get("maxstep")) + "',...\n")

            #not needed, since SaveOutput seems to be ignored, instead just take Out ports
            #fileobject.write("'SimulationMode', 'normal',...\n")
            #fileobject.write("'SaveTime', 'on', 'TimeSaveName', 'tout',...\n")
            #fileobject.write("'SaveState', 'on', 'StateSaveName', 'xout',...\n")
            #fileobject.write("'SaveOutput', 'on', 'OutputSaveName', 'yout',...\n")

            fileobject.write("'SaveFormat', 'StructureWithTime');\n")
            fileobject.write("\n")

            #write results in a file------------------------------------------------------------------------------------
            fileobject.write("%Get the simulation results and write them into a CSV file\n")
            #fileobject.write("save('" + modelName + ".mat', 'simout')\n")  #it shall be saved as csv instead, therefore the following lines

            fileobject.write("t = simout.tout;\n")              #get the simulation time
            fileobject.write("y = simout.yout.signals;\n")      #get the simulation signals with their values
            fileobject.write("numValues = length(t);\n")
            fileobject.write("numSignals = length(y);\n")

            fileobject.write("header(1,1:numSignals+1) = {0};\n")              #preallocate memory for the header
            fileobject.write("simdata = zeros(numValues,numSignals+1);\n")     #simdata: preallocate memory for the signals and their values

            fileobject.write("header(1) = {'time'};\n")
            fileobject.write("simdata(:,1) = t;\n")

            fileobject.write("for i = 1:numSignals\n")  #fill the header and the simdata object
            fileobject.write("    blockName = simout.yout.signals(i).blockName;\n")
            fileobject.write("    blockName = split(blockName, '/');\n")
            fileobject.write("    blockName = blockName{end};\n")
            fileobject.write("    blockName = strrep(blockName, '_', '.');\n")
            fileobject.write("    header{1,i+1} = blockName;\n")
            fileobject.write("    simdata(:,i+1) = simout.yout.signals(i).values;\n")
            fileobject.write("end\n")

            fileobject.write("csvHeader = strjoin(header, ',');\n") #join the values in the header separated by comma
            fileobject.write("fid = fopen('" + modelName + ".csv','w');\n") #write the header to file
            fileobject.write("fprintf(fid, csvHeader);\n")
            fileobject.write("fprintf(fid, '\\n');\n")
            fileobject.write("fclose(fid);\n")

            fileobject.write("dlmwrite('" + modelName + ".csv',simdata,'-append');\n")

            #catch if error---------------------------------------------------------------------------------------------
            fileobject.write("\n")
            fileobject.write("catch\n")
            fileobject.write("end\n")
            fileobject.write("\n")

            #end write results in a file--------------------------------------------------------------------------------

            fileobject.write("bdclose\n")   #close the simulation model
            fileobject.write("quit\n")      #close Matlab

        #now run the script - start and wait until done
        if syst == "Windows":
            retcode = subprocess.call(["matlab", "-nosplash", "-nodesktop", "-wait", "-r", "\"run('" + modelfilepathname + "');\""])
        else:
            retcode = subprocess.call(["matlab", "-nosplash", "-nodesktop", "-wait", "-r", "run('" + modelfilepathname + "');"])
        print("The simulation of the model " + modelName + " was executed by Simulink returning " + str(retcode) + ".")
        print("The simulation of the model " + modelName + " was saved as csv.")

        #return the results file
        resfilepathname = os.path.splitext(modelfilepathname)[0] + ".csv"
        return resfilepathname

    #get the results
    def getResults(self, resultsfile):
        try:
            with open(resultsfile, 'r') as rf:
                reader = csv.reader(rf)
                signalValuesList = list(reader)
            return signalValuesList
        except:
            return []


"""
Write a function called element_visible that will check
if an element is visible on the page and returns True or False.
"""
from selenium import webdriver
from selenium.webdriver.common.keys import Keys

# Running browser >
driver = webdriver.Firefox()

# Maximizing the browser >
driver.maximize_window()

# Assigning the URL >
url = 'http://www.chegg.com/schools'

# Opening the URL >
driver.get(url)

# Assigning the keyword >
keyword = 'art'

# Finding the search field >
search_field = driver.find_element_by_id('schools-search-input')

# Sending the keyword
search_field.send_keys(keyword)
search_field.send_keys(Keys.RETURN)

# Verifying visibility
driver.implicitly_wait(10)

def visibility():
    hidden = driver.find_element_by_xpath(
      'html/body/div[2]/div[5]/div[2]/div[1]/a')
    if hidden.is_displayed():
        print('Element is visible')
        return hidden.is_displayed()
    else:
        print('Element is not visible')
        return hidden.is_displayed()
print(visibility())


import itertools

import abc
from beartype import beartype
import rich
import torch
import numpy as np

import data_tokenizer

class OurMetric(abc.ABC):
    @classmethod
    def prepare(cls, tokenizer: data_tokenizer.Tokenizer, pred, label, do_print):
        things_to_ignore = {
            -100,
        } | tokenizer.special_token_ids

        pred = pred.cpu().numpy().tolist()
        label = label.cpu().numpy().tolist()

        cleaned_preds = [x for x in pred if x not in things_to_ignore]
        cleaned_labels = [x for x in label if x not in things_to_ignore]

        return dict(cleaned_preds=cleaned_preds, cleaned_labels=cleaned_labels)

    @abc.abstractmethod
    def add(self, pred: list, label: list, do_print=False, descr=""):
        raise RuntimeError("Shouldn't be run directly")

    @abc.abstractmethod
    def compute(self, *args, **kwargs):
        raise RuntimeError("Shouldn't be run directly")

class EM(OurMetric):
    def __init__(self):
        self.total = 0
        self.correct = 0

    def add(self, pred: list, label: list, do_print=False, descr=""):
        prepped_decoded = list(pred)
        prepped_label = list(label)

        if prepped_decoded == prepped_label:
            self.correct += 1
        else:
            pass

        if do_print:
            rich.print(
                f"(EM) Answer - {descr}: "
                + ", ".join(
                    [
                        f"[green]{a}" if a == b else f"[red]{a}"
                        for a, b in itertools.zip_longest(
                            prepped_decoded, prepped_label, fillvalue=""
                        )
                        if a
                    ]
                )
            )
            rich.print(
                f"(EM) Label  - {descr}: "
                + ", ".join(
                    [
                        f"[green]{b}" if a == b else f"[red]{b}"
                        for a, b in itertools.zip_longest(
                            prepped_decoded, prepped_label, fillvalue=""
                        )
                        if b
                    ]
                )
            )

        self.total += 1

    def compute(self):
        return self.correct / self.total

# class RecallAcc:
#     def __init__(self):
#         self.recall_accuracies = []

#     @beartype
#     def add(self, pred: list, label: list, do_print: bool = False, descr=""):
#         recall_acc_decoded = list(pred)
#         recall_acc_label = list(label)

#         if len(recall_acc_decoded) < len(recall_acc_label):
#             recall_acc_decoded += [0] * (len(recall_acc_la el) - len(recall_acc_decoded))
#         elif len(recall_acc_decoded) > len(recall_acc_label):
#             recall_acc_decoded = recall_acc_decoded[:len(recall_acc_label)]

#         recall_acc_label_np =   np.array(recall_acc_label,   dtype=np.int64)
#         recall_acc_decoded_np = np.array(recall_acc_decoded, dtype=np.int64)
#         recall_acc =            np.mean(recall_acc_decoded_np == recall_acc_label_np)

#         self.recall_accuracies.append(recall_acc)

#     def compute(self):
#         return np.mean(self.recall_accuracies)

# class PrecisionAcc:
#     def __init__(self):
#         self.precision_accuracies = []

#     @beartype
#     def add(self, pred: list, label: list, do_print: bool = False, descr=""):
#         precision_acc_decoded = list(pred)
#         precision_acc_label = list(label)

#         if len(precision_acc_decoded) > len(precision_acc_label):
#             precision_acc_label += [0] * (len(precision_acc_decoded) - len(precision_acc_label))
#         elif len(precision_acc_decoded) < len(precision_acc_label):
#             precision_acc_label = precision_acc_label[:len(precision_acc_decoded)]

#         precision_acc_label_np =   np.array(precision_acc_label,   dtype=np.int64)
#         precision_acc_decoded_np = np.array(precision_acc_decoded, dtype=np.int64)
#         precision_acc =            np.mean(precision_acc_decoded_np == precision_acc_label_np)

#         self.precision_accuracies.append(precision_acc)

#     def compute(self):
#         return np.mean(self.precision_accuracies)


from . import SimpleView

from UM.i18n import i18nCatalog
i18n_catalog = i18nCatalog("uranium")

def getMetaData():
    return {
        "type": "view",
        "plugin": {
            "name": i18n_catalog.i18nc("@label", "Simple View"),
            "author": "Ultimaker",
            "version": "1.0",
            "description": i18n_catalog.i18nc("@info:whatsthis", "Provides a simple solid mesh view."),
            "api": 3
        },
        "view": {
            "name": i18n_catalog.i18nc("@item:inmenu", "Simple"),
            "visible": False
        }
    }

def register(app):
    return { "view": SimpleView.SimpleView() }


import random
from datetime import datetime, timedelta

# from io import BytesIO

import discord
from discord.ext import tasks, commands

from utils.pdf import get_events

class TaskCog(commands.Cog):
    def __init__(self, bot):
        self.bot = bot
        self.change_bot_activity.start()
        self.send_message_when_user_no_role.start()
        self.check_event.start()

    @tasks.loop(minutes=10.0)
    async def change_bot_activity(self):
        activity = random.choice(self.bot.config["discord"]["bot_activity"])
        await self.bot.change_presence(
            activity=discord.Game(activity), status=discord.Status.online
        )

    @change_bot_activity.before_loop
    async def before_send(self):
        await self.bot.wait_until_ready()

        return

    @tasks.loop(hours=24)
    async def send_message_when_user_no_role(self):
        """
        When user has no role after a certain amount of time
        Send a PM to tell him to take a role
        """
        for m in self.bot.get_all_members():
            if m.bot == False:
                if (
                    m.joined_at
                    >= datetime.now()
                    - timedelta(days=self.bot.config["user_no_role_reminder"]["days"])
                    and len(m.roles) == 0
                ):
                    await m.send(self.bot.config["user_no_role_reminder"]["message"])

    @tasks.loop(hours=24)
    async def check_event(self):
        # Not implemented in ilovepdf atm
        """
        auth = requests.post(
            f"{self.bot.config['ilovepdf']['base_url']}{self.bot.config['ilovepdf']['auth_endpoint']}",
            data={ "public_key": self.bot.config['ilovepdf']['public_key'] }
        )
        c_task = requests.get(
            f"{self.bot.config['ilovepdf']['base_url']}{self.bot.config['ilovepdf']['start_endpoint']}/extract",
            headers={ "Authorization": f"Bearer {auth.json()['token']}" }
        )
        requests.post(
            f"{self.bot.config['ilovepdf']['base_url']}{self.bot.config['ilovepdf']['upload_endpoint']}",
            params={ "task": c_task.json()["task"],"cloud_file": self.bot.config['event_pdf_link'] },
            headers={ "Authorization": f"Bearer {auth.json()['token']}" }
        )
        g_task = None
        while g_task is None or g_task.json()["status"] in ["TaskWaiting", "TaskProcessing"]:
            g_task = requests.get(
                f"{self.bot.config['ilovepdf']['base_url']}{self.bot.config['ilovepdf']['task_endpoint']}/{c_task.json()['task']}",
                headers={ "Authorization": f"Bearer {auth.json()['token']}" }
            )
            time.sleep(5)

        file = requests.get(
            f"{self.bot.config['ilovepdf']['base_url']}{self.bot.config['ilovepdf']['download_endpoint']}/{c_task.json()['task']}",
            headers={ "Authorization": f"Bearer {auth.json()['token']}" }
        )
        get_events(BytesIO(file.content))
        """
        events = get_events(
            self.bot.config["lyon2_event"]["file"],
            self.bot.config["lyon2_event"]["max_days_to_check"],
        )
        embed = discord.Embed(
            title="Lyon 2 calendrier universitaire",
            description=f"Evénements dans les {self.bot.config['lyon2_event']['max_days_to_check']} prochains jours",
            color=0xFF0000,
        )
        embed.set_footer(
            text=f"Dernière mise à jour le {datetime.now().strftime('%d/%m/%Y, %H:%M:%S')}"
        )
        for event in events:
            embed.add_field(
                name=event["title"],
                value=f"Du {event['start']} au {event['end']}",
                inline=False,
            )
        for g in self.bot.config["lyon2_event"]["guilds"]:
            channel = self.bot.get_channel(g["channel_id"])
            msg = await channel.fetch_message(g["message_id"])
            await msg.edit(embed=embed, content="")

    @check_event.before_loop
    async def before_check_event(self):
        await self.bot.wait_until_ready()

def setup(bot):
    bot.add_cog(TaskCog(bot))


#FIXME: should be registered to signal pre_save
"""
@author: Jozsef Steger, David Visontai
@summary: project manipulation logic
"""
import logging

from kooplex.lib import Docker

logger = logging.getLogger(__name__)

def configure_project(project, **kw):#image, scope, volumes, collaborators, description):
    from hub.models import VolumeProjectBinding
    """
    @summary: configure a user project
              1. set image and scope
              2. manage volume project bindings
              3. manage user project bindings and manage gitlab sharing
    @param project: the project model
    @type project: kooplex.hub.models.Project
    @param kw: the values to set
    @type kw: dict of parameters to set
    @return the number of running containers marked to be removed
    """
    mark_to_remove = False
    logger.debug(project)
    volumes = set(kw.get('volumes', []))

    old_volumes = set(project.functional_volumes).union(project.storage_volumes)

    logger.debug("old: %s new: %s" % (old_volumes, volumes))

    if old_volumes != volumes:
        mark_to_remove = True
        vol_remove = old_volumes.difference( volumes )
        vol_add = volumes.difference( old_volumes )
        logger.debug("- %s" % vol_remove)
        for volume in vol_remove:
            VolumeProjectBinding.objects.get(volume = volume, project = project).delete()
        logger.debug("+ %s" % vol_add)
        for volume in vol_add:
            VolumeProjectBinding.objects.create(volume = volume, project = project)

#    project.scope = scope
#    for vpb in VolumeProjectBinding.objects.filter(project = project):
#        if vpb.childvolume in volumes:
#            logger.debug("volume project binding remains %s" % vpb)
#            volumes.remove(vpb.childvolume)
#        else:
#            mark_to_remove = True
#            logger.debug("volume project binding removed %s" % vpb)
#            vpb.delete()
#    for volume in volumes:
#        mark_to_remove = True
#        vpb = VolumeProjectBinding(project = project, volume = volume)
#        logger.debug("volume project binding added %s" % vpb)
#        vpb.save()
#    for upb in UserProjectBinding.objects.filter(project = project):
#        if upb.user in collaborators:
#            logger.debug("collaborator remains %s" % upb)
#            collaborators.remove(upb.user)
#        else:
#            logger.debug("collaborator removed %s" % upb)
#            unshare_project_oc(project, upb.user)
#            upb.delete()
#    for user in collaborators:
#        join_project(project, user, gitlab)
    n_affected_running_containers = mark_containers_remove(project) if mark_to_remove else 0
    project.save()
    return n_affected_running_containers

def mark_containers_remove(project):
    """
    @summary: mark project containers to be removed when they are stopped next time. In case the container is already stopped, remove them
    @param project: the project model
    @type project: kooplex.hub.models.Project
    @returns the number of containers marked for removal
    @rtype int
    """
    n_mark = 0
    n_remove = 0
    for container in project.containers:
        if container.is_running:
            container.mark_to_remove = True
            container.save()
            n_mark += 1
        else:
            Docker().remove_container(container)
            n_remove += 1
    logger.info("project %s: %d containers removed, %d containers marked for removal" % (project, n_remove, n_mark))
    return n_mark

#def join_project(project, user, gitlab = None):
#    """
#    @summary: join a user project
#              1. add a new user project binding
#              2. owncloud share
#              3. gitlab project on the user's behalf
#    @param project: the project model
#    @type project: kooplex.hub.models.Project
#    @param user: the collaborator to join the project
#    @type user: kooplex.hub.models.User
#    @param gitlab: a gitlab driver instance, defaults to None, which means we are initializing a new here
#    @type gitlab: kooplex.lib.Gitlab
#    """
#    if gitlab is None:
#        gitlab = Gitlab(project.owner)
#    logger.debug(project)
#    upb = UserProjectBinding(project = project, user = user)
#    logger.debug("collaborator added %s" % upb)
#    share_project_oc(project, upb.user)
#    gitlab.add_project_member(project, upb.user)
#    mkdir_git_workdir(upb.user, project)
#    create_clone_script(project, collaboratoruser = upb.user)
#    upb.save()
#    logger.info("%s joins project %s" % (user, project))

#def leave_project(project, user):
#    """
#    @summary: leave a user project
#              1. remove user project binding
#              2. garbage collect data in git workdir
#              3. owncloud unshare
#              6. get rid of containers if any
#              7. delete gitlab project on the user's behalf
#    @param project: the project model
#    @type project: kooplex.hub.models.Project
#    @param user: the collaborator to leave the project
#    @type user: kooplex.hub.models.User
#    """
#    logger.debug(project)
#    try:
#        upb = UserProjectBinding.objects.get(project = project, user = user)
#        upb.delete()
#        logger.debug('user project binding removed: %s' % upb)
#    except UserProjectBinding.DoesNotExist:
#        msg = 'user %s is not bound to project %s' % (user, project)
#        logger.error(msg)
#        return msg
#    gitlab = Gitlab(project.owner)
#    cleanup_git_workdir(user, project)
#    unshare_project_oc(project, user)
#    gitlab.delete_project_member(project, user)
#    try:
#        container = ProjectContainer.objects.get(user = user, project = project)
#        logger.debug("remove container %s" % container)
#        remove_container(container)
#    except ProjectContainer.DoesNotExist:
#        logger.debug("%s has no container" % project)
#    logger.info("%s left project %s" % (user, project))


from typing import Optional, List, Dict, Tuple

from robocorp_ls_core.lsp import CompletionItemTypedDict
from robocorp_ls_core.protocols import check_implements, IDocumentSelection
from robocorp_ls_core.robotframework_log import get_logger
from robotframework_ls.impl.protocols import (
    ICompletionContext,
    IRobotDocument,
    IVariablesCollector,
    IVariableFound,
    IRobotToken,
    TokenInfo,
    AbstractVariablesCollector,
    VariableKind,
    INode,
    AdditionalVarInfo,
)
from robotframework_ls.impl.text_utilities import normalize_robot_name
from robotframework_ls.impl.variable_types import (
    VariableFoundFromToken,
    VariableFoundFromYaml,
)
from robotframework_ls.impl.ast_utils import KEYWORD_SET_ENV_TO_VAR_KIND

log = get_logger(__name__)

class _Collector(AbstractVariablesCollector):
    def __init__(
        self,
        selection: IDocumentSelection,
        in_expression: bool,
        tokens_and_matchers,
        in_assign: bool,
        add_prefix: Optional[str],
    ):
        self.completion_items: List[CompletionItemTypedDict] = []
        self.selection = selection
        self.in_expression = in_expression
        self._in_assign = in_assign
        if add_prefix:
            self._add_prefix_label: Optional[str] = add_prefix
            self._add_prefix_text: Optional[str] = add_prefix.replace("$", "\\$")
        else:
            self._add_prefix_label = self._add_prefix_text = None

        self._tokens_and_matchers = tokens_and_matchers

    def _create_completion_item_from_variable(
        self,
        variable_found: IVariableFound,
        selection: IDocumentSelection,
        token: IRobotToken,
    ) -> CompletionItemTypedDict:
        from robocorp_ls_core.lsp import (
            CompletionItem,
            InsertTextFormat,
            Position,
            Range,
            TextEdit,
        )
        from robocorp_ls_core.lsp import CompletionItemKind

        label = variable_found.variable_name

        if self.in_expression:
            # On expressions without '${...}' (just $var_name), we can't use spaces.
            label = label.replace(" ", "_")

        text = label
        text = text.replace("$", "\\$")

        if self._add_prefix_label:
            label = self._add_prefix_label + label
            if self.in_expression:
                text = r"%s%s" % (self._add_prefix_text, text)
            else:
                text = r"%s{%s}" % (self._add_prefix_text, text)

        text_edit = TextEdit(
            Range(
                start=Position(selection.line, token.col_offset),
                end=Position(selection.line, token.end_col_offset),
            ),
            text,
        )

        # text_edit = None
        return CompletionItem(
            label,
            kind=CompletionItemKind.Variable,
            text_edit=text_edit,
            documentation=variable_found.variable_value,
            insertTextFormat=InsertTextFormat.Snippet,
        ).to_dict()

    def accepts(self, variable_name: str) -> bool:
        return True

    def on_variable(self, variable_found: IVariableFound):
        from robotframework_ls.impl.string_matcher import RobotStringMatcher

        matcher: RobotStringMatcher
        token: IRobotToken

        for token, matcher in self._tokens_and_matchers:
            if not matcher.accepts(variable_found.variable_name):
                continue

            if self._in_assign and token.value == variable_found.variable_name:
                continue

            self.completion_items.append(
                self._create_completion_item_from_variable(
                    variable_found, self.selection, token
                )
            )
            break

    def __typecheckself__(self) -> None:
        _: IVariablesCollector = check_implements(self)

def _collect_variables_from_set_keywords(
    ast,
    completion_context: ICompletionContext,
    collector: IVariablesCollector,
    accept_sets_in: Dict[str, str],
    env_vars: bool = False,
):
    from robot.api import Token
    from robotframework_ls.impl import ast_utils

    for keyword_usage in ast_utils.iter_keyword_usage_tokens(
        ast, collect_args_as_keywords=True
    ):
        var_kind = accept_sets_in.get(normalize_robot_name(keyword_usage.name))
        if var_kind is not None:
            var_name_tok = None
            var_value_tok = None
            for tok in keyword_usage.node.tokens:
                if tok.type == Token.ARGUMENT:
                    if var_name_tok is None:
                        var_name_tok = tok
                    else:
                        var_value_tok = tok
                        break

            if var_name_tok is not None:
                var_name = var_name_tok.value
                start_offset = var_name_tok.col_offset

                if var_name.startswith("\\"):
                    var_name = var_name[1:]
                    start_offset += 1

                if var_name.startswith(("@", "$", "&", "%")):
                    var_name = var_name[1:]
                    start_offset += 1

                if var_name.startswith("{") and var_name.endswith("}"):
                    var_name = var_name[1:-1]
                    start_offset += 1

                if env_vars or collector.accepts(var_name):
                    base_token = ast_utils.copy_token_replacing(
                        var_name_tok, col_offset=start_offset, value=var_name
                    )
                    variable_value = ""
                    if var_value_tok is not None:
                        variable_value = var_value_tok.value

                    variable_found = VariableFoundFromToken(
                        completion_context,
                        base_token,
                        variable_value,
                        variable_name=var_name,
                        variable_kind=var_kind,
                        stack=keyword_usage.stack,
                    )
                    if env_vars:
                        collector.on_env_variable(variable_found)
                    else:
                        collector.on_variable(variable_found)

def collect_current_doc_global_variables(
    completion_context: ICompletionContext, collector: IVariablesCollector
):
    """
    Collects global variables used in keywords such as:
        Set Global Variable
        Set Suite Variable

    As well as environment variables used in:
        Set Environment Variable
    """
    from robotframework_ls.impl.ast_utils import KEYWORD_SET_GLOBAL_TO_VAR_KIND

    _collect_variables_from_set_keywords(
        completion_context.get_ast(),
        completion_context,
        collector,
        KEYWORD_SET_GLOBAL_TO_VAR_KIND,
    )

    _collect_variables_from_set_keywords(
        completion_context.get_ast(),
        completion_context,
        collector,
        KEYWORD_SET_ENV_TO_VAR_KIND,
        env_vars=True,
    )

def _collect_current_doc_variables(
    completion_context: ICompletionContext, collector: IVariablesCollector
):
    # Get keywords defined in the file itself
    completion_context.check_cancelled()

    for (
        variable_found
    ) in completion_context.get_doc_normalized_var_name_to_var_found().values():
        if collector.accepts(variable_found.variable_name):
            collector.on_variable(variable_found)

    collect_current_doc_global_variables(completion_context, collector)

def _collect_resource_imports_variables(
    completion_context: ICompletionContext, collector: IVariablesCollector
):
    resource_doc: Optional[IRobotDocument]
    for _node, resource_doc in completion_context.get_resource_imports_as_docs():
        if resource_doc is None:
            continue
        new_ctx = completion_context.create_copy(resource_doc)
        _collect_global_variables_from_document_context(new_ctx, collector)

def _collect_variables_from_variable_import_doc(
    variable_import_doc: IRobotDocument, collector: IVariablesCollector
):
    try:
        if variable_import_doc.path.lower().endswith(".py"):
            python_ast = variable_import_doc.get_python_ast()
            if python_ast is not None:
                from robotframework_ls.impl.variable_completions_from_py import (
                    collect_variables_from_python_ast,
                )

                collect_variables_from_python_ast(
                    python_ast, variable_import_doc, collector
                )

        elif variable_import_doc.path.lower().endswith((".yaml", ".yml")):
            dct_contents = variable_import_doc.get_yaml_contents()
            if isinstance(dct_contents, dict):
                if dct_contents:
                    try_to_compute_line = (
                        variable_import_doc.source.count("\n") * len(dct_contents)
                    ) <= 200
                    # Our (lame) algorithm to find a key will need to iterate
                    # over all lines for all entries, so, do it only for
                    # small docs (consider a better algorithm in the future)...
                    for initial_key, val in dct_contents.items():
                        key = initial_key

                        lineno = 0
                        if try_to_compute_line:
                            try:
                                # We don't have the real lineno during parsing,
                                # so, make a little hack to get something which
                                # may be close...
                                (
                                    lineno,
                                    _,
                                ) = variable_import_doc.get_last_line_col_with_contents(
                                    initial_key
                                )
                            except RuntimeError:
                                pass

                        if collector.accepts(key):
                            collector.on_variable(
                                VariableFoundFromYaml(
                                    key,
                                    str(val),
                                    source=variable_import_doc.path,
                                    lineno=lineno,
                                )
                            )

    except:
        log.exception()

def collect_global_variables_from_document_dependencies(
    completion_context: ICompletionContext,
    collector: IVariablesCollector,
):
    dependency_graph = completion_context.collect_dependency_graph()

    for resource_doc in completion_context.iter_dependency_and_init_resource_docs(
        dependency_graph
    ):
        new_ctx = completion_context.create_copy(resource_doc)
        _collect_current_doc_variables(new_ctx, collector)

    for node, variable_doc in dependency_graph.iter_all_variable_imports_as_docs():
        if variable_doc is None:
            # Note that 'None' documents will only be given for the
            # initial context (so, it's ok to use `completion_context`
            # in this case).
            from robot.api import Token

            node_name_tok = node.get_token(Token.NAME)
            if node_name_tok is not None:
                (
                    value,
                    token_errors,
                ) = completion_context.token_value_and_unresolved_resolving_variables(
                    node_name_tok
                )

                if token_errors:
                    for token_error, error_msg in token_errors:
                        collector.on_unresolved_variable_import(
                            completion_context,
                            node.name,
                            token_error.lineno,
                            token_error.lineno,
                            token_error.col_offset,
                            token_error.end_col_offset,
                            error_msg,
                            value,
                        )

                else:
                    collector.on_unresolved_variable_import(
                        completion_context,
                        node.name,
                        node_name_tok.lineno,
                        node_name_tok.lineno,
                        node_name_tok.col_offset,
                        node_name_tok.end_col_offset,
                        None,
                        value,
                    )
            else:
                collector.on_unresolved_variable_import(
                    completion_context,
                    node.name,
                    node.lineno,
                    node.end_lineno,
                    node.col_offset,
                    node.end_col_offset,
                    None,
                    "",
                )
            continue
        _collect_variables_from_variable_import_doc(variable_doc, collector)

def _collect_global_variables_from_document_context(
    completion_context: ICompletionContext,
    collector: IVariablesCollector,
    only_current_doc=False,
):
    """
    :param only_current_doc:
        If true we won't collect variables from dependencies.
    """

    completion_context.check_cancelled()
    _collect_current_doc_variables(completion_context, collector)

    if not only_current_doc:
        collect_global_variables_from_document_dependencies(
            completion_context, collector
        )

def _collect_arguments(
    completion_context: ICompletionContext,
    stack: Tuple[INode, ...],
    node: INode,
    collector: IVariablesCollector,
):
    from robotframework_ls.impl import ast_utils

    for arg_token in ast_utils.iter_keyword_arguments_as_tokens(node):
        name = arg_token.value
        if collector.accepts(name):
            variable_found = VariableFoundFromToken(
                completion_context,
                arg_token,
                "",
                variable_name=name,
                variable_kind=VariableKind.ARGUMENT,
                stack=stack,
            )
            collector.on_variable(variable_found)

def collect_variables(
    completion_context: ICompletionContext,
    collector: IVariablesCollector,
    only_current_doc=False,
) -> None:
    token_info = completion_context.get_current_token()
    # Note: we'll collect all variables in the current context -- i.e.:
    # Keyword/Test Case locals + globals -- regardless of whether we're inside a
    # variable right now (so, we can just use get_current_token() and not
    # get_current_variable()).
    if token_info is not None:
        collect_local_variables(completion_context, collector, token_info)

    collect_global_variables(completion_context, collector, only_current_doc)

def _collect_global_static_variables(
    completion_context: ICompletionContext,
    collector: IVariablesCollector,
) -> None:
    """
    Collects variables from builtins and settings.
    """
    for (
        var_found
    ) in completion_context.get_settings_normalized_var_name_to_var_found().values():
        if collector.accepts(var_found.variable_name):
            collector.on_variable(var_found)

    for var_found in completion_context.get_builtins_normalized_var_name_to_var_found(
        False
    ).values():
        if collector.accepts(var_found.variable_name):
            collector.on_variable(var_found)

    for (
        var_found
    ) in (
        completion_context.get_arguments_files_normalized_var_name_to_var_found().values()
    ):
        if collector.accepts(var_found.variable_name):
            collector.on_variable(var_found)

def collect_global_variables(
    completion_context: ICompletionContext,
    collector: IVariablesCollector,
    only_current_doc=False,
):
    """
    :param only_current_doc:
        If true we won't collect variables from dependencies nor builtins/settings.
    """
    _collect_global_variables_from_document_context(
        completion_context, collector, only_current_doc=only_current_doc
    )

    if not only_current_doc:
        _collect_global_static_variables(completion_context, collector)

def collect_local_variables(
    completion_context: ICompletionContext,
    collector: IVariablesCollector,
    token_info: TokenInfo,
):
    from robotframework_ls.impl import ast_utils
    from robotframework_ls.impl.ast_utils import KEYWORD_SET_LOCAL_TO_VAR_KIND
    from robotframework_ls.impl.ast_utils import get_local_variable_stack_and_node

    stack: Tuple[INode, ...]

    if token_info.stack:
        stack, stack_node = get_local_variable_stack_and_node(token_info.stack)
    else:
        current_section = completion_context.get_ast_current_section()
        if current_section is None:
            stack = ()  # Note: shouldn't happen in practice.
        else:
            stack = (current_section,)

    for assign_node_info in ast_utils.iter_local_assigns(stack_node):
        completion_context.check_cancelled()
        if collector.accepts(assign_node_info.token.value):
            rep = " ".join(tok.value for tok in assign_node_info.node.tokens)
            if assign_node_info.node.__class__.__name__ == "KeywordCall":
                if assign_node_info.token.lineno == token_info.token.lineno:
                    if not assign_node_info.node.keyword:
                        continue  # Skip the definition we're currently on.
            variable_found = VariableFoundFromToken(
                completion_context,
                assign_node_info.token,
                rep,
                variable_kind=VariableKind.LOCAL_ASSIGN_VARIABLE,
                stack=stack,
            )
            collector.on_variable(variable_found)

    _collect_arguments(completion_context, stack, stack_node, collector)

    _collect_variables_from_set_keywords(
        stack_node, completion_context, collector, KEYWORD_SET_LOCAL_TO_VAR_KIND
    )

def complete(completion_context: ICompletionContext) -> List[CompletionItemTypedDict]:
    from robotframework_ls.impl.string_matcher import RobotStringMatcher
    from robotframework_ls.impl import ast_utils
    from robocorp_ls_core.document_selection import word_to_column

    var_token_info = completion_context.get_current_variable()
    if var_token_info is not None:
        value = var_token_info.token.value
        in_assign = var_token_info.token.type == var_token_info.token.ASSIGN

        in_expression = (
            var_token_info.var_info.context == AdditionalVarInfo.CONTEXT_EXPRESSION
        )
        collector = _Collector(
            completion_context.sel,
            in_expression,
            [(var_token_info.token, RobotStringMatcher(value))],
            in_assign,
            add_prefix=None,
        )
        only_current_doc = False
        if in_assign:
            # When assigning to variables we don't want to assign what's not
            # currently in this document (such as builtins).
            only_current_doc = True

        collect_variables(
            completion_context, collector, only_current_doc=only_current_doc
        )
        return collector.completion_items

    # Ok, we don't have a variable started, so, let's see if we're in a scope
    # where we should add the full variable...
    token_info = completion_context.get_current_token()
    if token_info and token_info.token:
        token = token_info.token

        if token.type not in (token.ARGUMENT, token.NAME, token.EOL):
            return []

        if token.type == token.EOL:
            token = ast_utils.create_empty_token_name_at_eol(token)

        # It something as:
        # Log to console    v|
        # to become:
        # Log to console    ${variable chosen}
        #
        # or
        #
        # Log to console    some v| other
        # to become:
        # Log to console    some ${variable chosen} other
        #
        # or
        #
        # Log to console    arg=v|
        # to become:
        # Log to console    arg=${variable chosen}

        in_expression = ast_utils.is_node_with_expression_argument(token_info.node)
        cp = ast_utils.copy_token_with_subpart_up_to_col(
            token, completion_context.sel.col
        )

        tokens_and_matchers = [(token, RobotStringMatcher(token.value))]

        word = word_to_column(cp.value)
        add_prefix = "$"

        if word != cp.value:
            i = cp.value.rfind(word)

            word_starts_with_variable_prefix = False
            if i > 0:
                c = cp.value[i - 1]
                if c == "$":
                    add_prefix = "$"
                    word_starts_with_variable_prefix = True

                elif c == "@":
                    add_prefix = "@"
                    word_starts_with_variable_prefix = True

                elif c == "&":
                    add_prefix = "&"
                    word_starts_with_variable_prefix = True

            if word_starts_with_variable_prefix:
                # The token must have the '$' part but the string matcher not (so
                # add the -1 to add it and skip it afterwards).
                cp = ast_utils.copy_token_with_subpart(
                    cp, len(cp.value) - len(word) - 1, len(cp.value)
                )
                tokens_and_matchers.append((cp, RobotStringMatcher(cp.value[1:])))
            else:
                cp = ast_utils.copy_token_with_subpart(
                    cp, len(cp.value) - len(word), len(cp.value)
                )
                tokens_and_matchers.append((cp, RobotStringMatcher(cp.value)))

        collector = _Collector(
            completion_context.sel,
            in_expression,
            tokens_and_matchers,
            in_assign=False,
            add_prefix=add_prefix,
        )
        collect_variables(completion_context, collector, only_current_doc=False)
        return collector.completion_items

    return []


# -*- coding: utf-8 -*-
from django.core.files.base import ContentFile

from django.db import IntegrityError
from django.contrib.auth.models import User
from django.contrib.auth import password_validation
from django.core import exceptions
from django.utils import timezone
from django.contrib.auth.forms import SetPasswordForm
from django.contrib.auth.models import Permission
from rest_framework import serializers

from models import *
from administrador.models import *

class ProcesoAlumnoItemsSerializer(serializers.ModelSerializer):
	id = serializers.IntegerField(required=False)
	name = serializers.CharField(required=False)
	process_id = serializers.IntegerField(required=False)
	description = serializers.CharField(required=False)

	class Meta:
		model = ProcesoAlumnoItems
		fields = (
			'id',
			'name',
			'process_id',
			'process_alumno',
			'description',
		)
		depth = 1
		read_only_fields = (
			'id', 'deleted',
			)

	def __init__(self, *args, **kwargs):
		self.is_update = kwargs.pop('is_update', False)
		super(ProcesoAlumnoItemsSerializer, self).__init__(*args, **kwargs)

	def validate(self, data):
		result = super(ProcesoAlumnoItemsSerializer, self).validate(data)
		return result

class ProcesoAlumnoSerializer(serializers.ModelSerializer):
	id = serializers.IntegerField(required=False)
	process_id = serializers.IntegerField(required=False)
	alumn_id = serializers.IntegerField(required=False)
	subject = serializers.CharField(required=False)

	class Meta:
		model = ProcesoAlumno
		fields = (
			'id',
			'alumn',
			'process_id',
			'alumn_id',
			'process',
			'subject',
		)
		depth = 1
		read_only_fields = (
			'id', 'deleted',
			)

	def __init__(self, *args, **kwargs):
		self.is_update = kwargs.pop('is_update', False)
		super(ProcesoAlumnoSerializer, self).__init__(*args, **kwargs)

	def validate(self, data):
		result = super(ProcesoAlumnoSerializer, self).validate(data)
		return result

class ProcesoSerializer(serializers.ModelSerializer):
	class Meta:
		model = Proceso
		fields = (
			'name',
			'id',
		)
		depth = 1
		read_only_fields = (
			'id', 'deleted',
			)

	def __init__(self, *args, **kwargs):
		self.is_update = kwargs.pop('is_update', False)
		super(ProcesoSerializer, self).__init__(*args, **kwargs)

	def validate(self, data):
		result = super(ProcesoSerializer, self).validate(data)
		return result

class AlumnoSerializer(serializers.ModelSerializer):
	class Meta:
		model = Alumno
		fields = (
			'user',
		)
		depth = 1
		read_only_fields = (
			'id', 'deleted',
			)

	def __init__(self, *args, **kwargs):
		self.is_update = kwargs.pop('is_update', False)
		super(AlumnoSerializer, self).__init__(*args, **kwargs)

	def validate(self, data):
		result = super(AlumnoSerializer, self).validate(data)
		return result

class ProcesoAlumnoWSSerializer(serializers.ModelSerializer):
	subject = serializers.CharField(required=False)
	process = ProcesoSerializer()
	# alumn = AlumnoSerializer()

	class Meta:
		model = ProcesoAlumno
		fields = (
			'alumn',
			'process',
			'subject',
			'notes',
			'id',
		)
		depth = 1
		read_only_fields = (
			'id', 'deleted',
			)

	def __init__(self, *args, **kwargs):
		self.is_update = kwargs.pop('is_update', False)
		super(ProcesoAlumnoWSSerializer, self).__init__(*args, **kwargs)

	def validate(self, data):
		result = super(ProcesoAlumnoWSSerializer, self).validate(data)
		return result


import numpy as np
import pandas as pd
import os

import hashlib
import json
import decimal

import csv
import boto3
#from decimal import *

from Exporer import Exporter
import httplib2
import oauth2client
import httplib2
import argparse
import apiclient

import sys
from apiclient import discovery
from oauth2client.service_account import ServiceAccountCredentials

def exportToDataFrame():

    exporter = Exporter()

    table_name = "schedular"
    print("-" * 30)
    print("dynamo Table name : ", table_name)
    rows, _ = exporter.get_rows(table_name)

    df = pd.io.json.json_normalize(rows)
    columns_ = df.columns
    dot_splitter = lambda x: x.split('.')[0]

    columns_ = list( map( dot_splitter, columns_ )   )
    df.columns = columns_

    print(df.columns.tolist())

    newcolname = ["name","hospital","medicine","nextDate","total_amount","expiry","czDate"]
    df_ = df[newcolname].copy()
    df_["mark"] = ""
    df_["mark2"] = ""
    df_["standard"] = ""

    newcolname = ["name","mark","hospital","medicine","nextDate","total_amount","mark2","expiry","standard","czDate"]
    df_new = df_.copy()
    df_new = df_new[newcolname]

    print(df_new.shape)
    print(df_new.loc[0,:])
    return df_new

def insertDataSheet(df):

    SCOPES = 'https://www.googleapis.com/auth/spreadsheets'
    APPLICATION_NAME = 'read sample'  #
    SHEET_ID = '17iCNpYNaM4Lt88LtrBfJKCcwfLSdb8wLkFz1kicRk5o'
    RANGE = 'A:J'  #
    # -----------------------------------------------------------------------------
    # read credential file
    store = oauth2client.file.Storage("./credential.json")  # is there any credential file ?
    credentials = store.get()

    # allow ?
    if not credentials or credentials.invalid:
        flow = oauth2client.client.flow_from_clientsecrets('client_secret.json', SCOPES)
        flow.user_agent = APPLICATION_NAME

        # initialize
        import argparse
        args = '--auth_host_name localhost --logging_level INFO --noauth_local_webserver'
        flags = argparse.ArgumentParser(parents=[oauth2client.tools.argparser]).parse_args(args.split())

        credentials = oauth2client.tools.run_flow(flow, store, flags)  #

    # access to use credentials
    http = credentials.authorize(httplib2.Http())

    # read sheets

    service = apiclient.discovery.build('sheets', 'v4', http=http, discoveryServiceUrl='https://sheets.googleapis.com/$discovery/rest?version=v4')

    #request = service.spreadsheets().get(spreadsheetId=spreadsheet_id, ranges=ranges, includeGridData=include_grid_data)

    values = service.spreadsheets().values().get(spreadsheetId=SHEET_ID, range=RANGE).execute().get('values', [])

    resource = service.spreadsheets().values()

    print("-" * 40)
    print(" call dynamodb ....")
    RANGE_NAME = "A2"
#    df = exportToDataFrame()
    df = df.fillna("")

    print("total record(s) of dynamodb.." , len(df)  )

    if df.shape[0] > 0:
        data = df.values.tolist()

        body = {
            "range": RANGE_NAME ,
            "majorDimension": "ROWS",
            "values": data
        }

        resource.append(spreadsheetId=SHEET_ID, range=RANGE_NAME,
                        valueInputOption='USER_ENTERED', body=body).execute()

    else:
        print("Sorry, but data is ZERO.")

def main():

    df = exportToDataFrame()
    insertDataSheet(df)

if __name__ == "__main__":
    main()


# -*- coding: utf-8 -*-
# I think this file will not be needed

import numpy as np
import matplotlib.pyplot as plt
import cv2 as cv
import time
import os

DATADIR = 'C:/Users/Pollen/project/dataset'  #change the last letter after finishing the data collection "C:/Users/Light/project/dataset/Y"#and also changed the name Light to Pollen after windows setup
CATEGORIES = ["SNEEZE", "MEDICINE", "INFECTION", "INHALER", "BROKE", "BLOOD PRESSURE", \
              "FORGOT", "WHEN", "BAD", "GOOD", "FATHER", "MOTHER", "NEVER", "GUILT", \
              "SHOWER", "BETTER", "WAKE UP", "GLASS", "DEATH", "LIFE", "DAY", "BALL", \
              "ADULT", "STREET OR STRAIGHT", "AIRPLANE", "FEAR", "READ", "THANK YOU", \
              "TRUST", "LOVE", "DOCTOR", "BOOK", "TREE", "EYE", "SMILE", "PICTURE", "PAIN", \
              "DONT CARE", "DONT KNOW", "HELP", "MOON", "SHOES", "LEARN", "CAT", "DOG", "WORK", \
              "PHONE", "WATER", "BABY", "FOOD", "BED", "PERSON", "DEAF", "CAR", "BEAUTIFUL", "AGAIN", \
              "WHAT", "UNDERSTAND", "PLEASE", "NO", "YES", "HELLO" ]

CATEGORIES2 = ["ADULT", "AGAIN", "AIRPLANE", "BABY", "BAD", "BALL", \
               "BEAUTIFUL", "BED", "BETTER", "BLOOD PRESSURE", "BOOK", "BROKE", \
               "CAR", "CAT", "DAY", "DEAF", "DEATH", "DOCTOR", \
               "DONT CARE", "DONT KNOW", "EYE", "FATHER", "FEAR", "FOOD", \
               "FORGOT", "GLASS", "GOOD", "GOOD BYE", "GUILT", "HELLO", \
               "HELP", "INFECTION", "INHALER", "LEARN", "LIFE", "LOVE", \
               "MEDICINE", "MOON", "MOTHER", "NEVER", "NO", "PAIN", \
               "PERSON", "PHONE", "PICTURE", "PLEASE", "READ", "SHOES", \
               "SHOWER", "SMILE", "SNEEZE", "STREET", "THANK YOU", "TREE", \
               "TRUST", "UNDERSTAND", "WAKE UP", "WATER", "WHAT", "WHEN", \
               "WORK", "YES"]

print(len(CATEGORIES))
print(len(CATEGORIES2))


bags = dict()
def has_shiny_gold(name):
	if name == 'shiny gold':
		return True
	if len(bags[name]) == 0:
		return False
	return any([r for r in bags[name] if r == 'shiny gold' or has_shiny_gold(r)])

for rule in open('input.txt', 'r').readlines():
	rule.rstrip('\n')
	rule = rule.replace('.', '')
	bag_name = rule.split(' contain')[0].replace(' bags', '')
	bags[bag_name] = set()
	rules = rule.split('contain ')[1]
	if 'no other' in rules:
		continue
	rules = rules.replace('bags', 'bag')
	rule_list = rules.split(' bag')
	for i in range(len(rule_list) - 1):
		rule = rule_list[i]
		rule = rule.replace(', ', '')
		bags[bag_name].add(rule[2:])

cnt = 0
for name, rules in bags.items():
	for rule in rules:
		if has_shiny_gold(rule):
			cnt += 1
			break

print(cnt)


class Solution:
    def majorityElement(self, nums: List[int]) -> int:
        n=len(nums)
        cache={} #key=num : value= count

        for i in nums: #keeping count of occurence of every element
            if i in cache.keys():
                cache[i]+=1
            else:
                cache[i]=1

        a=list(cache.keys()) #making a list of all distinct elements
        for j in a:
            if cache[j]>int(n/2): #we return the element whose count is greater than n/2
                return j
        return -1


import string

up_let = string.ascii_uppercase
low_let = string.ascii_lowercase

with open("data/d03.txt") as f:
    input = f.read().split("\n")

def solve_p1(data:list[str], up:list[str], low:list[str]) -> int:
    '''
    Solves day 3 part 1 of AOC 2022
    Parameters: data -- list[str], up -- list[str], low -- list[str]
    Returns: value -- int
    '''
    lhs = [s[0:len(s)//2] for s in data]
    rhs = [s[len(s)//2:len(s)] for s in data]

    it = 0

    for ii in range(len(data)):
        for jj in range(len(lhs[ii])):
            if rhs[ii].find(lhs[ii][jj]) > -1:
                if up.find(lhs[ii][jj]) > -1:
                    it += up.find(lhs[ii][jj]) + 27
                    break
                else:
                    it += low.find(lhs[ii][jj]) + 1
                    break
            else:
                continue

    return it

def solve_p2(data, up:list[str], low:list[str]) -> int:
    '''
    Solves day 3 part 2 of AOC 2022
    Parameters: data -- list[str], up -- list[str], low -- list[str]
    Returns: value -- int
    '''
    it = 0

    for ii in range(len(input)):
        if (ii+1) % 3 != 0:
            continue
        else:
            for jj in input[ii]:
                if (input[ii-1].find(jj) > -1) and (input[ii-2].find(jj) > -1):
                    if up.find(jj) > -1:
                        it += up.find(jj) + 27
                        break
                    else:
                        it += low.find(jj) + 1
                        break

    return it

# Part 1 Answer
print(solve_p1(input, up_let, low_let))

# Part 2 Answer
print(solve_p2(input, up_let, low_let))


import torch
import math

class NeuralNetwork(object):
    def __init__(self, in_layer, *h_arr):
        self.layers = []
        self.in_layer = in_layer
        self.out_layer = h_arr[-1]
        for i in range(len(h_arr)):
            s = in_layer if i==0 else h_arr[i-1]
            e = h_arr[i]
            l = torch.normal(means=torch.zeros(e, s+1), std=torch.zeros(e, s+1).fill_(1/math.sqrt(e))).type(torch.DoubleTensor)
            self.layers.append(l)

    def getLayer(self, layer):
        return self.layers[layer-1]

    def forward(self, input):
        output = input.view(input.size()[0], 1) if len(input.size()) == 1 else input
        for idx, layer in enumerate(self.layers):
            bias = torch.ones(1, output.size()[1]).type(torch.DoubleTensor)
            output = torch.cat((bias, output), 0)
            output = torch.sigmoid(layer.mm(output))
        return output


import random
from checks import exitCheck, numCheck, symCheck
#This is a game for guessing a number between 1-10
def guessingGame():
    random_number = random.randint(1,11)
    user_guess = input("Guess a random number between 1-10. ")
    exitCheck(user_guess)
    if user_guess.isdigit():
        if random_number == int(user_guess):
            print ("Correct!")
        else:
            print ("Sorry the correct answer was ",random_number, " , try again.")
    else:
        print ("Please enter an integer.")
        guessingGame()

def ageGuess():
    movie = {"Cars":5, "The Dark Knight":13, "Shawshank Redemption":30, "Gone with the Wind":70}
    TV = {"Dora the Explorer":5, "Adventure Time":13, "Game of Thrones":30, "Golden Girls":70}
    food = {"Apple Sauce":5, "Pizza":13, "Steak":30, "Tapioca Pudding":70}
    choices = {"movie":0, "tv":0, "food":0}

    while True:
        print("What is your favorate Movie?")
        print("1. Cars")
        print("2. The Dark Knight")
        print("3. Shawshank Redemption")
        print("4. Gone with the Wind")
        print("5. Exit Game")

        user_input = input()
        exitCheck(user_input)
        while not(user_input == "1" or user_input == "2" or user_input == "3" or user_input == "4" or user_input == "5"):
            print(user_input)
            print("Invalid input, please try again.")
            user_input = input()
            print(user_input)
            exitCheck(user_input)
        if user_input == "1":
            choices["movie"] = movie["Cars"]
        elif user_input == "2":
            choices["movie"] = movie["The Dark Knight"]
        elif user_input == "3":
            choices["movie"] = movie["Shawshank Redemption"]
        elif user_input == "4":
            choices["movie"] = movie["Gone with the Wind"]
        elif user_input == "5":
            break

        print("What is your favorate TV show?")
        print("1. Dora the Explorer")
        print("2. Adventure Time")
        print("3. Game of Thrones")
        print("4. Golden Girls")
        print("5. Exit Game")

        user_input = input()
        exitCheck(user_input)
        while not(user_input == "1" or user_input == "2" or user_input == "3" or user_input == "4" or user_input == "5"):
            print("Invalid input, please try again.")
            user_input = input()
            exitCheck(user_input)
        if user_input == "1":
            choices["tv"] = TV["Dora the Explorer"]
        elif user_input == "2":
            choices["tv"] = TV["Adventure Time"]
        elif user_input == "3":
            choices["tv"] = TV["Game of Thrones"]
        elif user_input == "4":
            choices["tv"] = TV["Golden Girls"]
        elif user_input == "5":
            break

        print("What is your favorate food?")
        print("1. Apple Sauce")
        print("2. Pizza")
        print("3. Steak")
        print("4. Tapioca Pudding")
        print("5. Exit Game")

        user_input = input()
        exitCheck(user_input)
        while not(user_input == "1" or user_input == "2" or user_input == "3" or user_input == "4" or user_input == "5"):
            print("Invalid input, please try again.")
            user_input = input()
            exitCheck(user_input)
        if user_input == "1":
            choices["food"] = food["Apple Sauce"]
        elif user_input == "2":
            choices["food"] = food["Pizza"]
        elif user_input == "3":
            choices["food"] = food["Steak"]
        elif user_input == "4":
            choices["food"] = food["Tapioca Pudding"]
        elif user_input == "5":
            break

        print("You are between the ages of ", min(choices.values()), " and ", max (choices.values()))
        print("Your estimated average age is ", sum(choices.values())/len(choices.values()))


import datetime
import json
import os
import sys
import time
import traceback

import requests
import schedule

cur_path = os.path.split(os.path.realpath(__file__))[0]
file_path = os.path.abspath(os.path.join(cur_path, ".."))
sys.path.insert(0, file_path)

from base import NewsBase, logger
from configs import LOCAL

class OraApi(NewsBase):
    """龙虎榜接口数据"""
    def __init__(self):
        super(OraApi, self).__init__()
        self.url = 'http://bg.jingzhuan.cn?api=stock_rank_INS_Up&timeperiod=1'
        self.idx_table = 'stk_quot_idx'
        self.day = datetime.datetime.combine(datetime.datetime.today(), datetime.time.min)
        # self.day = datetime.datetime(2020, 6, 30)
        self.target_table = 'news_generate'
        self.fields = ['Title', 'Date', 'Content', 'NewsType', 'NewsJson']

    def _create_table(self):
        """
        新闻类型：
        1:  三日连续净流入前10个股
        2:  连板股今日竞价表现
        3:  早盘主力十大净买个股
        4:  开盘异动盘口
        5:  机构首次评级
        6:  获多机构买入增持评级
        7:  龙虎榜-机构净买额最大
        8:  龙虎榜-机构席位最多
        """
        self._target_init()
        sql = '''
        CREATE TABLE IF NOT EXISTS `{}` (
          `id` int(11) NOT NULL AUTO_INCREMENT,
          `NewsType` int NOT NULL COMMENT '新闻类型',
          `Date` datetime NOT NULL COMMENT '日期',
          `NewsJson` json  DEFAULT  NULL COMMENT 'json 格式的新闻数据体',
          `Title` varchar(64) CHARACTER SET utf8 COLLATE utf8_bin DEFAULT NULL COMMENT '生成文章标题',
          `Content` text CHARACTER SET utf8 COLLATE utf8_bin COMMENT '生成文章正文',
          `CREATETIMEJZ` datetime DEFAULT CURRENT_TIMESTAMP,
          `UPDATETIMEJZ` datetime DEFAULT CURRENT_TIMESTAMP ON UPDATE CURRENT_TIMESTAMP,
           PRIMARY KEY (`id`),
           UNIQUE KEY `dt_type` (`Date`, `NewsType`)
        ) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_bin COMMENT='资讯生成表';
        '''.format(self.target_table)
        self.target_client.insert(sql)
        self.target_client.end()

    def get_changepercactual(self, inner_code):
        """获取行情数据"""
        self._dc_init()
        sql = '''select Date, Close, ChangePercActual from {} where InnerCode = '{}' and Date <= '{}' order by Date desc limit 1;
        '''.format(self.idx_table, inner_code, self.day)  # 因为假如今天被机构首次评级立即发布,未收盘前拿到的是昨天的行情数据, 收盘手拿到的是今天的
        ret = self.dc_client.select_one(sql)
        changepercactual = self.re_decimal_data(ret.get("ChangePercActual"))
        _close = self.re_decimal_data(ret.get("Close"))
        _date = ret.get("Date")    # 最近的一个已结束交易日的时间
        # TODO
        assert _date == self.day
        return changepercactual, _close

    def get_resp_datas(self):
        resp = requests.get(self.url)
        if resp.status_code == 200:
            body = resp.text
            datas = json.loads(body).get("response")
            return datas
        else:
            print(resp)
            return None

    def sort_datas(self, datas):
        # 找出机构净买额最大的一个
        datas = sorted(datas, key=lambda x: float(x["SUMNETBUY"]), reverse=True)
        data1 = datas[0]

        # 找出机构席位最多的一个
        datas = sorted(datas, key=lambda x: int(x['INSUP']), reverse=True)
        data2 = datas[0]

        return data1, data2

    def gene_content_maxnetbuy(self, data):
        inner_code, secu_abbr = self.get_juyuan_codeinfo(data['TRD_CODE'])

        title = '今日机构净买额最多个股为{}，机构净买额达{}，总净买额达{}。'.format(secu_abbr,
                                                          self.re_money_data(float(data['SUMNETBUY'])),
                                                          self.re_money_data(float(data['SUMBUY'])))

        changepercactual, _close = self.get_changepercactual(inner_code)
        rise_str = "涨幅" if changepercactual > 0 else "跌幅"
        content = '截至今日收盘，{}机构净买额{}，总净买金额达{}，今日收盘价{}，{}{}%。'.format(
            secu_abbr, self.re_money_data(float(data['SUMNETBUY'])),
            self.re_money_data(float(data['SUMBUY'])),
            _close, rise_str, changepercactual,
        )

        item = dict()
        item["Date"] = self.day
        item['Title'] = title
        item['Content'] = content
        item['NewsType'] = 7
        return item

    def gene_content_maxinsup(self, data):
        inner_code, secu_abbr = self.get_juyuan_codeinfo(data['TRD_CODE'])

        title = '龙虎榜今日机构买入席位最多个股为{}'.format(secu_abbr)

        changepercactual, _close = self.get_changepercactual(inner_code)
        rise_str = "涨幅" if changepercactual > 0 else "跌幅"
        content = '今日龙虎榜机构买席最多个股为{}，{}个机构买入，{}个机构卖出，购买金额为{}。今日收盘价{}，{}{}%。'.format(
            secu_abbr, data['INSBUY'], data['INSSELL'], self.re_money_data(float(data['SUMNETBUY'])),
            _close, rise_str, changepercactual,
        )

        item = dict()
        item["Date"] = self.day
        item['Title'] = title
        item['Content'] = content
        item['NewsType'] = 8
        return item

    def start(self):
        if LOCAL:
            self._create_table()

        is_trading = self.is_trading_day(self.day)
        if not is_trading:
            logger.warning("非交易日")
            return

        datas = self.get_resp_datas()

        if not datas:
            logger.warning("接口异常, 请检查")
            return

        data1, data2 = self.sort_datas(datas)

        item1 = self.gene_content_maxnetbuy(data1)

        item2 = self.gene_content_maxinsup(data2)
        print(item1)
        print(item2)

        self._target_init()
        self._save(self.target_client, item1, self.target_table, self.fields)
        self._save(self.target_client, item2, self.target_table, self.fields)

        # TODO
        self.ding("龙虎榜-机构净买额最大: \n {}\n\n 龙虎榜-机构席位最多: \n{}".format(item1, item2))

def task():
    try:
        OraApi().start()
    except Exception:
        OraApi().ding("龙虎榜资讯生成异常:{} 请检查".format(traceback.format_exc()))

if __name__ == "__main__":
    # TODO
    # task()

    schedule.every().day.at("15:30").do(task)

    schedule.every().day.at("18:06").do(task)

    while True:
        schedule.run_pending()
        time.sleep(10)

'''
docker build -f DockerfileUseApi2p -t registry.cn-shenzhen.aliyuncs.com/jzdev/jzdata/newsgenerator:v2 .
docker push registry.cn-shenzhen.aliyuncs.com/jzdev/jzdata/newsgenerator:v2
sudo docker pull registry.cn-shenzhen.aliyuncs.com/jzdev/jzdata/newsgenerator:v2

sudo docker run --log-opt max-size=10m --log-opt max-file=3 -itd \
--name generate_winlist \
registry.cn-shenzhen.aliyuncs.com/jzdev/jzdata/newsgenerator:v2 \
python WinnersList/winlist_api.py
'''

'''
龙虎榜-机构净买额最大
条件：龙虎榜机构净买额最大个股，收盘时发布
标题：今日机构净买额最多个股为宁德时代，机构净买额达10.04亿，总净买额达12.07亿。
内容：截至今日收盘，宁德时代机构净买额10.04亿，总净买金额达12.07亿，今日收盘价128.21，涨幅/跌幅+3.12%。

龙虎榜-机构席位最多
条件：龙虎榜机构买席数量最多个股，收盘时发布
标题：龙虎榜今日机构买入席位最多个股为山河药辅
内容：今日龙虎榜机构买席最多个股为山河药辅，10个机构买入，6个机构卖出，购买金额为10.12亿。今日收盘价128.21，涨幅/跌幅+3.12%。
'''

'''
 'response': [{
'END_DT': '2020-06-24 00:00:00', # 时间
'INSBUY': '4',                   # 买入结构个数
'INSSELL': '2',                  # 卖出机构个数
'INSUP': '6',                    # INSUP 机构数量=INSBUY+ISSELL
'PREID': '5.48471658',            # 异动值
'SUMBUY': '32152878.0000',        # 总买入
'SUMNETBUY': '20672612.0000',     # 净买入
'SUMSELL': '11480266.0000',       # 总卖出
'TRD_CODE': '002977',             # 股票代码
'userdata': '002977',             # 同上 股票代码
},
'''


from enum import IntEnum
import copy

class Token(IntEnum):
    NONE = 0
    P1 = 1
    P2 = 2

class UTTTError(Exception):
    def __init__(self, value):
        self.value = value

    def __str__(self):
        return repr(self.value)

class UltimateTicTacToe:
    """It's ULTIMATE"""
    def __init__(self):
        self.init_board()

    def init_board(self):
        self.big_board = [Token.NONE for _ in range(9)]
        self.little_boards = [copy.deepcopy(self.big_board) for _ in range(9)]
        self.player_turn = Token.P1
        self.moves = []
        self.winner = Token.NONE
        self.space = -1

    def game_over(self):
        return self.winner != Token.NONE

    def get_winner(self):
        if self.winner == Token.NONE:
            raise UTTTError("There's no winner")
        return "X" if self.winner == Token.P1 else "O"

    def get_player(self):
        return "X" if self.player_turn == Token.P1 else "O"

    def needs_board(self):
        return self.space == -1 or self.big_board[self.space] != Token.NONE

    def select_board(self, space):
        if space < 0 or space > 8:
            raise UTTTError("That space ain't in bounds.")
        if self.big_board[space] != Token.NONE:
            raise UTTTError("That space has already been won.")
        self.space = space

    def place(self, space):
        bx = self.space // 3
        by = self.space % 3
        lx = space // 3
        ly = space % 3
        self.validate_move(bx, by, lx, ly)
        self.place_token(self.player_turn, bx, by, lx, ly)
        self.switch_player()
        self.moves.append((bx, by, lx, ly))

    def place_token(self, token, bx, by, lx, ly):
        self.little_boards[bx*3+by][lx*3+ly] = token
        self.space = lx * 3 + ly
        if self.board_won_by_token(self.little_boards[bx*3+by], token):
            self.big_board[bx*3+by] = token
            if self.board_won_by_token(self.big_board, token):
                self.winner = token

    def undo(self):
        if len(self.moves) < 1:
            raise UTTTError("No moves to undo.")
        bx,by,lx,ly = self.moves.pop()
        self.little_boards[bx*3+by][lx*3+ly] = Token.NONE
        self.switch_player()
        self.space = self.moves[-1][2] * 3 + self.moves[-1][3]

    def switch_player(self):
        self.player_turn = Token.P2 if self.player_turn == Token.P1 else Token.P1

    def board_won_by_token(self, board, token):
        for i in range(3):
            l = []
            for j in range(3):
                l.append(board[i*3+j])
            if all(x == token for x in l):
                return True
        for i in range(3):
            l = []
            for j in range(3):
                l.append(board[j*3+i])
            if all(x == token for x in l):
                return True
        l = []
        for i in range(3):
            l.append(board[i*3+i])
        if all(x == token for x in l):
            return True
        l = []
        for i in range(3):
            l.append(board[i*3+2-i])
        if all(x == token for x in l):
            return True
        return False

    def validate_move(self, bx, by, lx, ly):
        if self.needs_board():
            raise UTTTError("Gotta set a board first bud.")
        if bx < 0 or bx > 2 or by < 0 or by > 2 or lx < 0 or lx > 2 or ly < 0 or ly > 2:
            raise UTTTError("Not a valid spot. All values gotta be between 0 and 2 inclusive.")
        print(bx*3+by)
        if self.big_board[bx*3+by] != Token.NONE:
            raise UTTTError("That little board has already been won.")
        if self.little_boards[bx*3+by][lx*3+ly] != Token.NONE:
            raise UTTTError("There's already a token placed at that spot.")

    def __repr__(self):
        x = f"""
            {self.print_big_row(0)}
            -------------------------
            {self.print_big_row(1)}
            -------------------------
            {self.print_big_row(2)}
            """
        return x

    def print_big_row(self, row):
        return f"""{self.print_little_row(row * 3, 0)}  |  {self.print_little_row(row * 3 + 1, 0)}  |  {self.print_little_row(row * 3 + 2, 0)}
            {self.print_little_row(row * 3, 1)}  |  {self.print_little_row(row * 3 + 1, 1)}  |  {self.print_little_row(row * 3 + 2, 1)}
            {self.print_little_row(row * 3, 2)}  |  {self.print_little_row(row * 3 + 1, 2)}  |  {self.print_little_row(row * 3 + 2, 2)}"""

    def print_little_row(self, lb, row):
        if self.big_board[lb] == Token.P1:
            return ["XX XX", " XXX ", "XX XX"][row]
        if self.big_board[lb] == Token.P2:
            return ["OOOOO", "OO OO", "OOOOO"][row]

        ret = f"""{self.little_boards[lb][row*3+0]}|{self.little_boards[lb][row*3+1]}|{self.little_boards[lb][row*3+2]}"""
        ret = ret.replace("1", "X").replace("2", "O")
        if row < 2:
            return ret.replace("0", "_")
        else:
            return ret.replace("0", " ")

if __name__ == "__main__":
    print("Starting game of Ultimate Tic-Tac-Toe")
    uttt = UltimateTicTacToe()
    while not uttt.game_over():
        print(uttt)
        try:
            if uttt.needs_board():
                print(f"Which board do you want to place in? You're player {uttt.get_player()}.\nOptions: 'u' to undo, 'h' for help, or move in form 'space' (1 <= s <= 9)\n")
            else:
                print(f"What's your move? You're {uttt.get_player()} placing on board {uttt.space + 1}\nOptions: 'u' to undo, 'h' for help, or move in form 'space' (1 <= s <= 9)\n")
            s = input().strip()
            print()
            if s.lower() == "undo" or s.lower() == "u":
                uttt.undo()
                continue
            if s.lower == "help" or s.lower() == "h":
                print("""Spaces arranged in form:
            1|2|3
            4|5|6
            7|8|9
            """)
            m = int(s) - 1
            if uttt.needs_board():
                uttt.select_board(m)
            else:
                uttt.place(m)
        except UTTTError as e:
            print("No can do baby:", e)
        #except Exception as e:
        #    print("Unexpected Error:", e)

    print(f"Yay player {uttt.get_winner()}!")
    print(uttt)
    print(f"Player {uttt.get_winner()} won!")


infile = open('data.txt', 'r')
text_data = infile.readlines()
vals = []
for element in text_data:
  vals.append(element.strip())

DIRS = {'N': (0, 1), 'E': (1, 0), 'S': (0, -1), 'W': (-1, 0)}

posn = (0, 0)
waypoint = (10, 1)

for val in vals:
	if val[0] == 'F':
		n = int(val[1:])
		posn = (posn[0] + (waypoint[0] * n), posn[1] + (waypoint[1] * n))
	elif val[0] == 'L' or val[0] == 'R':
		dire = val[0]
		n =  int((int(val[1:]) / 90) % 4)
		if (dire == 'L' and n == 1) or (dire == 'R' and n == 3):
			waypoint = (waypoint[1] * -1, waypoint[0])
		elif n == 2:
			waypoint = (waypoint[0] * -1, waypoint[1] * -1)
		elif (dire == 'L' and n == 3) or (dire == 'R' and n == 1):
			waypoint = (waypoint[1], waypoint[0] * -1)
	else:
		n = int(val[1:])
		waypoint = (waypoint[0] + DIRS[val[0]][0] * n, waypoint[1] + DIRS[val[0]][1] * n)

print(abs(posn[0]) + abs(posn[1]))