import csv
import itertools
from logging import exception
import copy
from pickletools import ArgumentDescriptor
import random
import re
import sys
import os

# formula to extract the inferred score from the inferences
def scoreFromInference(var2):
	ag_score_infered = []
	for ag in var2:
		# the inferred score is the middle of the inferred interval
		ag_score_infered.append((max(ag[0],ag[2]) + min(ag[1],ag[3]))/2.0)
	return ag_score_infered

# return true if an argument attacks the issue
def attackTarget(agentArgs):
	for arg in agentArgs:
		if(arg in attaquants[0]):
			return True
	return False

# computes the score with respect to the h-categorizer semantic
def getScore(graph, firstValuation = []):
	if(firstValuation == []):
		firstValuation = []
		for item in range(len(graph)): # creation of the new valuation
			firstValuation.append(float(1.0))
	newValuation = []
	stable = True
	for item in range(len(graph)): # creation of the new valuation
		newValuation.append(float(1.0))
	i = 0
	for arg,att in graph.items(): # go through the elements of the graph
		sum = 1.0
		j = 0
		for item in graph:
			if(item in graph[arg]):
				sum += float(firstValuation[j])
			j += 1
		newValuation[i] = float(1.0/sum)
		if(abs(firstValuation[i] - newValuation[i]) > 0.0001): # the treshhold is fixed to 0.0001
			stable = False
		i += 1
	if(stable):
		return float(newValuation[0])
	else:
		return getScore(graph, newValuation)

# computes the positive inference
def turnScoreInference(move, previousTurnScore, argsPlayed, agentsInference):
	if(move.__len__() == 2): # if the agent did not play
		return move[0], int(0), [], argsPlayed, previousTurnScore, agentsInference
	elif(move.__len__() == 3): # if the agent played one argument
		newScore = getScore(move[2])
		if(newScore < previousTurnScore): # if the score got closer to zero
			if(((previousTurnScore + newScore)/2.0) < agentsInference[move[0]][1]):
				agentsInference[move[0]][1] = ((previousTurnScore + newScore)/2.0)
		else: # if the score got closer to one
			if(((previousTurnScore + newScore)/2.0) > agentsInference[move[0]][0]): # if it gives new information about the personal score of the agent
				agentsInference[move[0]][0] = ((previousTurnScore + newScore)/2.0)
		return move[0], int(1), [move[1]], argsPlayed+[argToId[move[1]]], newScore, agentsInference
	elif(move.__len__() == 4): # if the agent played two arguments
		newScore = getScore(move[3])
		if(newScore < previousTurnScore):
			if(((previousTurnScore + newScore)/2.0) < agentsInference[move[0]][1]):
				agentsInference[move[0]][1] = ((previousTurnScore + newScore)/2.0)
		else:
			if(((previousTurnScore + newScore)/2.0) > agentsInference[move[0]][0]):
				agentsInference[move[0]][0] = ((previousTurnScore + newScore)/2.0)
		return move[0], int(1), [move[1]]+[move[2]], argsPlayed+[argToId[move[1]]]+[argToId[move[2]]], newScore, agentsInference

# computes the negative inference
def negInference(turnNotPlayed, move, game_att, agentsInference):
	# print('NEGINF1')
	# print(move)
	couldHave = False
	if(move.__len__() == 3): # if the agent played one argument
		# i = 0
		# print('NEGINF3')
			# if(att == 1):
		for turn in turnNotPlayed: # goes through the turns during which the agent did not play
			print(f'{turn} == {move[0]} ?')
			if(turn[0] == move[0]): # if it was the agent's turn to play
				for att in turn[1]: #game_att[argToId[move[1]]]:
				# print(f'NEGINF, turn : {turn}, {att}')
					print(att)
					if(argToId[move[1]] in game_att[att]): # agent could have played
						couldHave = True
						temp = copy.deepcopy(turn[1])
						temp[argToId[move[1]]] = move[2][argToId[move[1]]]
						newScore = getScore(temp)
						if(newScore < turn[2]): # if the score would have gotten closer to zero
							print('NEGINFBS')
							if(((turn[2] + newScore)/2.0) > agentsInference[move[0]][2]):
								agentsInference[move[0]][2] = ((turn[2] + newScore)/2.0)
						else: # closer to one
							print('NEGINFBI')
							if(((turn[2] + newScore)/2.0) < agentsInference[move[0]][3]):
								agentsInference[move[0]][3] = ((turn[2] + newScore)/2.0)
			# i += 1
	elif(move.__len__() == 4): # if the agent played two arguments
		# i = 0
		# print('NEGINF4')
			# if(att == 1):
		for turn in turnNotPlayed:
			print(f'{turn} == {move[0]} ?')
			if(turn[0] == move[0]):
				# print(f'NEGINF, turn : {turn}, {att}')
				for att in turn[1]: #game_att[argToId[move[1]]]:
					if(argToId[move[1]] in game_att[att]): # agent could have played
						couldHave = True
						temp = copy.deepcopy(turn[1])
						temp[argToId[move[1]]] = move[3][argToId[move[1]]]
						temp[argToId[move[2]]] = move[3][argToId[move[2]]]
						newScore = getScore(temp)
						if(newScore < turn[2]):
							print('NEGINF')
							if(((turn[2] + newScore)/2.0) > agentsInference[move[0]][2]):
								agentsInference[move[0]][2] = ((turn[2] + newScore)/2.0)
						else:
							print('NEGINF')
							if(((turn[2] + newScore)/2.0) < agentsInference[move[0]][3]):
								agentsInference[move[0]][3] = ((turn[2] + newScore)/2.0)
			# i += 1
	return agentsInference,couldHave

# this function process the game history to compute the inferences
def gameScoreInference(moves, nbAgent, game_att):
	score = 1
	agentsInference = []
	turnNotPlayed = []
	inferenceHistory = []
	i = 0
	args = [0]
	for a in range(nbAgent): # init the inferred intervals
		agentsInference += [[0,1,0,1]] # positive inference lower and upper bounds and negative inference lower and upper bounds
		inferenceHistory += [[[0,1,0,1]]]
	# print(f'moves : {moves}')
	for move in moves: # goes through the game history
		couldHave = False
		print(f'move : {move}')
		ag, hasPlayed, played, args, score, agentsInference = turnScoreInference(move, score, args, agentsInference) # calls positive inference
		if(hasPlayed == 0): # if the agent did not play
			turnNotPlayed += [[ag,move[1],score]]
			print(f'Agent {ag} did not play, so we save the game : {[ag,move[1],score]}')# : {turnNotPlayed}')
		else: # if the agent played
			print(f'Agent {ag} did play ',end='')#{played} : {agentsInference}')
			print("{",end='')
			j = 0
			for item in played:
				if(j==0):
					print(f'{item}',end='')
				else:
					print(f', {item}',end='')
				j += 1
			print("} :")
			print(f'\tAgent\'s inference : {agentsInference[ag]}')
			agentsInference, couldHave = negInference(turnNotPlayed, move, game_att, agentsInference) # calls negative inference
			# inferenceHistory[ag].append([agentsInference[ag][0], agentsInference[ag][1], agentsInference[ag][2], agentsInference[ag][3]])
			print(f'\tAgent\'s inference : {agentsInference[ag]}, {couldHave}')
			if(couldHave == True): # if the agent could have make this move before now
				print(f'Agent {ag} could have played ',end='')#{played} : {agentsInference}')
				print("{",end='')
				j = 0
				for item in played:
					if(j==0):
						print(f'{item}',end='')
					else:
						print(f', {item}',end='')
					j += 1
				print("} earlier :")
				print(f'\tAgent\'s inference : {agentsInference[ag]}')
		inferenceHistory[ag].append([agentsInference[ag][0], agentsInference[ag][1], agentsInference[ag][2], agentsInference[ag][3]])
	print()
	return turnNotPlayed, agentsInference, inferenceHistory

# never called (attempt to improve the inference)
def gameScoreInference2(moves, nbAgent, game_att):
	agentsInference = []
	inferenceHistory = []
	args = [0]
	for a in range(nbAgent):
		agentsInference += [[0,1,0,1]]
		inferenceHistory += [[[0,1,0,1]]]

	for ag in range(nb_agents):
		ag_move = []
		for move in moves:
			if(move[0] == ag):
				if(move.__len__() == 3):
					temp = copy.deppcopy(move[2])
					temp = temp.pop(argToId[move[1]])
					ag_move.append(temp)
				if(move.__len__() == 4):
					temp = copy.deepcopy(move[3])
					temp = temp.pop(argToId[move[1]])
					temp = temp.pop(argToId[move[2]])
					ag_move.append(temp)
		i = 0
		for move in moves:
			if(move[0] == ag):
				if(move.__len__() == 3):
					for j in range(i):
						for arg in ag_move[j].keys():
							if(arg in att[argToId[move[1]]]):
								pass # move[1] aurait pu etre played
				if(move.__len__() == 4):
					pass
			i += 1

	return agentsInference, inferenceHistory

# this function runs the protocol
def protocol(agentsOrder, ag_score, agentAF, exception = []):
	# nbArgPlayed = 0
	gameArgs = [int(0)]
	done = False
	argsImpact = {}
	game = []
	game_att = {}
	game_att[0] = []
	# each agent tries every arg not in it yet and plays the best one
	while(not done):
		done = True
		for i in agentsOrder: # for each agent
			game_score = getScore(game_att) # get the game score
			minDiff = abs(ag_score[i] - game_score) # calculate the difference between their own score and the game score
			min_index = -1 # for now no arg is played
			multipleArgs = False
			j = 0
			for arg in agentAF[i]: # for each arg of the agent
				if((arg not in gameArgs) and (arg not in exception)): # if the arg has not been played
					temp = copy.deepcopy(game_att)
					temp[arg] = []
					for k in temp:
						for l in temp:
							if((l in attaquants[k]) and (l not in temp[k])):
								temp[k].append(l)
					new_score = getScore(temp) # score if arg is added
					# print(f'arg : {arg}, new_score : {new_score}')
					if(abs(ag_score[i] - new_score) < minDiff): # if it brings the game score closer to own score
						min_index = j # holds the arg that brings the score closest to own score
						minDiff = abs(ag_score[i] - new_score) # update the score difference
						best_score = new_score
						done = False # an arg is played so the game is not done
						multipleArgs = False
					else:
						for item in attaquants[arg]:
							if((item in agentAF[i]) and (item not in gameArgs) and (item not in exception)):
								temp[item] = []
								for k in temp:
									for l in temp:
										if((l in attaquants[k]) and (l not in temp[k])):
											temp[k].append(l)
								new_score = getScore(temp) # score if arg is added
								# print(f'item : {item}, new_score : {new_score}')
								if(abs(ag_score[i] - new_score) < minDiff): # if it brings the game score closer to own score
									min_index = j # holds the arg that brings the score closest to own score
									minDiff = abs(ag_score[i] - new_score) # update the score difference
									best_score = new_score
									done = False # an arg is played so the game is not done
									multipleArgs = [item]
				j += 1 # update index for next loop
			if(min_index == -1):
				print(f'Agent {i} doesn\'t play this round')
				game += [[int(i), copy.deepcopy(game_att)]]
			elif(multipleArgs == False): # if the agent plays one argument
				# print([key for key in agentAF[i].keys()][min_index])
				print(f'Agent {i} plays argument {idToArg[[key for key in agentAF[i].keys()][min_index]]}')
				# add the argument to the debate graph
				game_att[[key for key in agentAF[i].keys()][min_index]] = []
				for k in game_att:
					for l in game_att:
						if((l in attaquants[k]) and (l not in game_att[k])):
							game_att[k].append(l)
				# add the play to the game history
				game += [[int(i), idToArg[[key for key in agentAF[i].keys()][min_index]], copy.deepcopy(game_att)]]
				# argsPlayedByAgent[int(i)].append(int(agentsArgs[i][min_index]))
				argsImpact[[key for key in agentAF[i].keys()][min_index]] = best_score - game_score # game_score - ag_score[i] + minDiff
				gameArgs.append(int([key for key in agentAF[i].keys()][min_index]))
			else: # if the agent played two arguments
				print(f'Agent {i} plays argument {idToArg[[key for key in agentAF[i].keys()][min_index]]} and {idToArg[multipleArgs[0]]}')
				game_att[[key for key in agentAF[i].keys()][min_index]] = []
				game_att[multipleArgs[0]] = []
				for k in game_att:
					for l in game_att:
						if((l in attaquants[k]) and (l not in game_att[k])):
							game_att[k].append(l)
				game += [[int(i), idToArg[[key for key in agentAF[i].keys()][min_index]], idToArg[multipleArgs[0]], copy.deepcopy(game_att)]]
				# argsPlayedByAgent[int(i)].append(int(agentsArgs[i][min_index]))
				# argsPlayedByAgent[int(i)].append(int(multipleArgs[0]))
				argsImpact[[key for key in agentAF[i].keys()][min_index]] = (best_score - game_score)/2 # game_score - ag_score[i] + minDiff
				gameArgs.append(int([key for key in agentAF[i].keys()][min_index]))
				argsImpact[multipleArgs[0]] = (best_score - game_score)/2 # game_score - ag_score[i] + minDiff
				gameArgs.append(int(multipleArgs[0]))
	print(f'End of the protocol because no agent played during the round')
	print("\n-------------------------------------------------------------------")
	print()
	return game, gameArgs, game_att, argsImpact

argDen = random.randint(4,8)
argDensity = float(argDen/10.0)
nb_agents = random.randint(2,4)
argToId = {}
idToArg = {}
attaquants = {}
att = {}
universeGraph = []
agentAF = []
size_AF = 0
ag_score = []

path = ''
# finds the generated apx file
for file in os.listdir(sys.argv[1]):
	if(re.match("debate_graph_\S+", file)):
		path = sys.argv[1]+file

fileExists = os.path.exists(path)
if(fileExists == False):
	raise Exception("File not Found")
with open(path) as file_object:
	line = file_object.readline()
	while line:
		values = re.split("\\(|\\)|,",line)
		if(line.startswith('arg')): # new argument
			argToId[values[1]] = size_AF
			idToArg[size_AF] = values[1]
			attaquants[size_AF] = [] # attackers dictionnary
			att[size_AF] = [] # attacked dictionnary
			size_AF += 1
		elif((line.startswith('att')) and (values[1] in argToId) and (values[2] in argToId)): # new attack
			attaquants[argToId[values[2]]].append(argToId[values[1]])
			att[argToId[values[1]]].append(argToId[values[2]])
		else:
			raise Exception("Error in File")
		line = file_object.readline()

# creation of the universe graph
for item in range(size_AF):
	universeGraph.append([])
	for j in range(size_AF):
		if(j in att[item]):
			universeGraph[item].append(int(1))
		else:
			universeGraph[item].append(int(0))

# creation of the agent's knowledge base
for ag in range(nb_agents):
	agentAF.append({})
	for i in range(size_AF):
		if(i == 0): # the issue is always part of the knowledge base
			agentAF[ag][i] = []
		elif(random.random() <= argDensity): # each argument has a probability to be part of the knowledge base
			agentAF[ag][i] = []
			#here to get nb args
	if(not attackTarget(agentAF[ag])): # verify that at least one argument attacks the issue
		agentAF[ag] = {}
		while(not attackTarget(agentAF[ag])):
			for i in range(size_AF):
				if(i == 0):
					agentAF[ag][i] = []
				elif(random.random() <= argDensity):
					agentAF[ag][i] = []
	for i in agentAF[ag]:
		for j in agentAF[ag]:
			if(j in attaquants[i]):
				agentAF[ag][i].append(j)

# allows to write the useful information in a file
f = open(sys.argv[1]+'data'+sys.argv[2]+'.csv', 'w', newline='')
f1 = open(sys.argv[1]+'bench'+sys.argv[2]+'.csv', 'w', newline='')
writer = csv.writer(f)
w = csv.writer(f1)
temp = [nb_agents, size_AF]
writer.writerow(temp)
w.writerow([size_AF])
w.writerow([nb_agents])
writer.writerow(argToId.keys())
writer.writerows(universeGraph)
for af in agentAF:
	writer.writerow(af.keys())
	temp = [getScore(af)]
	writer.writerow(temp)
	w.writerow(temp)
	w.writerow([af.__len__()])

agOrder = []
ag_score = []
for i in range(nb_agents):
	agOrder.append(int(i))
	ag_score.append(getScore(agentAF[i]))

agOrder = itertools.permutations(agOrder, nb_agents) # get every possible order

# use to write the logs
print(f'There are {nb_agents} agents playing.')
print()
print(f'With an argument density of {argDensity}')
print()
print(f'The agents have the following knowledge base : ')
k = 0
for ag in agentAF:
	print(f'Agent {k} knows the argument(s) :\n\t\t',end='')
	j = 0
	for cle, value in ag.items():
		if(j == 0):
			print("{",end='')
		else:
			print(", ",end='')
		print(f'{idToArg[cle]}',end='') #: [', end='')
		j += 1
	print("}\n\tand the relations :\n\t\t",end='')
	i = 0
	print("{", end='')
	for cle, value in ag.items():
		for val in value:
			if(i != 0):
				print(f', ', end='')
			print(f'({val},{cle})',end='')
			i += 1
	print("}",end='')
	print(f'\n\twith a personal score of {getScore(ag)}\n')
	k += 1

for agentsOrder in agOrder: # we run the protocol for every order possible
	print()
	print("-------------------------------------------------------------------")
	print(f'\t\t\tAGENTS ORDER : ',end='')
	i = 0
	for ag in agentsOrder:
		if(i == 0):
			print(f'{ag}',end='')
			i+=1
		else:
			print(f', {ag}',end='')
	print()
	print("-------------------------------------------------------------------")
	print()

	game, gameArgs, game_att, argsImpact = protocol(agentsOrder, ag_score, agentAF)

	print(f'The final graph :\n\t',end='')
	print(f'the argument(s) played are :\n\t\t',end='')
	j = 0
	for cle, value in game_att.items():
		if(j == 0):
			print("{",end='')
		else:
			print(", ",end='')
		print(f'{idToArg[cle]}',end='') #: [', end='')
		j += 1
	print("}\n\tand the relations :\n\t\t",end='')
	i = 0
	print("{", end='')
	for cle, value in game_att.items():
		for val in value:
			if(i != 0):
				print(f', ', end='')
			print(f'({val},{cle})',end='')
			i += 1
	print("}")
	k += 1
	print()
	print(f'\twith a score of {getScore(game_att)}')
	print()
	print(f'The immediate impacts of the arguments when played are :')
	for key, value in argsImpact.items():
		print(f'\tthe impact of the argument {idToArg[key]} equals {value}')
	print()

	print("---------------impact of args based on final outcome---------------\n")

	argsImpactOnFinalOutcome = {}

	for item in gameArgs: # for every argument in the final debate graph
		if(item != 0):
			temp1 = copy.deepcopy(game_att)
			for arg in attaquants[item]:
				if arg in temp1:
					temp1.pop(arg) # remove the direct attackers of item
			temp2 = copy.deepcopy(game_att)
			temp2.pop(item) # remove item
			a = getScore(temp1)
			b = getScore(temp2)
			argsImpactOnFinalOutcome[item] = a - b
		else:
			argsImpactOnFinalOutcome[item] = 0.0

	print(f'The arguments impact based on the final outcome :')
	for key, value in argsImpactOnFinalOutcome.items():
		print(f'\tthe impact of the argument {idToArg[key]} equals {value}')

	print("\n-------------impact of args based on omniscient protocol-------------\n")

	argsImpactOnUniverseProtocol = {}

	gameScore = getScore(game_att)
	for item in gameArgs:
		if((item != 0)):
			print(f'Protocol without the argument {idToArg[item]}\n')
			game2, gameArgs2, game_att2, argsImpact2 = protocol(agentsOrder, ag_score, agentAF, [item])
			newScore = getScore(game_att2)
			argsImpactOnUniverseProtocol[item] = gameScore - newScore
		else:
			argsImpactOnUniverseProtocol[item] = 0.0

	print(f'The arguments impact based on the omniscient protocol :')
	for key, value in argsImpactOnUniverseProtocol.items():
		print(f'\tthe impact of the argument {idToArg[key]} equals {value}')
	print()

	print("--------------impact of args based on observable protocol-------------\n")

	var1, var2, inferenceHistory = gameScoreInference(game, nb_agents, game_att)

	print(f'The saved steps of the game are :')
	for turn in var1:
		print(f'\t{turn} :\n\tAgent {turn[0]}\'s turn, ',end='')
		i = 0
		for item in turn[1]:
			if(i == 0):
				print("{",end='')
				print(f'{item}',end='')
			else:
				print(f', {item}',end='')
			i += 1
		print("}",end='')
		print(f', with a score of {turn[2]}\n')
	print(f'The infered score intervals of the agents are :')
	i = 0
	for item in var2:
		print(f'for agent {i} : [{max(item[0], item[2])}, {min(item[1], item[3])}]')
		i += 1
		print(f'item : {item}')

	argsImpactOnPartialProtocolH1 = {}
	argsImpactOnPartialProtocolH2 = {}
	gameScore = getScore(game_att)
	ag_score_infered = scoreFromInference(var2)

	i = 0
	print(f'\nThe infered score :')
	for item in ag_score_infered:
		print(f'for agent {i} : {item}')
		i += 1

	i = 0
	print(f'\nThe only playable arguments are :')
	for item in gameArgs:
		if(i == 0):
			print("\t{",end='')
			print(f'{item}',end='')
		else:
			print(f', {item}',end='')
		i += 1
	print("}")
	print()
	print("-------------------------------------------------------------------")
	print()

	tempAF2 = []
	for i in range(nb_agents):
		tempAF2.append({})
		tempAF2[i][0] = []
	for move in game:
		if(move.__len__() == 3):
			tempAF2[move[0]][argToId[move[1]]] = []
		elif(move.__len__() == 4):
			tempAF2[move[0]][argToId[move[1]]] = []
			tempAF2[move[0]][argToId[move[2]]] = []
	for ag in tempAF2:
		for key, values in attaquants.items():
			if(key in ag):
				for arg in values:
					if(arg in ag):
						ag[key].append(arg)

	poped = []
	for af in agentAF:
		for arg,value in af.items():
			if(arg not in gameArgs) and (arg not in poped):
				poped.append(arg)

	tempAF = copy.deepcopy(agentAF)
	for ag in tempAF:
		if(item in ag):
			ag.pop(item)
		for arg in poped:
			if(arg in ag):
				ag.pop(arg)

	for item in game_att:
		if(item != 0):
			print(f'Protocol without the argument {idToArg[item]} under hypothesis 1\n')
			game2, gameArgs2, game_att2, argsImpact2 = protocol(agentsOrder, ag_score_infered, tempAF, exception=[item])
			newScore = getScore(game_att2)
			argsImpactOnPartialProtocolH1[item] = gameScore - newScore
			print(f'Protocol without the argument {idToArg[item]} under hypothesis 2\n')
			game3, gameArgs3, game_att3, argsImpact3 = protocol(agentsOrder, ag_score_infered, tempAF2, exception=[item])
			newScore2 = getScore(game_att3)
			argsImpactOnPartialProtocolH2[item] = gameScore - newScore2
		else:
			argsImpactOnPartialProtocolH1[item] = 0.0
			argsImpactOnPartialProtocolH2[item] = 0.0

	print(f'The arguments impact based on the observable protocol with hypothesis 1 :')
	for key, value in argsImpactOnPartialProtocolH1.items():
		print(f'\tthe impact of the argument {idToArg[key]} equals {value}')
	print()

	print(f'The arguments impact based on the observable protocol with hypothesis 2 :')
	for key, value in argsImpactOnPartialProtocolH2.items():
		print(f'\tthe impact of the argument {idToArg[key]} equals {value}')
	print()

	writer.writerow([])
	writer.writerow(agentsOrder)
	writer.writerow(gameArgs)
	temp = [game.__len__()]
	writer.writerow(temp)
	w.writerow(temp)
	for move in game:
		writer.writerow(move)
	i = 0
	for ag in inferenceHistory:
		writer.writerow(ag)
		w.writerow(ag)
		writer.writerow([ag_score_infered[i]])
		w.writerow([ag_score_infered[i]])
		i += 1
	argsPlayed = []
	for item in range(nb_agents):
		argsPlayed.append([])
	for move in game:
		if(move.__len__() == 3):
			argsPlayed[move[0]].append(argToId[move[1]])
		elif(move.__len__() == 4):
			argsPlayed[move[0]].append(argToId[move[1]])
			argsPlayed[move[0]].append(argToId[move[2]])

	writer.writerow(argsImpactOnFinalOutcome.values())
	writer.writerow(argsImpactOnUniverseProtocol.values())
	writer.writerow(argsImpactOnPartialProtocolH1.values())
	writer.writerow(argsImpactOnPartialProtocolH2.values())
	w.writerow(argsImpactOnFinalOutcome.values())
	w.writerow(argsImpactOnUniverseProtocol.values())
	w.writerow(argsImpactOnPartialProtocolH1.values())
	w.writerow(argsImpactOnPartialProtocolH2.values())
	w.writerow(argsImpactOnFinalOutcome.keys())
	for item in argsPlayed:
		w.writerow(item)


import sqlite3 as sql
from typing import List

from pydojoctl.models.dojo import (
    Evento,
    EventoAtuacao,
    EventoConfiguracao,
    Participante,
)

def conectar(database='codedojo.db') -> sql.Connection:
    try:
        con = sql.connect(database)
        con.row_factory = sql.Row
        con.execute('PRAGMA foreign_keys=ON')
        return con
    except sql.DatabaseError as erro:
        print(erro)
        raise

def criar_base(connection=None):
    try:
        with (connection if connection else conectar()) as con:
            con.execute(
                """CREATE TABLE IF NOT EXISTS evento (
                  id INTEGER PRIMARY KEY AUTOINCREMENT,
                  nome text NOT NULL,
                  data text NOT NULL,
                  duracao_prevista integer,
                  duracao_real integer,
                  ativo integer
                )
            """
            )
    except sql.DatabaseError as erro:
        print(erro)
        raise

    # Participante
    try:
        with (connection if connection else conectar()) as con:
            con.execute(
                """CREATE TABLE IF NOT EXISTS participante (
                  id INTEGER PRIMARY KEY AUTOINCREMENT,
                  nome text NOT NULL,
                  email text NOT NULL,
                  presente integer
                )
            """
            )
    except sql.DatabaseError as erro:
        print(erro)
        raise

    # Configuração do evento
    try:
        with (connection if connection else conectar()) as con:
            con.execute(
                """CREATE TABLE IF NOT EXISTS evento_config (
                  id INTEGER PRIMARY KEY AUTOINCREMENT,
                  evento integer NOT NULL,
                  tempo_piloto integer NOT NULL,
                  tempo_audiencia integer NOT NULL,
                  FOREIGN KEY(evento) REFERENCES evento(id)
                )
            """
            )
    except sql.DatabaseError as erro:
        print(erro)
        raise

    # Atuação no evento
    try:
        with (connection if connection else conectar()) as con:
            con.execute(
                """CREATE TABLE IF NOT EXISTS evento_atuacao (
                  id INTEGER PRIMARY KEY AUTOINCREMENT,
                  evento integer NOT NULL,
                  participante integer NOT NULL,
                  ordem_sorteio integer,
                  FOREIGN KEY(evento) REFERENCES evento(id),
                  FOREIGN KEY(participante) REFERENCES participante(id)
                )
            """
            )
    except sql.DatabaseError as erro:
        print(erro)
        raise

def inserir_evento(evento: Evento, connection=None):
    try:
        with (connection if connection else conectar()) as con:
            return con.execute(
                """INSERT into evento
                (nome, data, duracao_prevista, duracao_real, ativo)
                VALUES
                (:nome, :data, :duracao_prevista, :duracao_real, :ativo)
            """,
                (
                    evento.nome,
                    evento.data,
                    evento.duracao_prevista,
                    evento.duracao_real,
                    evento.ativo,
                ),
            )
    except sql.DatabaseError as erro:
        print(erro)
        raise

def listar_eventos(connection=None) -> List[Evento]:
    eventos = []
    try:
        with (connection if connection else conectar()) as con:
            result = con.execute('SELECT * FROM evento')
            rows = result.fetchall()
            for row in rows:
                eventos.append(Evento(**row))
    except sql.DatabaseError as erro:
        print(erro)
        raise
    return eventos

def buscar_evento(evento_id, connection=None) -> Evento:
    try:
        with (connection if connection else conectar()) as con:
            result = con.execute(
                'SELECT * FROM evento where id = :evento_id',
                {'evento_id': evento_id},
            )
            row = result.fetchone()
            return Evento(**row)
    except sql.DatabaseError as erro:
        print(erro)
        raise

def inserir_participante(participante: Participante, connection=None):
    try:
        with (connection if connection else conectar()) as con:
            return con.execute(
                """INSERT into participante
                (nome, email, presente)
                VALUES
                (:nome, :email, :presente)
            """,
                (participante.nome, participante.email, participante.presente),
            )
    except sql.DatabaseError as erro:
        print(erro)
        raise

def inserir_configuracao(evento_config: EventoConfiguracao, connection=None):
    try:
        with (connection if connection else conectar()) as con:
            return con.execute(
                """INSERT into evento_config
                (evento, tempo_piloto, tempo_audiencia)
                VALUES
                (evento, tempo_piloto, tempo_audiencia)
            """,
                (
                    evento_config.evento.id,
                    evento_config.tempo_piloto,
                    evento_config.tempo_audiencia,
                ),
            )
    except sql.DatabaseError as erro:
        print(erro)
        raise

def inserir_atuacao(evento_atuacao: EventoAtuacao, connection=None):
    try:
        with (connection if connection else conectar()) as con:
            return con.execute(
                """INSERT into evento_atuacao
                (evento, participante, ordem_sorteio)
                VALUES
                (:evento, :participante, :ordem_sorteio)
            """,
                (
                    evento_atuacao.evento.id,
                    evento_atuacao.participante.id,
                    evento_atuacao.ordem_sorteio,
                ),
            )
    except sql.DatabaseError as erro:
        print(erro)
        raise


# 121. 买卖股票的最佳时机
# 给定一个数组，它的第i 个元素是一支给定股票第 i 天的价格。
# 如果你最多只允许完成一笔交易（即买入和卖出一支股票一次），设计一个算法来计算你所能获取的最大利润。
# 注意：你不能在买入股票前卖出股票。

def maxProfit(prices):
    buy_in = min(prices)
    ind = prices.index(buy_in)
    if prices[ind + 1:]:
        return max(prices[ind + 1:]) - buy_in
    else:
        return 0

prices = [7, 1, 5, 3, 6, 4]
maxProfit(prices)
prices = [7, 6, 4, 3, 1]
maxProfit(prices)

121. 买卖股票的最佳时机.py


from flask import *
from configparser import ConfigParser
from tkinter import messagebox
import requests

api_url = 'http://api.openweathermap.org/data/2.5/weather?q={}&appid={}'

app = Flask(__name__)

config_file = 'config.ini'
config = ConfigParser()
config.read(config_file)
api_key = config['api_key']['key']

def get_weather(city):
    result = requests.get(api_url.format(city, api_key))
    if result:
        json = result.json()
        city = json['name']
        country = json['sys']['country']
        temp_kelvin = json['main']['temp']
        temp_celsius = round(temp_kelvin - 273.15, 2)
        temp_ferenheit = round(temp_celsius*9/5+32, 2)
        icon = "icons/"+(json['weather'][0]['icon'])+".png"
        weather = json['weather'][0]['main']
        final = (city, country, temp_celsius, temp_ferenheit, icon, weather)
        return final
    else:
        return None

@app.route('/', methods=["POST", "GET"])
def Weather_app():
    if request.method == "POST":
        city_name = request.form["city"]
        return redirect(url_for("city_weather", city=city_name))
    else:
        return render_template('index.html')

@app.route('/<city>')
def city_weather(city):
    city_info = get_weather(city)
    if city_info:
        return render_template('weatherOfCity.html', city_data = city_info)
    else:
        messagebox.showerror('[ERROR]',"Cannot Find City {}".format(city))

if __name__ == '__main__':
    app.run()


import sys

from bs4 import BeautifulSoup as bs4
from django.conf import settings
from django.utils.module_loading import import_string

from wagtail_toolbox.wordpress.models.config import StreamBlockSignatureBlocks

class WagtailBlockBuilder:
    def __init__(self, fallback_block_name=None, rich_text_block_name=None):
        if fallback_block_name is None and not hasattr(
            settings, "WPI_FALLBACK_BLOCK_NAME"
        ):
            self.fallback_block = (
                "wagtail_toolbox.wordpress.wagtail_builder_utils.raw_html_block_builder"
            )
        else:
            self.fallback_block = settings.WPI_FALLBACK_BLOCK_NAME

        if rich_text_block_name is None and not hasattr(
            settings, "WPI_RICHTEXT_BLOCK_NAME"
        ):
            self.rich_text_block = (
                "wagtail_toolbox.wordpress.wagtail_builder_utils.richtext_block_builder"
            )
        else:
            self.rich_text_block = settings.WPI_RICHTEXT_BLOCK_NAME

        self.stream_blocks = []
        self.stream_block_signatures = (
            StreamBlockSignatureBlocks.objects.all().values_list(
                "signature", "block_name", "block_kwargs"
            )
        )

    @staticmethod
    def make_tag_signature(element):
        """Make a signature for a BS4 tag and its children."""
        signature = f"{element.name}:"
        current = element.find()
        while current:
            signature += f"{current.name}:"
            current = current.find() if current.find() else None
        return signature

    def build(self, html):
        soup = bs4(html, "html.parser")
        block_stack = []

        for element in soup.findChildren(recursive=False):
            signature = self.make_tag_signature(element)

            try:
                stream_block_config = self.stream_block_signatures.get(
                    signature=signature
                )
            except StreamBlockSignatureBlocks.DoesNotExist:
                sys.stderr.write(f"Signature not found: {signature}\n")
                continue

            is_richtext = stream_block_config[1] == self.rich_text_block

            block_builder = import_string(stream_block_config[1])
            block_builder_kwargs = stream_block_config[2]
            block = block_builder(
                str(element), block_builder_kwargs=block_builder_kwargs
            )

            block_stack.append(block)  # add everything to the block stack

            # now fix up rich_text blocks as they should be one block
            # and not consecutive blocks
            if is_richtext and len(block_stack) > 1:
                # are the last 2 blocks on the stack a type="rich_text" block?
                # we know the last one is because of is_richtext
                if block_stack[-2]["type"] == "rich_text":
                    # pop the last block and get it's value
                    last_block_value = block_stack.pop()["value"]
                    # add the last_block_value to the last_block
                    block_stack[-1]["value"] += last_block_value

        return block_stack

make_tag_signature = WagtailBlockBuilder.make_tag_signature  # for convenience


# This Source Code Form is subject to the terms of the Mozilla Public
# License, v. 2.0. If a copy of the MPL was not distributed with this
# file, You can obtain one at http://mozilla.org/MPL/2.0/.

import argparse
import logging
import os
import sys
from collections import namedtuple

from wptrunner.wptmanifest.backends import base
from wptrunner.wptmanifest.node import KeyValueNode
from wptrunner.wptmanifest.serializer import serialize

here = os.path.dirname(__file__)
logger = logging.getLogger(__name__)

class Compiler(base.Compiler):
    def visit_KeyValueNode(self, node):
        key_name = node.data
        values = []
        for child in node.children:
            values.append(self.visit(child))

        self.output_node.set(key_name, values)

    def visit_ConditionalNode(self, node):
        assert len(node.children) == 2
        # For conditional nodes, just return the subtree
        return serialize(node.children[0]), self.visit(node.children[1])

    def visit_UnaryExpressionNode(self, node):
        raise NotImplementedError

    def visit_BinaryExpressionNode(self, node):
        raise NotImplementedError

    def visit_UnaryOperatorNode(self, node):
        raise NotImplementedError

    def visit_BinaryOperatorNode(self, node):
        raise NotImplementedError

class ExpectedManifest(base.ManifestItem):
    def __init__(self, node):
        """Object representing all the tests in a particular manifest"""
        base.ManifestItem.__init__(self, node)
        self.child_map = {}

    def append(self, child):
        """Add a test to the manifest"""
        base.ManifestItem.append(self, child)
        self.child_map[child.name] = child

    def insert(self, child):
        self.append(child)
        self.node.append(child.node)

    def delete(self, child):
        del self.child_map[child.name]
        child.node.remove()
        child.remove()

class TestManifestItem(ExpectedManifest):
    def set_expected(self, other_manifest):
        for item in self.node.children:
            if isinstance(item, KeyValueNode) and item.data == "expected":
                assert "expected" in self._data
                item.remove()
                del self._data["expected"]
                break

        for item in other_manifest.node.children:
            if isinstance(item, KeyValueNode) and item.data == "expected":
                assert "expected" in other_manifest._data
                item.remove()
                self.node.children.insert(0, item)
                self._data["expected"] = other_manifest._data.pop("expected")
                break

def data_cls_getter(output_node, visited_node):
    # visited_node is intentionally unused
    if output_node is None:
        return ExpectedManifest
    if isinstance(output_node, ExpectedManifest):
        return TestManifestItem
    raise ValueError

def compile(stream, data_cls_getter=None, **kwargs):
    return base.compile(Compiler, stream, data_cls_getter=data_cls_getter, **kwargs)

def get_manifest(manifest_path):
    """Get the ExpectedManifest for a particular manifest path"""
    try:
        with open(manifest_path, "rb") as f:
            try:
                return compile(f, data_cls_getter=data_cls_getter)
            except Exception:
                f.seek(0)
                sys.stderr.write("Error parsing:\n%s" % f.read().decode("utf8"))
                raise
    except IOError:
        return None

def indent(str_data, indent=2):
    rv = []
    for line in str_data.splitlines():
        rv.append("%s%s" % (" " * indent, line))
    return "\n".join(rv)

class Differences(object):
    def __init__(self):
        self.added = []
        self.deleted = []
        self.modified = []

    def __nonzero__(self):
        return bool(self.added or self.deleted or self.modified)

    def __str__(self):
        modified = []
        for item in self.modified:
            if isinstance(item, TestModified):
                modified.append(
                    "  %s\n    %s\n%s" % (item[0], item[1], indent(str(item[2]), 4))
                )
            else:
                assert isinstance(item, ExpectedModified)
                modified.append("  %s\n    %s %s" % item)
        return "Added:\n%s\nDeleted:\n%s\nModified:\n%s\n" % (
            "\n".join("  %s:\n    %s" % item for item in self.added),
            "\n".join("  %s" % item for item in self.deleted),
            "\n".join(modified),
        )

TestModified = namedtuple("TestModified", ["test", "test_manifest", "differences"])

ExpectedModified = namedtuple(
    "ExpectedModified", ["test", "ancestor_manifest", "new_manifest"]
)

def compare_test(test, ancestor_manifest, new_manifest):
    changes = Differences()

    compare_expected(changes, None, ancestor_manifest, new_manifest)

    for subtest, ancestor_subtest_manifest in ancestor_manifest.child_map.items():
        compare_expected(
            changes,
            subtest,
            ancestor_subtest_manifest,
            new_manifest.child_map.get(subtest),
        )

    for subtest, subtest_manifest in new_manifest.child_map.items():
        if subtest not in ancestor_manifest.child_map:
            changes.added.append((subtest, subtest_manifest))

    return changes

def compare_expected(changes, subtest, ancestor_manifest, new_manifest):
    if not (
        ancestor_manifest and ancestor_manifest.has_key("expected")  # noqa W601
    ) and (
        new_manifest and new_manifest.has_key("expected")  # noqa W601
    ):
        changes.modified.append(
            ExpectedModified(subtest, ancestor_manifest, new_manifest)
        )
    elif (
        ancestor_manifest
        and ancestor_manifest.has_key("expected")  # noqa W601
        and not (new_manifest and new_manifest.has_key("expected"))  # noqa W601
    ):
        changes.deleted.append(subtest)
    elif (
        ancestor_manifest
        and ancestor_manifest.has_key("expected")  # noqa W601
        and new_manifest
        and new_manifest.has_key("expected")  # noqa W601
    ):
        old_expected = ancestor_manifest.get("expected")
        new_expected = new_manifest.get("expected")
        if expected_values_changed(old_expected, new_expected):
            changes.modified.append(
                ExpectedModified(subtest, ancestor_manifest, new_manifest)
            )

def expected_values_changed(old_expected, new_expected):
    if len(old_expected) != len(new_expected):
        return True

    old_dict = {}
    new_dict = {}
    for dest, cond_lines in [(old_dict, old_expected), (new_dict, new_expected)]:
        for cond_line in cond_lines:
            if isinstance(cond_line, tuple):
                condition, value = cond_line
            else:
                condition = None
                value = cond_line
            dest[condition] = value

    return new_dict != old_dict

def record_changes(ancestor_manifest, new_manifest):
    changes = Differences()

    for test, test_manifest in new_manifest.child_map.items():
        if test not in ancestor_manifest.child_map:
            changes.added.append((test, test_manifest))
        else:
            ancestor_test_manifest = ancestor_manifest.child_map[test]
            test_differences = compare_test(test, ancestor_test_manifest, test_manifest)
            if test_differences:
                changes.modified.append(
                    TestModified(test, test_manifest, test_differences)
                )

    for test, test_manifest in ancestor_manifest.child_map.items():
        if test not in new_manifest.child_map:
            changes.deleted.append(test)

    return changes

def apply_changes(current_manifest, changes):
    for test, test_manifest in changes.added:
        if test in current_manifest.child_map:
            current_manifest.delete(current_manifest.child_map[test])
        current_manifest.insert(test_manifest)

    for test in changes.deleted:
        if test in current_manifest.child_map:
            current_manifest.delete(current_manifest.child_map[test])

    for item in changes.modified:
        if isinstance(item, TestModified):
            test, new_manifest, test_changes = item
            if test in current_manifest.child_map:
                apply_changes(current_manifest.child_map[test], test_changes)
            else:
                current_manifest.insert(new_manifest)
        else:
            assert isinstance(item, ExpectedModified)
            subtest, ancestor_manifest, new_manifest = item
            if not subtest:
                current_manifest.set_expected(new_manifest)
            elif subtest in current_manifest.child_map:
                current_manifest.child_map[subtest].set_expected(new_manifest)
            else:
                current_manifest.insert(new_manifest)

def get_parser():
    parser = argparse.ArgumentParser()
    parser.add_argument("ancestor")
    parser.add_argument("current")
    parser.add_argument("new")
    parser.add_argument("dest", nargs="?")
    return parser

def get_parser_mergetool():
    parser = argparse.ArgumentParser()
    parser.add_argument("--no-overwrite", dest="overwrite", action="store_false")
    return parser

def make_changes(ancestor_manifest, current_manifest, new_manifest):
    changes = record_changes(ancestor_manifest, new_manifest)
    apply_changes(current_manifest, changes)

    return serialize(current_manifest.node)

def run(ancestor, current, new, dest):
    ancestor_manifest = get_manifest(ancestor)
    current_manifest = get_manifest(current)
    new_manifest = get_manifest(new)

    updated_current_str = make_changes(
        ancestor_manifest, current_manifest, new_manifest
    )

    if dest != "-":
        with open(dest, "wb") as f:
            f.write(updated_current_str.encode("utf8"))
    else:
        print(updated_current_str)


from subprocess import call
import argparse

parser = argparse.ArgumentParser(description="Create subsamples of datasets.")
parser.add_argument("dataset", help="name of dataset collection XML file")
args = parser.parse_args()

sample_script = "../../data/collections/sample.py"
size_ratios = [.1, .2, .3, .4, .5, .6, .7, .8, .9]
sample_ids = range(5)
for size_ratio in size_ratios:
    for sample_id in sample_ids:
        sample_name = args.dataset.split('.')[0] + "-" + str(int(size_ratio * 100)) + "-" + str(sample_id) + ".xml"
        command = "python " + sample_script + " " + args.dataset + " " + sample_name + " --size_ratio " + str(size_ratio)
        call(command, shell=True)


import random

S = int(1e+6 + 1)
K = 6

def read_graph():
    n_e, n_v = int(input()), 0
    edges = []
    for _ in range(n_e):
        edge = list(map(int, input().split()))
        edges.append(edge)
        n_v = max(n_v, *edge)
    return n_v + 1, edges

def get_edmonds_matrix(n_v, edges):
    matrix = [[0] * n_v for _ in range(n_v)]
    for edge in edges:
        matrix[edge[0]][edge[1]] = random.choice(list(range(S)))
    return matrix

def deternminant(n_v, matrix):
    for i in range(n_v):
        col = [row[i] for row in matrix[i:]]
        if max(col) == 0:
            return 0
        matrix[i], matrix[col.index(max(col)) + i] = matrix[col.index(max(col)) + i], matrix[i]
        for j in range(i + 1, n_v):
            for k in range(i + 1, n_v):
                matrix[j][k] = (matrix[j][k] - matrix[i][k] // max(col) * matrix[j][i]) % S
    return 1

n_v, edges = read_graph()

dets = []
for k in range(K):
    matrix = get_edmonds_matrix(n_v, edges)
    dets.append(deternminant(n_v, matrix))

pm = 'yes' if sum(dets) else 'no'
print(pm)


### Distortion coefficients
import numpy as np

import cv2
from .common import make_gray, apply_pipeline

def get_corners(image, shape, nxy):
    gray = make_gray(image)
    if gray.shape != shape:
        return None

    ret, corners = cv2.findChessboardCorners(gray, nxy)
    if ret:
        return corners

    return None

def get_object_points(nx, ny, count):
    objpoint = np.zeros((nx*ny,3), np.float32)
    objpoint[:,:2] = np.mgrid[0:nx,0:ny].T.reshape(-1,2)
    return [objpoint] * count

### Transform matix

def apply_shape(arr, shape):
    arr[:,0] *= shape[1]
    arr[:,1] *= shape[0]

    return arr.astype(np.float32)

def get_transform_src(shape):
    x1, x2, x3, x4 = 0.1, 0.37, 0.65, 0.95
    y1, y2 = 0.7, 0.95
    return apply_shape(np.array([
        [x1, y2],
        [x2, y1],
        [x3, y1],
        [x4, y2],
    ]), shape)

def get_transform_dst(shape):
    return apply_shape(np.array([
        [0, 1],
        [0, 0],
        [1, 0],
        [1, 1]
    ]), shape)

def get_transform_matrices(shape):
    src = get_transform_src(shape)
    dst = get_transform_dst(shape)
    M = cv2.getPerspectiveTransform(src, dst)
    Minv = cv2.getPerspectiveTransform(dst, src)
    return M, Minv

### CameraCalibrator

class CameraCalibrator:
    def __init__(self, nx, ny, shape=(720, 1280)):
        self.image_points = []
        self.__nxy = (nx, ny)

        self.__M, self.__Minv  = get_transform_matrices(shape)

        self.__shape = shape
        self.__mtx = None
        self.__dist = None

    def calibrate(self, image):
        corners = get_corners(image, self.__shape, self.__nxy)
        if corners is not None:
            self.image_points.append(corners)
            return True
        return False

    def finish_calibrate(self):
        nx, ny = self.__nxy
        object_points = get_object_points(nx, ny, len(self.image_points))
        ret, mtx, dist, _, _ = cv2.calibrateCamera(
            object_points,
            self.image_points,
            self.__shape[::-1],
            None,
            None
        )
        assert(ret)
        self.__mtx = mtx
        self.__dist = dist

    def undistort(self, image):
        return cv2.undistort(image, self.__mtx, self.__dist, None, self.__mtx)

    def transform(self, image):
        shape = [image.shape[1], image.shape[0]]
        return cv2.warpPerspective(image, self.__M, shape)

    def un_transform(self, image):
        shape = [image.shape[1], image.shape[0]]
        return cv2.warpPerspective(image, self.__Minv, shape)

    def process_image(self, image):
        return list(apply_pipeline(image, [
            self.undistort,
            self.transform
        ]))


import cv2
import sqlite3
import numpy as np
from database_ops import *
import requests

faceDetect = cv2.CascadeClassifier("haarcascade_frontalface_alt2.xml")
recognizer = cv2.face.LBPHFaceRecognizer_create()
url = 'http://192.168.43.1:8080/shot.jpg'

recognizer.read('recognizer/training_data.yml')

while True:
    img_resp = requests.get(url)
    img_array = np.array(bytearray(img_resp.content),dtype = np.uint8)
    img = cv2.imdecode(img_array, -1)
    img = cv2.resize(img,(1280,720))
    gray = cv2.cvtColor(img,cv2.COLOR_BGR2GRAY)
    faces = faceDetect.detectMultiScale(gray,scaleFactor=1.5,minNeighbors=5)

    for(x,y,w,h) in faces:
        cv2.rectangle(img,(x,y),(x+w,y+h),(0,0,0),2)
        id,conf = recognizer.predict(gray[y:y+h, x:x+w])
        profile = 0
        if conf >= 45 and conf <= 85:
            profile = get_profile(id)
        if profile != 0:
            cv2.putText(img, profile[1], (x, y-40), 2, 0.8, (255, 255, 255), 1)
            cv2.putText(img, 'Age : ' + str(profile[2]), (x, y-20), 2, 0.8, (255, 255, 255), 1)
            cv2.putText(img, 'Gender : ' + str(profile[3]), (x, y), 2, 0.8, (255, 255, 255), 1)
        else:
            cv2.putText(img, 'Unknown', (x, y), 2, 0.8, (255, 255, 255), 1)

    cv2.imshow("Face_Detection_Window",img)
    if cv2.waitKey(1) == ord('q'):
        break

cv2.destroyAllWindows()


# 논리형 데이터를 사용해서 무한반복을 하거나 멈출 수 있다.

# flag를 이용해보자

flag=True
num=0
sum=0
while flag:
    num+=1
    sum+=num
    print(num, sum)

    if sum >= 1000:
        flag = False #if를 만족한 경우 반복문이 false가 되면서 멈춘다.

#---------------------------------------------------------
 # 예제 환자가 하루 50~100명 올 때 누적 환자 10000명이 넘는 날짜 구하기

import random

sum=0
date=1
flag=True

while flag:
    patientCount = random.randint(50,100)
    sum += patientCount
    date += 1
    print("날짜:{} \t 오늘환자수:{}, \t 누적환자수:{}".format(date, patientCount,sum))
    if sum>= 10000: # 합이 만이 넘을 때 반복문 종료
        flag = False


from django.urls import path
from rest_framework.urlpatterns import format_suffix_patterns
from .views import itemlist,item_detail,bidlist,item_bids

app_name = 'api'

urlpatterns = [
    path('itemlist/',itemlist),
    path('item_detail/<int:pk>/',item_detail),
    path('bidlist/',bidlist),
    path('item_bids/<int:pk>/',item_bids),
    # path('itemlist/',itemlist),

]

urlpatterns = format_suffix_patterns(urlpatterns)


import os
import json
import logging

logger = logging.getLogger(__name__)

def test_post(nc):
    with open('./test/integration/data/employee/data.json') as oj:
        s = oj.read()
        employee = json.loads(s)
    logger.debug('employee = %s', employee)
    res = nc.employees.post(employee)
    logger.debug('res = %s', res)
    assert res['externalId'] == employee['externalId'], 'ID Number does not match'
    assert res['type'] == 'employee', 'Type does not match'


import random

def FireGirl_DS_alg(seedValue, min_val, max_val, roughness=0.5):
    #This function creates a new 129x129 grid of values. It will return a list
    #  containing two elements, the first is a nested list for the timber_value
    #  grid, and the second is a nested list for the fuel_load grid
    #
    #Arguments:
    #seedValue:  is used to ensure replicability. If set to -1, the function
    #              uses system-provided random values instead (system time)
    #min_val:    is the lowest value the ds algorithm will allow in the grid
    #max_val:    is the highest value the ds algorithm will allow in the grid
    #roughness:  is a parameter of the ds algorithm which determines how smooth
    #              or rough the resulting field of values is. Values must fall
    #              between 0 and 1. Values close to 1 will result in rougher
    #              landscapes than values close to 0. The first iteration of the
    #              DS algorithm will allow variation up to half the range between
    #              min_val and max_val. Subsquent iterations will multiply this
    #              range by the roughness value of the previous iteration.

    #Creating the timber_value and fuel_load grids
    timber_val = []
    fuel_load = []
    for i in range(129):
        timber_val.append([])
        fuel_load.append([])
        for j in range(129):
            timber_val[i].append(0)
            fuel_load[i].append(0)

    #setting seed value
    if seedValue == -1:
        #if the seed value was given as -1, that indicates using pseudo-random
        #  system values, and ignoring replicability
        #using random.seed() with no arguements allows python to use its
        #   ordinary system-defined pseudo-random values
        random.seed()
    else:
        #a seed value is specified, so use it. This allows replicability
        random.seed(seedValue)

    # Note to Self: to increment over the NxN grid, increment by x:
    #  9x9     -> 16
    #  17x17   -> 8
    #  33x33   -> 4
    #  65x65   -> 2
    #  129x129 -> 1

    #seeding the initial 9x9 grid with random values between min_val and max_val
    # (by incrementing in 16s, we'll cover 9 values, i.e. the 9x9 sub-grid)
    for i in range(0,129,16):
        for j in range(0,129,16):
            timber_val[i][j] = random.uniform(min_val, max_val)

    #TESTING
    #print("Step 1 results, 0-17")
    #printgrid(timber_val,0,17,0,17)
    #print("Step 1 results, 112-129")
    #printgrid(timber_val,112,129,112,129)

    #starting the DS algorithm with the 17x17 subgrid
    #First, make the diamonds, by inserting new values orthogonally between
    #  the 9x9 grid-point values.  This means that on even-indexed rows we'll
    #  put values in starting at 7 (the 8th value), and incrementing by 16's.
    #  and averaging from the values 8 before, and 8 after on the same row.
    #  On odd-indexed rows, we'll start on index 0, and increment by 16s, and use
    #  average from the values above and below (in the same column).

    val_timb = 0
    val_fuel = 0
    wiggle_range = (0.5 * (max_val - min_val))

    #doing even-indexed rows
    for j in range(0,129,16):
        for i in range(8,129,16):
            #look at the value 8 before, and 8 after, and average them
            val_timb = 0.5 * (timber_val[i-8][j] + timber_val[i+8][j])
            val_fuel = 0.5 * (fuel_load[i-8][j] + fuel_load[i+8][j])

            #now wiggle the value. Since this is the first step, we allow the
            # average to wiggle up to 1/2 the range between min_val and max_val,
            # i.e, if the range between min and max is 4, then the total wiggle-room
            # will be +/-2, which is a range of 4.
            val_timb = DS_wiggle(val_timb, min_val, max_val, wiggle_range)
            val_fuel = DS_wiggle(val_fuel, min_val, max_val, wiggle_range)

            #and finally, assign the values to the grids
            timber_val[i][j] = val_timb
            fuel_load[i][j] = val_fuel

    #doing odd-indexed rows
    for j in range(8,129,16):
        for i in range(0,129,16):
            #look at the value above and below, and average them
            val_timb = 0.5 * (timber_val[i][j+8] + timber_val[i][j-8])
            val_fuel = 0.5 * (fuel_load[i][j+8] + fuel_load[i][j-8])

            #now wiggle the value as above
            val_timb = DS_wiggle(val_timb, min_val, max_val, wiggle_range)
            val_fuel = DS_wiggle(val_fuel, min_val, max_val, wiggle_range)

            #and finally, assign the values to the grids
            timber_val[i][j] = val_timb
            fuel_load[i][j] = val_fuel

    #Second, make the squares, by filling in those middle cells that we skipped
    #  in the diamond step. We only need to iterate on the odd-indexed rows,
    #  because there are no "middles" on the even-indexed rows. We'll increment
    #  starting at index 7 (the 8th value), and increment by 16s (skipping every
    #  second value in the 17x17 sub-grid, because they're already filled)
    for j in range(8,129,16):
        for i in range(8,129,16):
            #look at the four values, above, below, left and right, and average them
            val_timb = 0.25 * (timber_val[i-8][j] +
                               timber_val[i+8][j] +
                               timber_val[i][j-8] +
                               timber_val[i][j+8] )
            val_fuel = 0.25 * (fuel_load[i-8][j] +
                               fuel_load[i+8][j] +
                               fuel_load[i][j-8] +
                               fuel_load[i][j+8] )

            #on the square step, we don't need to wiggle unless we really feel
            # like it. I'm skipping it for now.

            #and finally, assign the values to the grids
            timber_val[i][j] = val_timb
            fuel_load[i][j] = val_fuel

    #TESTING
    #print("Step 2 results, 0-17")
    #printgrid(timber_val,0,17,0,17)
    #print("Step 2 results, 112-129")
    #printgrid(timber_val,112,129,112,129)

    #CONTINUING the DS algorithm with the 33X33 subgrid
    wiggle_range = roughness * (0.5 * (max_val - min_val))

    #doing even-indexed rows
    for j in range(0,129,8):
        for i in range(4,129,8):
            #look at the value 4 before, and 4 after, and average them
            val_timb = 0.5 * (timber_val[i-4][j] + timber_val[i+4][j])
            val_fuel = 0.5 * (fuel_load[i-4][j] + fuel_load[i+4][j])

            #now wiggle the value.
            val_timb = DS_wiggle(val_timb, min_val, max_val, wiggle_range)
            val_fuel = DS_wiggle(val_fuel, min_val, max_val, wiggle_range)

            #and finally, assign the values to the grids
            timber_val[i][j] = val_timb
            fuel_load[i][j] = val_fuel

    #doing odd-indexed rows
    for j in range(4,129,8):
        for i in range(0,129,8):
            #look at the value above and below, and average them
            val_timb = 0.5 * (timber_val[i][j+4] + timber_val[i][j-4])
            val_fuel = 0.5 * (fuel_load[i][j+4] + fuel_load[i][j-4])

            #now wiggle the value as above
            val_timb = DS_wiggle(val_timb, min_val, max_val, wiggle_range)
            val_fuel = DS_wiggle(val_fuel, min_val, max_val, wiggle_range)

            #and finally, assign the values to the grids
            timber_val[i][j] = val_timb
            fuel_load[i][j] = val_fuel

    #Second, make the squares
    for j in range(4,129,8):
        for i in range(4,129,8):
            #look at the four values, above, below, left and right, and average them
            val_timb = 0.25 * (timber_val[i-4][j] +
                               timber_val[i+4][j] +
                               timber_val[i][j-4] +
                               timber_val[i][j+4] )
            val_fuel = 0.25 * (fuel_load[i-4][j] +
                               fuel_load[i+4][j] +
                               fuel_load[i][j-4] +
                               fuel_load[i][j+4] )

            #on the square step, we don't need to wiggle unless we really feel
            # like it. I'm skipping it for now.

            #and finally, assign the values to the grids
            timber_val[i][j] = val_timb
            fuel_load[i][j] = val_fuel

    #TESTING
    #print("Step 3 results, 0-17")
    #printgrid(timber_val,0,17,0,17)
    #print("Step 3 results, 112-129")
    #printgrid(timber_val,112,129,112,129)

    #CONTINUING the DS algorithm with the 65X65 subgrid
    wiggle_range = roughness * roughness * (0.5 * (max_val - min_val))

    #doing even-indexed rows
    for j in range(0,129,4):
        for i in range(2,129,4):
            #look at the value 2 before, and 2 after, and average them
            val_timb = 0.5 * (timber_val[i-2][j] + timber_val[i+2][j])
            val_fuel = 0.5 * (fuel_load[i-2][j] + fuel_load[i+2][j])

            #now wiggle the value.
            val_timb = DS_wiggle(val_timb, min_val, max_val, wiggle_range)
            val_fuel = DS_wiggle(val_fuel, min_val, max_val, wiggle_range)

            #and finally, assign the values to the grids
            timber_val[i][j] = val_timb
            fuel_load[i][j] = val_fuel

    #doing odd-indexed rows
    for j in range(2,129,4):
        for i in range(0,129,4):
            #look at the value above and below, and average them
            val_timb = 0.5 * (timber_val[i][j+2] + timber_val[i][j-2])
            val_fuel = 0.5 * (fuel_load[i][j+2] + fuel_load[i][j-2])

            #now wiggle the value as above
            val_timb = DS_wiggle(val_timb, min_val, max_val, wiggle_range)
            val_fuel = DS_wiggle(val_fuel, min_val, max_val, wiggle_range)

            #and finally, assign the values to the grids
            timber_val[i][j] = val_timb
            fuel_load[i][j] = val_fuel

    #Second, make the squares
    for j in range(2,129,4):
        for i in range(2,129,4):
            #look at the four values, above, below, left and right, and average them
            val_timb = 0.25 * (timber_val[i-2][j] +
                               timber_val[i+2][j] +
                               timber_val[i][j-2] +
                               timber_val[i][j+2] )
            val_fuel = 0.25 * (fuel_load[i-2][j] +
                               fuel_load[i+2][j] +
                               fuel_load[i][j-2] +
                               fuel_load[i][j+2] )

            #on the square step, we don't need to wiggle unless we really feel
            # like it. I'm skipping it for now.

            #and finally, assign the values to the grids
            timber_val[i][j] = val_timb
            fuel_load[i][j] = val_fuel

    #TESTING
    #print("Step 4 results, 0-17")
    #printgrid(timber_val,0,17,0,17)
    #print("Step 4 results, 112-129")
    #printgrid(timber_val,112,129,112,129)

    #FINALLY: finishing the DS algorithm with the whole 129x129 grid
    wiggle_range = roughness * roughness * roughness * (0.5 * (max_val - min_val))

    #doing even-indexed rows
    for j in range(0,129,2):
        for i in range(1,129,2):
            #look at the value 1 before, and 1 after, and average them
            val_timb = 0.5 * (timber_val[i-1][j] + timber_val[i+1][j])
            val_fuel = 0.5 * (fuel_load[i-1][j] + fuel_load[i+1][j])

            #now wiggle the value.
            val_timb = DS_wiggle(val_timb, min_val, max_val, wiggle_range)
            val_fuel = DS_wiggle(val_fuel, min_val, max_val, wiggle_range)

            #and finally, assign the values to the grids
            timber_val[i][j] = val_timb
            fuel_load[i][j] = val_fuel

    #doing odd-indexed rows
    for j in range(1,129,2):
        for i in range(0,129,2):
            #look at the value above and below, and average them
            val_timb = 0.5 * (timber_val[i][j+1] + timber_val[i][j-1])
            val_fuel = 0.5 * (fuel_load[i][j+1] + fuel_load[i][j-1])

            #now wiggle the value as above
            val_timb = DS_wiggle(val_timb, min_val, max_val, wiggle_range)
            val_fuel = DS_wiggle(val_fuel, min_val, max_val, wiggle_range)

            #and finally, assign the values to the grids
            timber_val[i][j] = val_timb
            fuel_load[i][j] = val_fuel

    #Second, make the squares
    for j in range(1,129,2):
        for i in range(1,129,2):
            #look at the four values, above, below, left and right, and average them
            val_timb = 0.25 * (timber_val[i-1][j] +
                               timber_val[i+1][j] +
                               timber_val[i][j-1] +
                               timber_val[i][j+1] )
            val_fuel = 0.25 * (fuel_load[i-1][j] +
                               fuel_load[i+1][j] +
                               fuel_load[i][j-1] +
                               fuel_load[i][j+1] )

            #on the square step, we don't need to wiggle unless we really feel
            # like it. I'm skipping it for now.

            #and finally, assign the values to the grids
            timber_val[i][j] = val_timb
            fuel_load[i][j] = val_fuel

    #TESTING
    #print("Step 5 results, 0-17")
    #printgrid(timber_val,0,17,0,17)
    #print("Step 5 results, 112-129")
    #printgrid(timber_val,112,129,112,129)

    #FINALLY - RETURNING THE LANDSCAPE
    results = [timber_val, fuel_load]
    return results

def DS_wiggle(current_val, min, max, range):
    #This function does the actual wiggle step. It will limit the possible range
    # of values to +/- 1/2x the range argument given, and will enforce the min and max
    # restrictions
    top = current_val + (0.5 * range)
    bottom = top - range

    #enforcing boundaries
    if top > max:
        top = max
    if bottom < min:
        bottom = min

    #the new value can be anything in between these ranges, so just grab a value
    new_val = random.uniform(bottom,top)

    return new_val

def printgrid(grid, x_start, x_end, y_start, y_end):
    #this is a test function to print segments of any 2D array. Make sure the
    #  indices are okay, because it's not going to bother checking for you.

    for i in range(x_start,x_end):
        for j in range(y_start, y_end):
            print(str(int(grid[i][j])) + " "), #terminating with a comma instructs print to skip the newline
        print(" ") #to get a newline


#!/usr/bin/env python3

''' Original code from: https://github.com/xysun/pychat
    Updated for use in OU ACM Chapter's networking talk
    This file contains code for running the client'''

import select
import socket
import sys
import utils

READ_BUFFER = 4096

def prompt():
    ''' Prompt for client input '''
    print('#> ', end=' ', flush=True)

def main():
    ''' Main function for the client script '''
    if len(sys.argv) < 2:
        print("Usage: Python3 client.py [hostname]", file=sys.stderr)
        sys.exit(1)
    else:
        server_connection = socket.socket(socket.AF_INET, socket.SOCK_STREAM)
        server_connection.setsockopt(socket.SOL_SOCKET, socket.SO_REUSEADDR, 1)
        server_connection.connect((sys.argv[1], utils.PORT))

    print("Connected to server\n")
    msg_prefix = ''

    socket_list = [sys.stdin, server_connection]

    while True:
        read_sockets, _, _ = select.select(socket_list, [], [])
        # the _ means drop the value in python
        for sock in read_sockets:
            if sock is server_connection: # incoming message
                msg = sock.recv(READ_BUFFER)
                if not msg:
                    print("Server down!")
                    sys.exit(2)
                else:
                    if msg == utils.QUIT_STRING.encode():
                        sys.stdout.write('Bye\n')
                        sys.exit(2)
                    else:
                        sys.stdout.write(msg.decode())
                        if 'Please tell us your name' in msg.decode():
                            msg_prefix = 'name: ' # identifier for name
                        else:
                            msg_prefix = ''
                        prompt()

            else:
                msg = msg_prefix + sys.stdin.readline()
                server_connection.sendall(msg.encode())

if __name__ == '__main__':
    main()


''' Crie um programa que leia o nome e o preço de vários produtos. O programa deverá perguntar se o usuário
vai continuar ou não. No final, mostre:
A) qual é o total gasto na compra.
B) quantos produtos custam mais de R$1000.
C) qual é o nome do produto mais barato.'''

total_gasto = count = produto_barato = total_mil = 0
produto = ''
while True:
    nome_produto = str(input('Qual o nome do produto? ')).strip()
    preco_produto = float(input('Qual o preço do produto? '))
    count += 1
    total_gasto += preco_produto
    print('='*25)
    if preco_produto > 1000:
        total_mil += 1
    if count == 1 or preco_produto < produto_barato:
        produto_barato = preco_produto
        produto = nome_produto
    resposta = ' '
    while resposta not in 'SN':
        resposta = str(input('Quer continuar?[S/N] ')).strip().upper()[0]
        print('=' * 25)
    if resposta == 'N':
        break
print(f'O total gasto na compra foi de R${total_gasto}')
print(f'{total_mil} produtos custaram mais de R$1000.')
print(f'O nome do produto mais barato foi {produto} e custou R$ {produto_barato}')


from users.models import Customer, Executer
from task.models import Task
from rest_framework import serializers

class CustomerSerializer(serializers.ModelSerializer):
    class Meta:
        model = Customer
        fields = ('id', 'first_name', 'balance')

class ExecuterSerializer(serializers.ModelSerializer):
    class Meta:
        model = Executer
        fields = ('id', 'first_name', 'balance')

class TaskSerializer(serializers.ModelSerializer):
    # customer = CustomerSerializer(read_only=True)
    # executer = ExecuterSerializer(read_only=True)

    class Meta:
        model = Task
        fields = ('id', 'title', 'description', 'price', 'owner', 'created_by')


import os
import yaml
import sys

def get_bom_dir():
    return os.path.join(sys.argv[1], "bom")

def get_default_tkr_bom():
    bomDir = get_bom_dir()
    for bomFile in os.listdir(bomDir):
        if(bomFile.startswith("tkr-bom")):
            return bomFile
    return None

def main():
    bomFile = get_default_tkr_bom()
    bomDir = get_bom_dir()
    bomFilePath = os.path.join(bomDir, bomFile)
    with open(bomFilePath) as file:
        bom = yaml.safe_load(file)
    osInfo = bom["azure"][0]["osinfo"]

    # Create a file with no azure VM image info in BOM
    del bom["azure"]
    bom["release"]["version"] = "v0.0.0+no-azure-image"
    with open(os.path.join(bomDir, "bom-clustergen-no-azure-image-test.yaml"), 'w') as file:
        documents = yaml.dump(bom, file)

    # Create a file with marketplace azure VM image info in BOM
    bom["azure"] = [{
        "publisher": "bom-image-publisher",
        "offer":"bom-image-offer",
        "sku":"bom-image-sku",
        "version":"bom-image-version",
        "thirdPartyImage":True,
        "osinfo": osInfo
    }]
    bom["release"]["version"] = "v0.0.0+marketplace-image"
    with open(os.path.join(bomDir, "bom-clustergen-marketplace-image-test.yaml"), 'w') as file:
        documents = yaml.dump(bom, file)

    # Create a file with marketplace azure VM image(no thirdPartyImage flag) info in BOM
    bom["azure"] = [{
        "publisher": "bom-image-publisher",
        "offer":"bom-image-offer",
        "sku":"bom-image-sku",
        "version":"bom-image-version",
        "osinfo": osInfo
    }]
    bom["release"]["version"] = "v0.0.0+marketplace-image-no-thirdpartyimage"
    with open(os.path.join(bomDir, "bom-clustergen-marketplace-no-thirdparty-image-test.yaml"), 'w') as file:
        documents = yaml.dump(bom, file)

    # Create a file with shared gallery azure VM image info in BOM
    bom["azure"] = [{
        "resourceGroup": "bom-resource-group",
        "name":"bom-image-name",
        "subscriptionID":"bom-subscription-id",
        "version":"bom-image-version",
        "gallery":"bom-image-gallery",
        "osinfo": osInfo
    }]
    bom["release"]["version"] = "v0.0.0+shared-gallery-image"
    with open(os.path.join(bomDir, "bom-clustergen-shared-gallery-image-test.yaml"), 'w') as file:
        documents = yaml.dump(bom, file)

if __name__ == "__main__":
    main()


import boto3
import json
import logging
import time
import botocore
import os
import sys
from datetime import datetime

logger = logging.getLogger()
logger.setLevel(logging.INFO)
ec2_client = boto3.client('ec2')
asg_client = boto3.client('autoscaling')
ec2 = boto3.resource('ec2')

def lambda_handler(event, context):
    instance_id = event['detail']['EC2InstanceId']
    LifecycleHookName = event['detail']['LifecycleHookName']
    AutoScalingGroupName = event['detail']['AutoScalingGroupName']
    secgroup_id = os.environ['SecGroupId']
    vpc_id = os.environ['VPCId']
    route_table_id = os.environ['WANRouteTable']
    cidr = str(os.environ['VIPCIDRBlock'])
    vip = str(os.environ['VIPAddress']).split('/')[0]
    eipaddress = str(os.environ['EIPAddress']).split('/')[0]
    eipallocation = str(os.environ['EIPAllocationId']).split('/')[0]
    LambdaInfoTracing = str(os.environ['LambdaInfoTracing'])
    InstanceRequiresReboot = str(os.environ['InstanceRequiresReboot'])
    SubnetCreationAttempts = int(os.environ['SubnetCreationAttempts'])

    # printing event received:
    infolog("lambda_handler -- Event keys: {}".format(list(event['detail'].keys())),LambdaInfoTracing)
    infolog("lambda_handler -- Complete Event: {}".format(str(event['detail'])),LambdaInfoTracing)

    # Find out AZ from the instance
    AZ_list = []

    try:
        event_instanceid = event['detail']['EC2InstanceId']
        infolog("lambda_handler -- EC2 instance triggering event: {}".format(event_instanceid),LambdaInfoTracing)
    except botocore.exceptions.ClientError as e:
        errorlog("Error extracting EC2 instance from event details: {}".format(e.response['Error']))

    try:
        instance_list = ec2_client.describe_instances()
        infolog("lambda_handler -- EC2 instances description response: {}".format(instance_list),LambdaInfoTracing)
        for reservation in instance_list["Reservations"]:
            for instance in reservation.get("Instances", []):
                if instance['InstanceId'] == event_instanceid:
                    AZ_list.append(instance["Placement"]["AvailabilityZone"])
        infolog("lambda_handler -- AZs out of EC2 instances description response: {}".format(AZ_list),LambdaInfoTracing)
    except botocore.exceptions.ClientError as e:
            errorlog("Error extracting AZ from EC2 instances description response: {}".format(e.response['Error']))

    if AZ_list:
        AZ = AZ_list[0]
    else:
        errorlog("No AZs could be extracted")
        return

    # Tracing EC2 details
    infolog("lambda_handler -- Event: {}".format(event["detail-type"]),LambdaInfoTracing)
    infolog("lambda_handler -- Instance Id: {}".format(instance_id),LambdaInfoTracing)
    infolog("lambda_handler -- LifecycleHookName: {}".format(LifecycleHookName),LambdaInfoTracing)
    infolog("lambda_handler -- AutoScalingGroupName: {}".format(AutoScalingGroupName),LambdaInfoTracing)
    infolog("lambda_handler -- secgroup_id: {}".format(secgroup_id),LambdaInfoTracing)
    infolog("lambda_handler -- vpc_id: {}".format(vpc_id),LambdaInfoTracing)
    infolog("lambda_handler -- route_table_id: {}".format(route_table_id),LambdaInfoTracing)
    infolog("lambda_handler -- cidr: {}".format(cidr),LambdaInfoTracing)
    infolog("lambda_handler -- vip: {}".format(vip),LambdaInfoTracing)
    infolog("lambda_handler -- eipaddress: {}".format(eipaddress),LambdaInfoTracing)
    infolog("lambda_handler -- eipallocation: {}".format(eipallocation),LambdaInfoTracing)
    infolog("lambda_handler -- AZ: {}".format(AZ),LambdaInfoTracing)
    infolog("lambda_handler -- InstanceRequiresReboot: {}".format(InstanceRequiresReboot),LambdaInfoTracing)
    infolog("lambda_handler -- SubnetCreationAttempts: {}".format(SubnetCreationAttempts),LambdaInfoTracing)

    if event["detail-type"] == "EC2 Instance-launch Lifecycle Action":

        subnet_id = None
        attempts = 0
        # Attempts to create secondary subnet in same AZ and associate it to Route Table
        while (not subnet_id) and attempts < SubnetCreationAttempts :
            infolog("lambda_handler -- Attempt nr. {} to create and associate subnet".format(attempts),LambdaInfoTracing)
            subnet_id = create_and_associate_subnet(vpc_id,cidr,AZ,route_table_id,LambdaInfoTracing)
            attempts += 1
            time.sleep(10)

        if not subnet_id:
            # No subnet could be created after SubnetCreationAttempts attempts, abandon lifecycle hook
            # Lifecycle Hook event failed
            complete_lifecycle_action_failure(LifecycleHookName,AutoScalingGroupName,instance_id,LambdaInfoTracing)
            return

        # Create ENI within secondary subnet in same AZ
        interface_id = create_interface(subnet_id,secgroup_id,vip,eipaddress,eipallocation,LambdaInfoTracing)

        if not interface_id:
            # No ENI could be created
            # Lifecycle Hook event failed
            complete_lifecycle_action_failure(LifecycleHookName,AutoScalingGroupName,instance_id,LambdaInfoTracing)
            disassociate_delete_subnet(subnet_id,route_table_id,LambdaInfoTracing)
            return

        # Index is 1 because it is secondary interface to the instance
        attachment = attach_interface(interface_id,instance_id,1,LambdaInfoTracing)

        if not attachment:
            # ENI could not be attached
            # Lifecycle Hook event failed
            complete_lifecycle_action_failure(LifecycleHookName,AutoScalingGroupName,instance_id,LambdaInfoTracing)
            delete_interface(interface_id,eipaddress,eipallocation,LambdaInfoTracing)
            return

        if str(InstanceRequiresReboot) == "true":
            # ENI attachment requires instance reboot
            time.sleep(30)
            restart_instance(instance_id,LambdaInfoTracing)
            time.sleep(120)

        # Lifecycle Hook event successfully completed otherwise
        complete_lifecycle_action_success(LifecycleHookName,AutoScalingGroupName,instance_id,LambdaInfoTracing)
        return

    if event["detail-type"] == "EC2 Instance-terminate Lifecycle Action":

        # Obtained Subnet ID from same VPC and CIDR range
        subnet_id = get_subnet(vpc_id,cidr,LambdaInfoTracing)

        # Obtained Interface ID from same subnet
        interface_id = get_interface(subnet_id,vip,LambdaInfoTracing)

        # Interface ID could be extracted from Subnet ID
        if interface_id is not None:
            try:
                # Detach the ENI from the instance
                detach_interface(interface_id,LambdaInfoTracing)
            except botocore.exceptions.ClientError as e:
                errorlog("Error detaching interface: {}".format(e.response['Error']))

            try:
                # After detaching, delete the interface
                delete_interface(interface_id,eipaddress,eipallocation,LambdaInfoTracing)
            except botocore.exceptions.ClientError as e:
                errorlog("Error deleting interface: {}".format(e.response['Error']))

        if subnet_id is not None:
            try:
                # After having detached and deleted the ENI, subnet can be deleted
                disassociate_delete_subnet(subnet_id,route_table_id,LambdaInfoTracing)
            except botocore.exceptions.ClientError as e:
                errorlog("Error deleting subnet: {}".format(e.response['Error']))

        # After detaching ENI, deleting it and deleting the subnet, this is a successful lifecycle hook
        complete_lifecycle_action_success(LifecycleHookName,AutoScalingGroupName,instance_id,LambdaInfoTracing)
        return

def create_and_associate_subnet(vpc_id,cidr,az,route_table_id,LambdaInfoTracing):
    """
    create subnet id from VPC in a specific AZ with a private IPv4 CIDR range

    :param vpc_id: VPC id
    :param cidr: CIDR IPv4 range for subnet
    :param az: Availability Zone
    :param route_table_id: Route Table id

    """
    subnet_id = None
    if vpc_id and cidr:
        try:
            infolog("create_and_associate_subnet -- VPC ID parameter: {}".format(vpc_id),LambdaInfoTracing)
            infolog("create_and_associate_subnet -- CIDR parameter: {}".format(cidr),LambdaInfoTracing)
            infolog("create_and_associate_subnet -- AZ parameter: {}".format(az),LambdaInfoTracing)
            subnet = ec2_client.create_subnet(TagSpecifications=[{'ResourceType': 'subnet', 'Tags': [ {'Key': 'Name', 'Value': 'VIP Subnet'}]}],AvailabilityZone=az,CidrBlock=cidr,VpcId= vpc_id)
            infolog("create_and_associate_subnet -- EC2 create subnet response: {}".format(subnet),LambdaInfoTracing)
            subnet_id = subnet['Subnet']['SubnetId']
            infolog("create_and_associate_subnet -- EC2 created subnet ID: {}".format(subnet_id),LambdaInfoTracing)
        except botocore.exceptions.ClientError as e:
            errorlog("Error creating subnet: {}".format(e.response['Error']))
            if e.response['Error']['Code'] == 'InvalidSubnet.Conflict':
                errorlog("create_and_associate_subnet -- Previous subnet {} has not been deleted yet".format(cidr))

    if subnet_id:
        try:
            infolog("create_and_associate_subnet -- Route Table parameter: {}".format(route_table_id),LambdaInfoTracing)
            infolog("create_and_associate_subnet -- created Subnet ID: {}".format(subnet_id),LambdaInfoTracing)
            response = ec2_client.associate_route_table(RouteTableId=route_table_id,SubnetId=subnet_id)
            infolog("create_and_associate_subnet -- found Route Table: {}".format(response),LambdaInfoTracing)
        except botocore.exceptions.ClientError as e:
            errorlog("Error associating subnet: {}".format(e.response['Error']))

    return subnet_id

def create_interface(subnet_id,sg_id,vip,eipaddress,eipallocation,LambdaInfoTracing):
    """
    create interface id with subnet, Security Group and a specific private IPv4 address

    :param subnet_id: subnet id within VPC
    :param sg_id: Security Group ID
    :param vip: (virtual) private IPv4 address that is mapped to interface

    """

    network_interface_id = None
    if subnet_id:
        try:
            infolog("create_interface -- subnet ID parameter: {}".format(subnet_id),LambdaInfoTracing)
            infolog("create_interface -- Security Group ID parameter: {}".format(sg_id),LambdaInfoTracing)
            infolog("create_interface -- Virtual IP address parameter:: {}".format(vip),LambdaInfoTracing)
            network_interface = ec2_client.create_network_interface(Description='VIP ENI',Groups=[sg_id],SubnetId=subnet_id,PrivateIpAddress=vip)
            infolog("create_interface -- EC2 create ENI response: {}".format(network_interface),LambdaInfoTracing)
            network_interface_id = network_interface['NetworkInterface']['NetworkInterfaceId']
            infolog("create_interface -- EC2 created ENI ID: {}".format(network_interface_id),LambdaInfoTracing)
        except botocore.exceptions.ClientError as e:
            errorlog("Error creating network interface: {}".format(e.response['Error']))

    # Associate existing EIP allocation
    if eipallocation:
        try:
            infolog("create_interface -- eipaddress parameter: {}".format(eipaddress),LambdaInfoTracing)
            infolog("create_interface -- eipallocation parameter: {}".format(eipallocation),LambdaInfoTracing)
            response = ec2_client.associate_address(AllocationId=eipallocation,NetworkInterfaceId=network_interface_id)
            infolog("create_interface -- EC2 associate EIP response: {}".format(response),LambdaInfoTracing)
        except botocore.exceptions.ClientError as e:
            errorlog("Error associating EIP to network interface: {}".format(e.response['Error']))

    return network_interface_id

def get_subnet(vpc_id,cidr,LambdaInfoTracing):
    """
    obtain subnet id from VPC based on IPv4 CIDR range

    :param vpc_id: VPC id
    :param cidr: CIDR IPv4 range from subnet

    """

    subnet_id = None
    if vpc_id and cidr:
        try:
            infolog("get_subnet -- VPC ID parameter: {}".format(vpc_id),LambdaInfoTracing)
            infolog("get_subnet -- CIDR parameter: {}".format(cidr),LambdaInfoTracing)
            response = ec2_client.describe_subnets(
                Filters=[
                    {
                        'Name': 'cidr-block',
                        'Values': [cidr]
                    }
                ]
            )
            infolog("get_subnet -- EC2 describe subnet reponse: {}".format(response),LambdaInfoTracing)
            if response['Subnets']:
                subnet_id = response['Subnets'][0]['SubnetId']
                infolog("get_subnet -- EC2 obtained subnet ID: {}".format(subnet_id),LambdaInfoTracing)
        except botocore.exceptions.ClientError as e:
            errorlog("Error obtaining subnet: {}".format(e.response['Error']))
    return subnet_id

def get_interface(subnet_id,vip,LambdaInfoTracing):
    """
    obtain interface id from subnet based on specific IPv4 address

    :param subnet_id: subnet id within VPC
    :param vip: (virtual) IPv4 address that is mapped to interface

    """

    interface_id = None
    if subnet_id:
        try:
            infolog("get_interface -- Subnet ID parameter: {}".format(subnet_id),LambdaInfoTracing)
            infolog("get_interface -- Virtual IP address parameter: {}".format(vip),LambdaInfoTracing)
            response = ec2_client.describe_network_interfaces(
                Filters=[{"Name": "private-ip-address", "Values": [vip]}]
            )
            infolog("get_interface -- EC2 describe ENI response: {}".format(response),LambdaInfoTracing)
            if response['NetworkInterfaces']:
                interface_id = response['NetworkInterfaces'][0]['NetworkInterfaceId']
                infolog("get_interface -- EC2 obtained interface ID: {}".format(interface_id),LambdaInfoTracing)
        except botocore.exceptions.ClientError as e:
            errorlog("Error obtaining interface: {}".format(e.response['Error']))
    return interface_id

def detach_interface(network_interface_id,LambdaInfoTracing):
    """
    detach  interface if it is attached to instance

    :param network_interface_id: network interface id that
                               we previously obtain

    """

    attachment = None
    response = None
    if network_interface_id:
        try:
            infolog("detach_interface -- Network Interface ID parameter: {}".format(network_interface_id),LambdaInfoTracing)
            response = ec2_client.describe_network_interfaces(
                Filters=[{"Name": "network-interface-id", "Values": [network_interface_id]}]
            )
            infolog("detach_interface -- EC2 describe ENI response: {}".format(response),LambdaInfoTracing)
        except botocore.exceptions.ClientError as e:
            errorlog("Error obtaining interface description: {}".format(e.response['Error']))

    if response:
        try:
            if "Attachment" in response['NetworkInterfaces'][0]:
                attachment = response['NetworkInterfaces'][0]['Attachment']['AttachmentId']
                infolog("detach_interface -- EC2 obtained attachmend id: {}".format(attachment),LambdaInfoTracing)
        except botocore.exceptions.ClientError as e:
            errorlog("Error obtaining attachment: {}".format(e.response['Error']))

    if attachment:
        try:
            response = ec2_client.detach_network_interface(AttachmentId=attachment,Force=True)
            infolog("detach_interface -- EC2 obtained response from interface detachment: {}".format(response),LambdaInfoTracing)
            # Wait time to accomplish detachment
            time.sleep(60)
        except botocore.exceptions.ClientError as e:
            errorlog("Error trying detachment: {}".format(e.response['Error']))

    return attachment

def attach_interface(network_interface_id,instance_id,index,LambdaInfoTracing):
    """
    attach  interface to instance

    :param network_interface_id: network interface id that
                               we previously obtain
    :param instance_id: instance ID to attach interface to
    :param index: index for interface attachment (starting from '0')

    """

    attachment = None
    if network_interface_id and instance_id:
        try:
            infolog("attach_interface -- Network Interface ID parameter: {}".format(network_interface_id),LambdaInfoTracing)
            infolog("attach_interface -- Instance ID parameter: {}".format(instance_id),LambdaInfoTracing)
            attach_interface = ec2_client.attach_network_interface(
                NetworkInterfaceId=network_interface_id,
                InstanceId=instance_id,
                DeviceIndex=index
            )
            infolog("attach_interface -- EC2 attach ENI response: {}".format(attach_interface),LambdaInfoTracing)
            attachment = attach_interface['AttachmentId']
            infolog("attach_interface -- created network attachment ID: {}".format(attachment),LambdaInfoTracing)

            network_interface = ec2.NetworkInterface(network_interface_id)

            #modify_attribute doesn't allow multiple parameter change at once..
            network_interface.modify_attribute(
                SourceDestCheck={
                    'Value': False
                }
            )
            network_interface.modify_attribute(
                Attachment={
                    'AttachmentId': attachment,
                    'DeleteOnTermination': True
                },
            )
            infolog("attach_interface -- created network interface: {}".format(network_interface),LambdaInfoTracing)

        except botocore.exceptions.ClientError as e:
            errorlog("Error attaching network interface: {}".format(e.response['Error']))

    return attachment

def delete_interface(network_interface_id,eipaddress,eipallocation,LambdaInfoTracing):
    """
    delete interface

    :param network_interface_id: network interface id to be deleted

    """
    association = None

    if network_interface_id:
        try:
            infolog("delete_interface -- Network Interface ID parameter: {}".format(network_interface_id),LambdaInfoTracing)
            response = ec2_client.describe_network_interfaces(
                Filters=[{"Name": "network-interface-id", "Values": [network_interface_id]}]
            )
            infolog("delete_interface -- EC2 describe ENI response: {}".format(response),LambdaInfoTracing)
        except botocore.exceptions.ClientError as e:
            errorlog("Error obtaining interface description: {}".format(e.response['Error']))

    # Disassociate existing EIP allocation
    if ( "NetworkInterfaces" in response ) and eipallocation:
        try:
            if response['NetworkInterfaces'][0]:
                if "Association" in response['NetworkInterfaces'][0]:
                    association = response['NetworkInterfaces'][0]['Association']['AssociationId']
                    infolog("delete_interface -- EC2 obtained association id: {}".format(association),LambdaInfoTracing)
        except botocore.exceptions.ClientError as e:
            errorlog("Error obtaining association: {}".format(e.response['Error']))

    if association:
        try:
            infolog("delete_interface -- eipaddress parameter: {}".format(eipaddress),LambdaInfoTracing)
            infolog("delete_interface -- eipallocation parameter: {}".format(eipallocation),LambdaInfoTracing)
            response = ec2_client.disassociate_address(AssociationId=association)
            infolog("delete_interface -- EC2 disassociate EIP response: {}".format(response),LambdaInfoTracing)
        except botocore.exceptions.ClientError as e:
            errorlog("Error disassociating EIP from network interface: {}".format(e.response['Error']))

    # Then delete the interface
    try:
        infolog("delete_interface -- Network Interface ID parameter: {}".format(network_interface_id),LambdaInfoTracing)
        ec2_client.delete_network_interface(
            NetworkInterfaceId=network_interface_id
        )
        infolog("delete_interface -- EC2 deleted network interface: {}".format(network_interface_id),LambdaInfoTracing)
        return True

    except botocore.exceptions.ClientError as e:
        errorlog("Error deleting interface {}: {}".format(network_interface_id,e.response['Error']))

def disassociate_delete_subnet(subnet_id,route_table_id,LambdaInfoTracing):
    """
    disassociate_delete subnet

    :param subnet_id: subnet id to be deleted
    :param route_table_id: route table id to disassociate subnet from

    """
    try:
        infolog("disassociate_delete_subnet -- Subnet ID parameter: {}".format(subnet_id),LambdaInfoTracing)
        infolog("disassociate_delete_subnet -- Route Table ID parameter: {}".format(route_table_id),LambdaInfoTracing)
        response = ec2_client.describe_route_tables(RouteTableIds=[route_table_id])
        infolog("disassociate_delete_subnet -- EC2 obtained route table description: {}".format(response),LambdaInfoTracing)
        RouteTableAssociationId = response['RouteTables'][0]['Associations'][0]['RouteTableAssociationId']
        infolog("disassociate_delete_subnet -- EC2 obtained route table id subnet: {}".format(RouteTableAssociationId),LambdaInfoTracing)
    except botocore.exceptions.ClientError as e:
        errorlog("Error obtaining Route Table Association {}: {}".format(subnet_id,e.response['Error']))

    if RouteTableAssociationId:
        try:
            infolog("disassociate_delete_subnet -- Subnet ID parameter: {}".format(subnet_id),LambdaInfoTracing)
            infolog("disassociate_delete_subnet -- Route Table ID parameter: {}".format(route_table_id),LambdaInfoTracing)
            response = ec2_client.disassociate_route_table(AssociationId=RouteTableAssociationId)
            infolog("disassociate_delete_subnet -- EC2 disassociating subnet: {}".format(response),LambdaInfoTracing)
        except botocore.exceptions.ClientError as e:
            errorlog("Error disassociating subnet {}: {}".format(subnet_id,e.response['Error']))

    try:
        infolog("disassociate_delete_subnet -- Subnet ID parameter: {}".format(subnet_id),LambdaInfoTracing)
        ec2_client.delete_subnet(
            SubnetId=subnet_id
        )
        infolog("disassociate_delete_subnet -- EC2 deleted subnet: {}".format(subnet_id),LambdaInfoTracing)
        return True
    except botocore.exceptions.ClientError as e:
        errorlog("Error deleting subnet {}: {}".format(subnet_id,e.response['Error']))

def complete_lifecycle_action_success(hookname,groupname,instance_id,LambdaInfoTracing):
    """
    Complete Lifecycle Action Success

    Complete the lifecycle with success if no exception occurs

    :param hookname: Life cycle hook name
    :param groupname: Autoscaling group name
    :param instanceid: Instance id for newly launched instance

    """

    try:
        infolog("complete_lifecycle_action_success -- hookname parameter: {}".format(hookname),LambdaInfoTracing)
        infolog("complete_lifecycle_action_success -- ASG parameter: {}".format(groupname),LambdaInfoTracing)
        infolog("complete_lifecycle_action_success -- Instance ID parameter: {}".format(instance_id),LambdaInfoTracing)
        asg_client.complete_lifecycle_action(
            LifecycleHookName=hookname,
            AutoScalingGroupName=groupname,
            InstanceId=instance_id,
            LifecycleActionResult='CONTINUE'
        )
        infolog("complete_lifecycle_action_success -- Lifecycle hook CONTINUEd for: {}".format(instance_id),LambdaInfoTracing)
    except botocore.exceptions.ClientError as e:
            errorlog("Error completing life cycle hook for instance {}: {}".format(instance_id, e.response['Error']))
            errorlog('{"Error": "1"}')

def complete_lifecycle_action_failure(hookname,groupname,instance_id,LambdaInfoTracing):
    """
    Complete Lifecycle Action Failure

    Complete the lifecycle with failure if exception occurs

    :param hookname: Life cycle hook name
    :param groupname: Autoscaling group name
    :param instanceid: Instance id for newly launched instance

    """

    try:
        infolog("complete_lifecycle_action_failure -- hookname parameter: {}".format(hookname),LambdaInfoTracing)
        infolog("complete_lifecycle_action_failure -- ASG parameter: {}".format(groupname),LambdaInfoTracing)
        infolog("complete_lifecycle_action_failure -- Instance ID parameter: {}".format(instance_id),LambdaInfoTracing)
        asg_client.complete_lifecycle_action(
            LifecycleHookName=hookname,
            AutoScalingGroupName=groupname,
            InstanceId=instance_id,
            LifecycleActionResult='ABANDON'
        )
        infolog("complete_lifecycle_action_failure -- Lifecycle hook ABANDONed for: {}".format(instance_id),LambdaInfoTracing)
    except botocore.exceptions.ClientError as e:
            errorlog("Error completing life cycle hook for instance {}: {}".format(instance_id, e.response['Error']))
            errorlog('{"Error": "1"}')

def restart_instance(instance_id,LambdaInfoTracing):
    """
    restart instance for proper ENI attachment

    :param instance_id: instance ID to restart and discover with newly attached interface

    """
    if instance_id:
        try:
            infolog("restart_instance -- Instance ID: {}".format(instance_id),LambdaInfoTracing)
            response = ec2_client.reboot_instances(
                InstanceIds=[instance_id]
            )
            infolog("restart_instance -- EC2 restart EC2 response: {}".format(response),LambdaInfoTracing)
        except botocore.exceptions.ClientError as e:
            errorlog("Error restarting EC2 instance: {}".format(e.response['Error']))

def errorlog(error):
    """
    Log

    takes message as an input and print it with time in iso format
    """
    logger.error('%s', error)

def infolog(string,LambdaInfoTracing):
    """
    Log

    takes message as an input and print it with time in iso format
    """
    if str(LambdaInfoTracing) == "true":
        logger.info('%s', string)