#!/usr/bin/python3

# python test_1.py --rai_dir ~/rai-python
import sys
import os

dir_file=os.path.abspath(os.path.dirname(__file__))
sys.path.append(dir_file+'/../ry/')
from libry import *

#from numpy import *

import tensorflow as tf

import rai_setup as rai_world
#import minimal_experiment as expert

import datetime
import time
import shutil

# Main function
# Train hierarchical policy
# Use hierarchical policy to solve sequential manipulation problems
# Note: goal formulations: (held obj) (on obj table)

def createResults(rai_net, cheat_goalstate=False,cheat_tree=False, start=1, planOnly=False, test=False):
	# Creates directory for results
	if rai_net.setup == "minimal":

		# Append modes to name
		append_folder=""
		if cheat_goalstate:
			append_folder=append_folder+"_goalstate"
		if cheat_tree:
			append_folder=append_folder+"_tree"

		if not rai_net.tray=="":
			append_folder=append_folder+"_tray"

		# Create dir
		path=rai_net.path_rai+'/result_minimal/'+rai_net.model_dir+append_folder
		if not(os.path.exists(path)):
				os.makedirs(path)

		if start==1:
			if rai_net.NNmode in ["mixed10"]:
				appendmode="mixed"+str(rai_net.dataMode)
			elif rai_net.NNmode in ["FFnew", "minimal"]:
				appendmode=rai_net.NNmode+str(rai_net.dataMode)
			else:
				NotImplementedError

			# Append mode to file name
			if planOnly:
				append_test="_plan"
			else:
				append_test=""
			if test:
				append_test=append_test+"_test"

			# Copy parameter file
			shutil.copyfile(rai_net.path_rai+'/logs/'+rai_net.model_dir+"_"+appendmode+'/params.txt',path+'/params.txt')

			# Create Summary file
			with open(path+'/env'+str(rai_net.nenv).zfill(3)+append_test+'.txt', 'a+') as f:
				f.write("\n\n-----Result for env "+str(rai_net.nenv)+"-----\n\n")

		return path

def writeResults(rai_net,skeleton,typeDecision,successmsg,path, goalnumber_string="", planOnly=False, feasible=True, tries=0, test=False):

	if rai_net.setup == "minimal":
		# Append mode to file name
		if planOnly:
			append_test="_plan"
		else:
			append_test=""
		if test:
			append_test=append_test+"_test"

		if feasible:
			strfeas=" feasible 1"
		else:
			strfeas=" infeasible 0"

		with open(path+'/env'+str(rai_net.nenv).zfill(3)+append_test+'.txt', 'a+') as f:
			# Header_ objective, feasible
			f.write("----"+successmsg+" "+goalnumber_string+": "+rai_net.goalString_orig+strfeas+"----\n")
			if tries>0 and feasible:
				f.write("---- in "+str(tries)+" tries ----\n")

			actions=rai_world.splitStringStep(skeleton, list_old=[],verbose=0)
			for act, typedec in zip(actions,typeDecision):
				# For all high-level actions
				# Print action
				f.write("\t\t  "+typedec[0]+": "+act)
				if typedec[0]=="NN":
					# If directly through policy [seq seqPath] feasibility
					f.write("[ "+str(typedec[1])+" "+str(typedec[2])+" ]")
					f.write("\n")

				elif typedec[0]=="MP":
					# If through evalution of all high-level actions: [seq seqPath] feasibility + originahigh-level action that was replaced
					f.write("[ "+str(typedec[3])+" "+str(typedec[4])+" ]")
					f.write("\twith prob "+str(round(typedec[2],3))+" instead of "+typedec[1]+"\n")

				else:
					NotImplementedError
			f.write("--------------------\n\n")

def printResult(rai_net, skeleton):
	# Print final skeleton to console
	print("\n----Final Result----")
	print("Goal\t\t: "+rai_net.goalString_orig)
	print("Final skeleton\t: ")

	actions=rai_world.splitStringStep(skeleton, list_old=[],verbose=0)
	for act in actions:
		print("\t\t  "+act)
	print("--------------------")
	print("")

def buildSkeleton(rai_net, cheat_terminal = False, cheat_goalstate=False,cheat_tree=False, showFinal=True, waitTime=0, cheat_feas=False, feasThresh=0.4, planOnly=False,
					infeasibleSkeletons=[], depthSkeletons=[], tries=0, verbose=True, newLGP=True, maxTimeOP=0):

	skeleton=""
	tmpskeleton=""
	typeDecision=[]
	tmpDes=[]
	depth=0

	K0=Config()
	K0.copy(rai_net.K)

	timeHP=0
	timeOP=0

	if tries>0:
		print("Next try: "+str(tries))

	successmsg="Failed to reach goal"

	if rai_net.lgp.isTerminal() or len(rai_net.preprocessGoals(check=True))==0:
		return skeleton, typeDecision, "Successfully reached goal", True

	while True:
		starttime=time.time()
		tmpDes=[]
		# Get encoded state
		envState=rai_net.encodeState()
		if cheat_goalstate or rai_net.numGoal_orig>2 or not rai_net.tray=="":
			# Get (possibly new) encoded objective
			goals_tmp, _, change=rai_net.preprocessGoalState(cheatGoalState=cheat_goalstate)
			# Get encoded input
			inputState=rai_net.encodeInput(envState, goalState=goals_tmp)
			if change and rai_net.setup=="minimal" and verbose:
				print("\tGoal changed to "+rai_net.goalString)
		else:
			# Get encoded input
			inputState=rai_net.encodeInput(envState)

		if not cheat_tree:
			# Get high-level action directly through policy
			outEncoded = rai_net.processPrediction(inputState)
			outDecoded = rai_net.decodeAction1(outEncoded)
		else:
			outDecoded=""
		if cheat_tree or skeleton + " " +outDecoded in infeasibleSkeletons+depthSkeletons or (outDecoded in infeasibleSkeletons+depthSkeletons and depth==0) or (outDecoded not in rai_net.lgp.getDecisions() and not rai_net.lgp.getDecisions() == []) or rai_net.checkPlaceSame(outDecoded):
			# if cheat_tree logically or skeleton labeled infeasible or invalid high-level action
			old=outDecoded
			infeasibleSke=[]
			depthSke=[]
			if depth==0:
				# Find high-level actions that lead to skeletons labeled infeasbile
				for tmpske in infeasibleSkeletons:
					tmpskeStep = rai_world.splitStringStep(tmpske, list_old=[])
					if len(tmpskeStep)==1:
						infeasibleSke.append(tmpskeStep[-1])
				for tmpske in depthSkeletons:
					tmpskeStep = rai_world.splitStringStep(tmpske, list_old=[])
					if len(tmpskeStep)==1:
						depthSke.append(tmpskeStep[-1])

			else:
				# Find high-level actions that lead to skeletons labeled infeasbile
				for tmpske in infeasibleSkeletons:
					tmpskeStep = rai_world.splitStringStep(tmpske, list_old=[])
					if skeleton == ' '.join(tmpskeStep[:-1]):
						infeasibleSke.append(tmpskeStep[-1])
				for tmpske in depthSkeletons:
					tmpskeStep = rai_world.splitStringStep(tmpske, list_old=[])
					if skeleton == ' '.join(tmpskeStep[:-1]):
						depthSke.append(tmpskeStep[-1])

			# Evaluate heuristic for all possible high-level actions
			outDecoded, prob = rai_net.evalPredictions(inputState, infeasible=infeasibleSke, maxdepth=depthSke, prevSke=outDecoded, depth=depth+1, tries=tries)
			if verbose:
				print("MP Decision", outDecoded, "\twith probability", prob)
				print("\tInstead of: ".expandtabs(4), old)
			tmpDes.append("MP")
			tmpDes.append(old)
			tmpDes.append(prob)
		else:
			if verbose:
				print("NN Decision", outDecoded)
			tmpDes.append("NN")

		endtime=time.time()

		timeHP=timeHP+endtime-starttime

		# Append to skeleton
		if skeleton=="":
			skeleton=outDecoded
		else:
			skeleton = skeleton + " " + outDecoded

		if tmpskeleton=="":
			tmpskeleton=outDecoded
		else:
			tmpskeleton = tmpskeleton + " " + outDecoded
		depth+=1

		# Walk to node
		rai_net.lgp.walkToRoot()
		rai_net.lgp.walkToNode(tmpskeleton,0)
		starttime=time.time()
		try:
			# Solve lgp
			komo = rai_world.runLGP(rai_net.lgp, BT.seq, verbose=0, view=False)
			if not planOnly:
				komo = rai_world.runLGP(rai_net.lgp, BT.seqPath, verbose=0, view=False)

		except:
			print("Can not solve komo path for skeleton:", skeleton)
			successmsg="KOMO path failed for goal"
			rai_net.lgp.walkToRoot()
			rai_net.K.copy(K0)
			break
		endtime=time.time()
		timeOP=timeOP+endtime-starttime

		# Determine seq and seqPath feasibility: Currently not used any further
		if rai_net.lgp.returnFeasible(BT.seq):
			tmpDes.append(1)
		else:
			tmpDes.append(0)

		if not planOnly:
			if rai_net.lgp.returnFeasible(BT.seqPath):
				tmpDes.append(1)
			else:
				tmpDes.append(0)
		else:
			tmpDes.append(-1)

		typeDecision.append(tmpDes)

		# Copy condiguration from komo solution
		if planOnly:
			komo.getKFromKomo(rai_net.K, komo.getPathFrames(rai_net.logicalNames).shape[0]-2)
		else:
			komo.getKFromKomo(rai_net.K, komo.getPathFrames(rai_net.logicalNames).shape[0]-1)

		if newLGP:
			if rai_net.restartLGP():
				tmpskeleton=""

		# Wait (for vid recording)
		if showFinal or rai_net.view:
			time.sleep(waitTime)

		# Stop if terminal
		if rai_net.lgp.isTerminal() or len(rai_net.preprocessGoals(check=True))==0:
			if showFinal:
				input("symbolic search finished")
			rai_net.K.copy(K0)
			if newLGP:
				rai_net.restartLGP()
				rai_net.lgp.walkToNode(skeleton,0)
			break
		# Stop if maximum depth reached
		if depth==rai_net.maxDepth:
			print("Maximum depth reached: "+str(rai_net.maxDepth))
			successmsg="Maximum depth of "+str(rai_net.maxDepth)+" reached for goal"
			rai_net.K.copy(K0)
			if newLGP:
				rai_net.restartLGP()
			break

	# Get feasible from final high-level action from seqPath optimization
	if not planOnly:
		feastmp = rai_net.lgp.returnFeasible(BT.seqPath)
	else:
		feastmp = False

	if skeleton=="":
		skeleton="(grasp pr2R obj0) (place pr2R obj0 obj1) (grasp pr2L obj2) (grasp pr2R obj1) (place pr2R obj1 obj2) (grasp pr2R obj3) (place pr2L obj2 obj3) (grasp pr2L obj4) (place pr2R obj3 obj4) (place pr2L obj4 obj5) (grasp pr2R obj6) (place pr2R obj6 obj7) (grasp pr2L obj5) (place pr2L obj5 obj6) (grasp pr2L obj7) (place pr2L obj7 tray) (grasp pr2R obj9) (place pr2R obj9 obj10) (grasp pr2R obj8) (place pr2R obj8 obj9) (grasp pr2R obj11) (place pr2R obj11 obj12) (grasp pr2R obj10) (place pr2R obj10 obj11) (grasp pr2R obj13) (place pr2R obj13 obj14) (grasp pr2L obj12) (place pr2L obj12 obj13) (grasp pr2L obj14) (place pr2L obj14 tray)"
		#skeleton="(grasp pr2R obj0) (place pr2R obj0 obj1) (grasp pr2L obj2) (grasp pr2R obj1) (place pr2R obj1 obj2) (place pr2L obj2 obj3) (grasp pr2L obj4) (place pr2L obj4 obj5) (grasp pr2L obj3) (place pr2L obj3 obj4) (grasp pr2L obj5) (place pr2L obj5 obj6) (grasp pr2L obj7) (place pr2L obj7 tray) (grasp pr2L obj6) (place pr2L obj6 obj7) (grasp pr2L obj9) (place pr2L obj9 obj10) (grasp pr2R obj8) (place pr2R obj8 obj9) (grasp pr2R obj11) (grasp pr2L obj10) (place pr2R obj11 obj12) (place pr2L obj10 obj11) (grasp pr2R obj13) (place pr2R obj13 obj14) (grasp pr2L obj12) (place pr2L obj12 obj13) (grasp pr2L obj14) (place pr2L obj14 tray)"

		rai_net.lgp.walkToRoot()
		rai_net.lgp.walkToNode(skeleton,0)

	if len(rai_net.preprocessGoals(check=True))>0:
		if verbose:
			print("--!! Goal not reached !!--")
		feastmp=False
	else:
		if verbose:
			print("\nSkeleton found. Show path and node info")
		successmsg="Successfully reached goal"
		if planOnly:
			# determine feasibility through seqPth optimization
			starttime=time.time()
			try:
				#if newLGP:
				#	for i in range(6):
				#		tmpnoise=0.01-i*0.002
				#		print("----- Noise for seq optimization "+str(tmpnoise)+" -----")
				#		tmptime=time.time()
				#		_ = rai_world.runLGP(rai_net.lgp, BT.seq, verbose=0, view=False, initnoise=tmpnoise)
				#		endtime=time.time()
				#		print("Constraint: seq ",rai_net.lgp.returnConstraint(BT.seq))
				#		print(str(endtime-tmptime)+" sec")
				#		if rai_net.lgp.returnFeasible(BT.seq):
				#			print("seq bound feasible")
				#			break
				#		else:
				#			print(str(i) + ": seq infeasible")

				#for i in range(11):
				#	tmpnoise=0.02-i*0.002
				#	print("----- Noise for seq optimization "+str(tmpnoise)+" -----")
				#	tmptime=time.time()
				#	_ = rai_world.runLGP(rai_net.lgp, BT.seqPath, verbose=0, view=showFinal, initnoise=tmpnoise)
				#	endtime=time.time()
				#	print("Constraint: seq ",rai_net.lgp.returnConstraint(BT.seq), ", seqPath ",rai_net.lgp.returnConstraint(BT.seqPath))
				#	print(str(endtime-tmptime)+" sec")
				#	feastmp = rai_net.lgp.returnFeasible(BT.seqPath)
				#	if feastmp:
				#		break
				#	else:
				#		print(str(i) + ": seqPath infeasible")

				for i in [0, -1, 1, -2, 2 , -3, 3, -4, 4, -5, 5]:
					tmpnoise=0.01+i*0.002
					if verbose:
						print("----- Noise for seq and seqPath optimization "+str(tmpnoise)+" -----")
					tmptime=time.time()
					#if newLGP:
					_ = rai_world.runLGP(rai_net.lgp, BT.seq, verbose=0, view=False, initnoise=tmpnoise)
					komo = rai_world.runLGP(rai_net.lgp, BT.seqPath, verbose=0, view=showFinal, initnoise=tmpnoise)
					endtime=time.time()
					if verbose:
						print("Constraint: seq ",rai_net.lgp.returnConstraint(BT.seq), ", seqPath ",rai_net.lgp.returnConstraint(BT.seqPath))
						print(str(endtime-tmptime)+" sec")
					feastmp = rai_net.lgp.returnFeasible(BT.seqPath)
					if feastmp:
						break
					else:
						print(str(i) + ": seqPath infeasible")

					if endtime-starttime>maxTimeOP:
						print("Optimzation time "+str(endtime-starttime)+ " > "+ str(maxTimeOP))
						break

					if i==0 and rai_net.lgp.returnConstraint(BT.seqPath)>3.5:
						break

					time.sleep(1)

			except:
				print("Can not solve komo for skeleton:", skeleton)
				rai_net.K.copy(K0)
				successmsg="KOMO failed for goal"
			endtime=time.time()
			if showFinal:
				print("\nTime HP", timeHP)
				print("Time OP next config", timeOP)
				print("Time OP full path",endtime-starttime)

	if showFinal and feastmp:
		rai_net.lgp.nodeInfo()
		komo.getKFromKomo(rai_net.K, komo.getPathFrames(rai_net.logicalNames).shape[0]-1)
		input("Results")

	rai_net.lgp.walkToRoot()
	rai_net.K.copy(K0)

	if not feastmp and verbose:
		print("--!! Infeasible Skeleton !!--")

	return skeleton, typeDecision, successmsg, feastmp

def main():
	import argparse
	parser = argparse.ArgumentParser()
	parser.add_argument('--rai_dir', type=str, default=dir_file)
	parser.add_argument('--verbose', type=int, default=1)
	parser.add_argument('--waitTime', type=float, default=0.0)

	parser.add_argument('--epochs_inst', type=int, default=500)
	parser.add_argument('--hlayers_inst', type=int, default=2)
	parser.add_argument('--hlayers_inst2', type=int, default=0)
	parser.add_argument('--size_inst', type=int, default=80)
	parser.add_argument('--epochs_grasp', type=int, default=1000)
	parser.add_argument('--hlayers_grasp', type=int, default=3)
	parser.add_argument('--size_grasp', type=int, default=80)
	parser.add_argument('--epochs_place', type=int, default=1000)
	parser.add_argument('--hlayers_place', type=int, default=3)
	parser.add_argument('--size_place', type=int, default=80)
	parser.add_argument('--num_batch_it', type=int, default=1)
	parser.add_argument('--batch_size', type=int, default=128)

	parser.add_argument('--lr', type=float, default=0.001)
	parser.add_argument('--lr_drop', type=float, default=1.0)
	parser.add_argument('--epoch_drop', type=int, default=100)
	parser.add_argument('--clipnorm', type=float, default=100.0)
	parser.add_argument('--val_split', type=float, default=0.2)
	parser.add_argument('--reg_l2', type=float, default=0.0001)
	parser.add_argument('--reg0_l2', type=float, default=0.00001)

	parser.add_argument('--train_only', dest='train_only', action='store_true')
	parser.set_defaults(train_only=False)
	parser.add_argument('--saveModel', dest='saveModel', action='store_true')
	parser.set_defaults(saveModel=False)
	parser.add_argument('--model_dir', type=str, default='20200221-152316')
	parser.add_argument('--model_dir_data', type=str, default='')

	parser.add_argument('--cheat_tree', dest='cheat_tree', action='store_true')
	parser.set_defaults(cheat_tree=False)
	parser.add_argument('--cheat_goalstate', dest='cheat_goalstate', action='store_true')
	parser.set_defaults(cheat_goalstate=False)
	parser.add_argument('--completeTesting', dest='completeTesting', action='store_true')
	parser.set_defaults(completeTesting=False)
	parser.add_argument('--allEnv', dest='allEnv', action='store_true')
	parser.set_defaults(allEnv=False)
	parser.add_argument('--showFinal', dest='showFinal', action='store_true')
	parser.set_defaults(showFinal=False)
	parser.add_argument('--viewConfig', dest='viewConfig', action='store_true')
	parser.set_defaults(viewConfig=False)
	parser.add_argument('--NoPlanOnly', dest='planOnly', action='store_false')
	parser.add_argument('--planOnly', dest='planOnly', action='store_true')
	parser.set_defaults(planOnly=True)
	parser.add_argument('--newLGP', dest='newLGP', action='store_true')
	parser.set_defaults(newLGP=False)
	parser.add_argument('--exclude', dest='exclude', action='store_true')
	parser.set_defaults(exclude=False)

	parser.add_argument('--goal', type=str, default="(on red green) (on green blue)")
	parser.add_argument('--env', type=int, default=1)
	parser.add_argument('--setup', type=str, default="minimal")
	parser.add_argument('--NNmode', type=str, default="FFnew")
	parser.add_argument('--datasetMode', type=int, default=1)
	parser.add_argument('--start', type=int, default=1)
	parser.add_argument('--startSub', type=int, default=1)
	parser.add_argument('--maxDepth', type=int, default=20)
	parser.add_argument('--maxTries', type=int, default=1)
	parser.add_argument('--maxTimeOP', type=float, default=0.0)

	parser.add_argument('--tray', type=str, default="")

	args = parser.parse_args()
	path_rai = args.rai_dir
	verbose=args.verbose
	waitTime= args.waitTime

	model_dir=args.model_dir # model_dir: timestamp of Policy directory or model_dir_data
	model_dir_data=args.model_dir_data # model_dir_data_ timestamp of data set
	if model_dir_data=="":
		model_dir_data=model_dir

	# Training parameters
	train_only = args.train_only #only trains model
	saveModel = args.saveModel #trains model

	# Instruction parameters
	epochs_inst=args.epochs_inst
	n_size_inst=args.size_inst
	n_layers_inst=args.hlayers_inst
	n_layers_inst2=args.hlayers_inst2 # LSTM layer

	# Grasp and Place parameters
	epochs_grasp=args.epochs_grasp
	n_size_grasp=args.size_grasp
	n_layers_grasp=args.hlayers_grasp
	epochs_place=args.epochs_place
	n_size_place=args.size_place
	n_layers_place=args.hlayers_place
	batch_size=args.batch_size

	# Learning parameters
	lr=args.lr
	lr_drop=args.lr_drop
	epoch_drop=args.epoch_drop
	clipnorm=args.clipnorm
	val_split=args.val_split
	reg=args.reg_l2
	reg0=args.reg0_l2 # LSTM layer

	nenv=args.env
	goalString=args.goal # objective if not (train_only or exclude)
	setup=args.setup
	NNmode=args.NNmode # minimal(impl1) FFnew(impl2) mixed10(impl3)
	dataMode=args.datasetMode # 1 5(global coord) 2 6(relative coord) 3 7(global coord+encoder) 4 8(relative coord+encoder) # 1-4 initial setup 1-5 modified setup

	# Testing parameters
	maxDepth=args.maxDepth # maximum depth before reattempting
	maxTries=args.maxTries # maximum tries
	maxTimeOP=args.maxTimeOP # maximum time for final path optimization
	tray=args.tray # Forces object to be placed on tray, if it is blocking

	cheat_goalstate= args.cheat_goalstate # adapts goal state if one goal formulation is satisfied
	cheat_tree=args.cheat_tree # always evaluate heuristic for all high-level actions

	completeTesting=args.completeTesting # Test all objectives
	allEnv=args.allEnv # Test a sequence of env
	showFinal=args.showFinal # Display final path
	viewConfig=args.viewConfig # enable K.view
	planOnly=args.planOnly # seq used for next config instead if seqPath
	exclude=args.exclude # Tests only objectives that are excluded in training set. Here: (on red table1)
	newLGP=args.newLGP # new LGP at intermediate node -> faster but objects can get shifted for some reason

	# train_only starts at objective
	start=args.start
	startSub=args.startSub
	start0=start

	if not dataMode in [1,2,3,4,5,6,7,8]:
		planOnly=False
		NotImplementedError

	if dataMode in [5,6,7,8]:
		#print("here")
		import new_experiment0 as expert
	elif dataMode in [1,2,3,4]:
		import minimal_experiment as expert

	# Objectives to exclude
	obg = [[],[]]#[[15], [10,20,30,39,48,53,58,63,68]]
	or1 = [[2], [11,12,13,14,15,16,17,18,19,20]]
	og2 = [[],[]]#[[8], [3,13,23,33,42,59,60,61,62,63]]

	#-------------------------------------------------------------------------------------------------------------------------
	print("Setting up basic Config and FOL for env: "+str(nenv))
	rai=rai_world.RaiWorld(path_rai, nenv, setup, goalString, verbose, maxDepth=maxDepth, NNmode=NNmode, datasetMode=dataMode, view=viewConfig, tray = tray)
	goalString=rai.goalString_orig
	print("\nModel and dataset")
	if saveModel or train_only:
		# Train model using data set from model_dir_data
		rai.saveFit(model_dir_data,epochs_inst, n_layers_inst, n_size_inst, epochs_grasp, n_layers_grasp, n_size_grasp, epochs_place, n_layers_place, n_size_place,
					lr, lr_drop, epoch_drop, clipnorm, val_split, reg, reg0, batch_size,n_layers_inst2=n_layers_inst2)
		print("Model trained: "+rai.rai_net.timestamp)
		model_dir=rai.model_dir
	else:
		# Load model from model_dir
		rai.loadFit(model_dir)
		print("Model loaded")

	if not train_only and not model_dir=="":
		if planOnly:
			append_test="_plan"
		else:
			append_test=""

		if completeTesting or exclude:
			# Select initial configurations to test
			if allEnv:
				if nenv in range(100,104):
					rangeEnv=range(nenv,104)
				elif nenv in range(106,109):
					rangeEnv=range(nenv,109)
				elif dataMode in [5,6,7,8]:
					rangeEnv=[4,8,12,16,20,24,28,32,36,40,44,48,52]
					rangeEnv=rangeEnv[rangeEnv.index(nenv-200):]
				else:
					rangeEnv=[29,38,46,56,64,73,82,91,
							32,39,48,57,65,75,83,93,
							100,101,102,103]#,
							#33,40,50,58,66,78,88,94,
							#35,42,51,59,68,80,89,97,
							#43,54,63,72,81,90]
					rangeEnv=rangeEnv[rangeEnv.index(nenv):]
			else:
				rangeEnv=range(nenv,nenv+1)

			for nenv in rangeEnv:
				summary=[[],[],[],[],[]] #optimal feasible infeasible-op infeasible no

				start=start0
				if dataMode in [5,6,7,8]:
					envadd=200
				else:
					envadd=0
				rai.nenv=nenv+envadd
				path=createResults(rai,cheat_tree=cheat_tree, cheat_goalstate=cheat_goalstate, start=start0, planOnly=planOnly)
				if 2*(start-1) < len(expert.Sets):
					# Test objectives consisting of 2 goal formulations twice - once for each sequence
					numGoal=start-1

					if not startSub==1:
						numGoal+=1
					for i in range(2*(start-1)+startSub-1,len(expert.Sets)):
						# For each objective id
						if i%2==0:
							numGoal+=1
							strgoal=str(numGoal).zfill(3)+"-1"
						else:
							strgoal=str(numGoal).zfill(3)+"-2"

						if exclude and not numGoal in or1[1]+og2[1]+obg[1]:
							#print("skip "+str(numGoal))
							continue

						# Get objective string
						goal=expert.Sets[i]

						# Init
						infeasibleSkeletons=[]
						depthSkeletons=[]
						skeleton=""

						# Reload configuration
						if dataMode in [5,6,7,8]:
							rai.redefine(goal, nenv=nenv+200)
						else:
							rai.redefine(goal, nenv=nenv)

						for tries in range(maxTries):
							# Set objective
							rai.resetFit(cheatGoalState=cheat_goalstate, goal=rai.goalString_orig)
							print("----Test Goal "+strgoal+": '"+rai.goalString_orig+"' for env "+str(rai.nenv)+"----\n")

							# Find skeleton
							skeleton, typeDecision,successmsg, feasible=buildSkeleton(rai, cheat_tree=cheat_tree, cheat_goalstate=cheat_goalstate, showFinal=showFinal, waitTime=waitTime, planOnly=planOnly,
																						infeasibleSkeletons=infeasibleSkeletons, depthSkeletons=depthSkeletons, tries=tries, newLGP=newLGP, maxTimeOP=maxTimeOP)

							if successmsg=="Maximum depth of "+str(rai.maxDepth)+" reached for goal":
								# If maximum depth reached: label all partial skeletons infeasible
								depthSkeletons= depthSkeletons + rai_world.splitStringPath(skeleton, list_old=[])
							elif not feasible:
								# If not feasible: label all partial skeletons infeasible
								infeasibleSkeletons= infeasibleSkeletons + rai_world.splitStringPath(skeleton, list_old=[])

							# Write results to txt file
							writeResults(rai,skeleton,typeDecision,successmsg,path,goalnumber_string=strgoal, planOnly=planOnly, feasible=feasible, tries=tries)

							if feasible or skeleton=="":
								break
						# Print results to console
						printResult(rai, skeleton)

						if i%2==0:
							# If first sequence checked
							idxsol=4
							skeletonPrev=skeleton
							strgoalPrev=strgoal
							if successmsg=="Successfully reached goal":
								# Determine whether optimal/feasible solution is found: 0 optimal, 1 feasible, 2 optimal but infeasible, 3 infeasible, 4 no solution
								solutions, _, _ = expert.getData(nenv=nenv, nset=numGoal)
								if not solutions ==[]:
									if not feasible:
										if len(rai_world.splitStringStep(solutions[0], list_old=[])) >= len(rai_world.splitStringStep(skeleton, list_old=[])):
											idxsol=2
										else:
											idxsol=3
									elif len(rai_world.splitStringStep(solutions[0], list_old=[])) >= len(rai_world.splitStringStep(skeleton, list_old=[])):
										idxsol=0
									else:
										idxsol=1

							else:
								summary[4].append(strgoal)
								idxsol=4
						else:
							# If second sequence checked
							# If same skeleton twice: both feasible if one is feasible
							# Assign to: optimal feasible infeasible-op infeasible no
							if skeleton == skeletonPrev:
								feasible = feasible or idxsol in [0,1]
								if feasible and idxsol in [2,3]:
									idxsol=idxsol-2
							elif not idxsol==4:
								summary[idxsol].append(strgoalPrev)

							if successmsg=="Successfully reached goal":
								solutions, _, _ = expert.getData(nenv=nenv, nset=numGoal)
								if not solutions ==[]:
									# Determine whether optimal/feasible solution is found: 0 optimal, 1 feasible, 2 optimal but infeasible, 3 infeasible, 4 no solution
									if not feasible:
										if len(rai_world.splitStringStep(solutions[0], list_old=[])) >= len(rai_world.splitStringStep(skeleton, list_old=[])):
											summary[2].append(strgoal)
										else:
											summary[3].append(strgoal)
									elif len(rai_world.splitStringStep(solutions[0], list_old=[])) >= len(rai_world.splitStringStep(skeleton, list_old=[])):
										summary[0].append(strgoal)
									else:
										summary[1].append(strgoal)

									if skeleton == skeletonPrev:
										summary[idxsol].append(strgoalPrev)
							else:
								summary[4].append(strgoal)

					start=0
				else:
					numGoal=start-1
					start=(start-1)-len(expert.Sets)/2

				for i in range(int(start),len(expert.test)):
					# Test sinlge goal formulation
					numGoal+=1
					if exclude and not i+1 in or1[0]+og2[0]+obg[0]:
						continue

					strgoal=str(numGoal).zfill(3)+"-1"

					# get goal string
					goal= expert.test[i]+" "+expert.test[i]
					infeasibleSkeletons=[]
					depthSkeletons=[]

					# Reload configuration
					if dataMode in [5,6,7,8]:
						rai.redefine(goal, nenv=nenv+200)
					else:
						rai.redefine(goal, nenv=nenv)

					for tries in range(maxTries):
						# Set objective
						rai.resetFit(cheatGoalState=cheat_goalstate, goal=rai.goalString_orig)
						print("----Test Goal "+strgoal+": '"+rai.goalString_orig+"' for env "+str(rai.nenv)+"----\n")

						skeleton, typeDecision,successmsg, feasible=buildSkeleton(rai,cheat_tree=cheat_tree, cheat_goalstate=cheat_goalstate, showFinal=showFinal,waitTime=waitTime, planOnly=planOnly,
																					infeasibleSkeletons=infeasibleSkeletons, depthSkeletons=depthSkeletons, tries=tries, newLGP=newLGP, maxTimeOP=maxTimeOP)
						if successmsg=="Maximum depth of "+str(rai.maxDepth)+" reached for goal":
							# If maximum depth reached: label all partial skeletons infeasible
							depthSkeletons= depthSkeletons + rai_world.splitStringPath(skeleton, list_old=[])
						elif not feasible:
							# If infeasible: label all partial skeletons infeasible
							infeasibleSkeletons= infeasibleSkeletons + rai_world.splitStringPath(skeleton, list_old=[])

						# Write results to txt file
						writeResults(rai,skeleton,typeDecision,successmsg,path, goalnumber_string=strgoal, planOnly=planOnly, feasible=feasible, tries=tries)
						if feasible:
							break
					# Print results to console
					printResult(rai, skeleton)

					# Assign to: optimal feasible infeasible-op infeasible no
					if successmsg=="Successfully reached goal":
						solutions, _, _ = expert.getData1(nenv=nenv, nset=i+1)
						if not solutions ==[]:
							# Determine whether optimal/feasible solution is found: 0 optimal, 1 feasible, 2 optimal but infeasible, 3 infeasible, 4 no solution
							if not feasible:
								if len(rai_world.splitStringStep(solutions[0], list_old=[])) >= len(rai_world.splitStringStep(skeleton, list_old=[])):
									summary[2].append(strgoal)
								else:
									summary[3].append(strgoal)
							elif len(rai_world.splitStringStep(solutions[0], list_old=[])) >= len(rai_world.splitStringStep(skeleton, list_old=[])):
								summary[0].append(strgoal)
							else:
								summary[1].append(strgoal)
					else:
						summary[4].append(strgoal)

				# Write summary
				with open(path+'/Summaryenv'+str(rai.nenv).zfill(3)+append_test+'.txt', 'a+') as f:
					f.write(rai.NNmode+", datamode "+str(rai.dataMode)+", maxDepth "+str(rai.maxDepth)+", maxTries "+str(maxTries)+"\n\n" )
					f.write("----Optimal Solution ("+str(len(summary[0]))+")----\n")
					for elem in summary[0]:
						f.write(elem+"\t")
					f.write("\n----Feasible Solution ("+str(len(summary[1]))+")----\n")
					for elem in summary[1]:
						f.write(elem+"\t")
					f.write("\n----Infeasible-op Solution ("+str(len(summary[2]))+")----\n")
					for elem in summary[2]:
						f.write(elem+"\t")
					f.write("\n----Infeasible Solution ("+str(len(summary[3]))+")----\n")
					for elem in summary[3]:
						f.write(elem+"\t")
					f.write("\n----No Solution ("+str(len(summary[4]))+")----\n")
					for elem in summary[4]:
						f.write(elem+"\t")
					f.write("\n")

		else:
			# Test single objective
			print("\nPredict: "+goalString)
			path=createResults(rai,cheat_tree=cheat_tree, cheat_goalstate=cheat_goalstate, start=start0, planOnly=planOnly, test=True)
			infeasibleSkeletons=[]
			depthSkeletons=[]
			teststep=1
			if showFinal or viewConfig:
				input("Press enter to continue")
				time.sleep(waitTime+1)

			starttime=time.time()
			for tries in range(maxTries):
				# Set objective
				rai.resetFit(cheatGoalState=cheat_goalstate, goal=goalString)
				skeleton,typeDecision,successmsg, feasible=buildSkeleton(rai, cheat_tree=cheat_tree, cheat_goalstate=cheat_goalstate, planOnly=planOnly, waitTime=waitTime,
																			infeasibleSkeletons=infeasibleSkeletons, depthSkeletons=depthSkeletons, verbose=verbose, showFinal=showFinal, newLGP=newLGP, maxTimeOP=maxTimeOP)

				if successmsg=="Maximum depth of "+str(rai.maxDepth)+" reached for goal":
					# If maximum depth reached: label all partial skeletons infeasible
					depthSkeletons= depthSkeletons + rai_world.splitStringPath(skeleton, list_old=[])
				elif not feasible:
					# If infeasible: label all partial skeletons infeasible
					infeasibleSkeletons= infeasibleSkeletons + rai_world.splitStringPath(skeleton, list_old=[])
				# Write results to txt file
				writeResults(rai,skeleton,typeDecision,successmsg,path,goalnumber_string="", planOnly=planOnly, feasible=feasible, tries=tries, test=True)
				if feasible:
					break
				teststep=teststep+1
			endtime=time.time()

			if not feasible:
				successmsg="Infeasible solution"
			print("time: "+str(endtime-starttime)+", tries: "+str(teststep)+", "+successmsg)

			# Print results to console
			printResult(rai, skeleton)

			if not feasible:
				print("Infeasible Solution")

			#if saveModel and successmsg=="Successfully reached goal":
			#	with open(path_rai+'/logs/toTest.txt', 'a+') as f:
			#		f.write(rai.model_dir+'\n')

	if not completeTesting and not train_only:
		input("Press Enter to end Program...")

if __name__ == "__main__":
    main()


import jinja2
from django import template
from django.template import TemplateDoesNotExist
from django.template.loader import render_to_string
from django_jinja import library

from ..models import get_section_name as get_section_name_base
from ..models import SECTION_TYPES

register = template.Library()

@library.global_function
@jinja2.contextfunction
def render_section(context, page_section):
    try:
        context = dict(context)
        context['section'] = page_section

        return render_to_string('sections/types/{}'.format(page_section.template), context)
    except TemplateDoesNotExist as e:
        import os
        from django.conf import settings

        if settings.DEBUG:
            os.system(f'touch {{ cookiecutter.package_name }}/apps/sections/templates/sections/types/{page_section.template}')

            return ''
        else:
            raise e

@library.global_function
@jinja2.contextfunction
def section_contains_image(context, section_obj):
    if not section_obj.content_left or not section_obj.content_right:
        return ''

    if any('<img' in s for s in[section_obj.content_left, section_obj.content_right]):
        return 'has-media'

    return ''

@register.inclusion_tag('admin/pages/page/type_modal.html')
def render_type_modal():
    return {
        'section_types': SECTION_TYPES
    }

@register.simple_tag
def get_section_name(obj):
    if isinstance(obj, tuple):
        return get_section_name_base(obj)

    # We have the section type as a string.
    for _, sections in SECTION_TYPES:
        for section in sections['sections']:
            if section[0] == obj:
                return get_section_name_base(section)


from django.db import models
from django.core.validators import MinValueValidator
from django.core.validators import MaxValueValidator
from datetime import date
from django.utils.translation import ugettext_lazy as _

class Quote(models.Model):
    """Model for a quote"""
    # TODO Add a carrier code reference to each quote
    # TODO Add a carrier code reference to each quote
    US_STATE = [
        ('AL', 'Alabama'),
        ('AK', 'Alaska'),
        ('AZ', 'Arizona'),
        ('AR', 'Arkansas'),
        ('CA', 'California'),
        ('CO', 'Colorado'),
        ('CT', 'Connecticut'),
        ('DE', 'Delaware'),
        ('DC', 'District of Columbia'),
        ('FL', 'Florida'),
        ('GA', 'Georgia'),
        # Hawaii not available
        # ('HI', 'Hawaii'),
        ('ID', 'Idaho'),
        ('IL', 'Illinois'),
        ('IN', 'Indiana'),
        ('IA', 'Iowa'),
        ('KS', 'Kansas'),
        ('KY', 'Kentucky'),
        ('LA', 'Louisiana'),
        ('ME', 'Maine'),
        ('MD', 'Maryland'),
        ('MA', 'Massachusetts'),
        ('MI', 'Michigan'),
        ('MN', 'Minnesota'),
        ('MS', 'Mississippi'),
        ('MO', 'Missouri'),
        ('MT', 'Montana'),
        ('NE', 'Nebraska'),
        ('NV', 'Nevada'),
        ('NH', 'New Hampshire'),
        ('NJ', 'New Jersey'),
        ('NM', 'New Mexico'),
        ('NY', 'New York'),
        ('NC', 'North Carolina'),
        ('ND', 'North Dakota'),
        ('OH', 'Ohio'),
        ('OK', 'Oklahoma'),
        ('OR', 'Oregon'),
        ('PA', 'Pennsylvania'),
        ('RI', 'Rhode Island'),
        ('SC', 'South Carolina'),
        ('SD', 'South Dakota'),
        ('TN', 'Tennessee'),
        ('TX', 'Texas'),
        ('UT', 'Utah'),
        ('VT', 'Vermont'),
        ('VA', 'Virginia'),
        ('WA', 'Washington'),
        ('WV', 'West Virginia'),
        ('WI', 'Wisconsin'),
        ('WY', 'Wyoming'),
    ]
    LOCATION_TYPE = [
        ('H','House'),
        ('A','Apt/Condo'),
        ('D','Dorm'),
        ('O','Office'),
        ('S','Storage'),
        ('M','Military'),
    ]
    MOVE_TYPE = [
        ('B', 'Individual boxes'),
        ('P', 'Fill a pod'),
    ]
    STATUS = [
        ('U', 'Unpaid'),
        ('P', 'Paid'),
    ]
    # reference_number begins as an empty value
    reference_number = models.CharField(max_length=22, blank=True, default=None)
    created_at = models.DateTimeField(auto_now_add=True, verbose_name='Created')
    updated_at = models.DateTimeField(auto_now=True, verbose_name='Last updated')
    quote_status = models.CharField(max_length=1, choices=STATUS, default='U')
    # Origin
    moving_from_address = models.CharField(max_length=50, blank=False, verbose_name='Where are you moving FROM?')
    moving_from_city = models.CharField(max_length=30, blank=False, verbose_name='City')
    moving_from_state = models.CharField(max_length=2, choices=US_STATE, blank=False, verbose_name='State')
    moving_from_zip = models.CharField(max_length=5, blank=False, verbose_name='Zip Code')
    moving_from_country = models.CharField(max_length=2, verbose_name='Country', default='US', editable=False)
    moving_from_location = models.CharField(max_length=1, choices=LOCATION_TYPE, blank=False, verbose_name='What type of location is this?')
    # Destination
    moving_to_address = models.CharField(max_length=50, blank=False, verbose_name='Where are you moving TO?')
    moving_to_city = models.CharField(max_length=30, blank=False, verbose_name='City')
    moving_to_state = models.CharField(max_length=2, choices=US_STATE, blank=False, verbose_name='State')
    moving_to_zip = models.CharField(max_length=5, blank=False, verbose_name='Zip Code')
    moving_to_country = models.CharField(max_length=2, verbose_name='Country', default='US', editable=False)
    moving_to_location = models.CharField(max_length=1, choices=LOCATION_TYPE, blank=False, verbose_name='What type of location is this?')
    # Other information
    saturday_pick_up = models.BooleanField(default=False)
    saturday_delivery = models.BooleanField(default=False)
    appointment_pick_up = models.BooleanField(default=False)
    appointment_delivery = models.BooleanField(default=False)
    inside_pick_up = models.BooleanField(default=False)
    inside_delivery = models.BooleanField(default=False)
    extended_loading_pick_up = models.BooleanField(default=True)
    extended_loading_delivery = models.BooleanField(default=False)
    carrier_insurance = models.BooleanField(default=True, editable=False)
    extended_insurance = models.BooleanField(default=False, editable=False)
    expiration_date = models.DateTimeField(auto_now_add=True)
    total_pieces = models.IntegerField(blank=True, default=0)
    total_gross_weight = models.IntegerField(validators=[MaxValueValidator(10000)], blank=True, default=0)
    total_cubic_feet = models.IntegerField(blank=True, default=0)
    total_shipment_value = models.IntegerField(validators=[MaxValueValidator(10000)], blank=True, default=0)
    density = models.FloatField(blank=True, default=0)
    freight_class = models.FloatField(blank=True, default=0)
    # Empty until API response from carrier is received
    origin_station = models.CharField(max_length=3, blank=True, default='N/A')
    destitation_station = models.CharField(max_length=3, blank=True, default='N/A')

    class Meta:
        verbose_name = _("Quote")
        verbose_name_plural = _("Quotes")

    # Add custom values to quote by adjusting the save method
    def save(self, *args, **kwargs):
        if self.pk is None:
            def increment_reference_number():
                # Generate the 2nd and 3rd part of the quote reference
                today = date.today()
                date_ref = today.strftime('%y%m%d')
                last_quote = Quote.objects.all().order_by('id').last()
                if not last_quote:
                    new_quote_ref = str(date_ref) + '-' + '00000000'
                else:
                    quote_ref = last_quote.reference_number
                    quote_ref_int = int(quote_ref.split('-')[-1])
                    new_quote_int = quote_ref_int + 1
                    new_quote_ref = date_ref + '-' + str(new_quote_int).zfill(8)
                    return new_quote_ref
            new_quote_ref = increment_reference_number()
            self.reference_number = new_quote_ref

        else:
            pass

        super().save(*args, **kwargs)

    def update_total_pieces(self, *args, **kwargs):
        if self.total_pieces == 0:
            quote_id = self.id
            this_quote = Quote.objects.get(quote_id=quote_id)
            pieces = this_quote.piece_quote_set.all()
            counted_pieces = 0
            for piece in pieces.all():
                counted_pieces += 1
            self.total_pieces = counted_pieces

        else:
            pass

        super().save(*args, **kwargs)

    def __str__(self):
        return self.reference_number

class Carrier(models.Model):
    """Model for a carrier"""
    # TODO Decide on max_weight_per_piece/shipment, max_cubic_feet_per_piece/shipment
    # TODO Check if insurance_rate/insurance_min comes through the API
    #quote = models.ForeignKey(Quote)#, on_delete=models.CASCADE)
    name = models.CharField(max_length=30, blank=False, unique=True, verbose_name='Carrier Name')
    code = models.CharField(max_length=3, blank=False, unique=True, verbose_name='Carrier Code')
    contact_name = models.CharField(max_length=30, blank=False, verbose_name='Contact Name')
    contact_email = models.EmailField(max_length=30, blank=False, unique=False, verbose_name='Contact Email')
    insurance_doc = models.FileField(upload_to='carrier_docs/', verbose_name='Carrier Insurance Document')

class Piece(models.Model):
    """Model for a piece"""
    quote = models.ForeignKey('Quote', related_name='piece_quote_set', on_delete=models.CASCADE)
    length = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(125)], blank=False, default=0)
    width = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(88)], blank=False, default=0)
    height = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(96)], blank=False, default=0)
    weight = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(500)], blank=False, default=0)
    value = models.IntegerField(validators=[MinValueValidator(1), MaxValueValidator(2500)], blank=False, default=0)

    class Meta:
        verbose_name = _("Piece")
        verbose_name_plural = _("Pieces")


# coding=utf-8
from collections import ChainMap

if __name__ == '__main__':
    """Lookups search the underlying mappings successively until a key is found.
    In contrast, writes, updates, and deletions only operate on the first
    mapping.
    """
    a = {'a': 'A', 'c': 'C'}
    b = {'b': 'B', 'c': 'D'}
    m = ChainMap(a, b)
    for k, v in m.items():
        print('{} = {}'.format(k, v))


# -*- coding:utf-8 -*-
from django.conf.urls import patterns, url

urlpatterns = patterns('clients.views',

    url(r'^list$', 'home', name='client_list'),

    url(r'^mod/', 'get_modal', name='clients_get_modal'),

    url(r'^s/', 'clients_filter', name='search_clients_link'),

    url(r'^do', 'client_do', name='clients_do'),

    url(r'^client(?P<id>\d+)$', 'client_info', name='clients_info_link'),

    url(r'^genconf$', 'genconfig', name='clients_gencofig_link')
)


#!/usr/bin/python3
# -*- coding: utf-8 -*-

from flask import Flask
from flask import request
import json
from db.mongo_pool import MongoPool
import settings

class ProxyApi(object):
    def __init__(self):
        # 初始一个Flask的Web服务
        self.app = Flask(__name__)
        self.proxy_pool = MongoPool()

        @self.app.route('/random')
        def random():
            # 从传入参数中获取URL
            # 根据protocol参数获取协议
            protocol = request.args.get('protocol')
            # 根据domain参数获取域名
            domain = request.args.get('domain')

            proxy = self.proxy_pool.random(protocol=protocol, domain=domain, count=settings.AVAILABLE_IP_COUNT)

            # 如果有协议, 就返回带有协议代理IP和端口号
            if protocol:
                return '{}://{}:{}'.format(protocol, proxy.ip, proxy.port)
            else:
                # 如果没有协议就返回, 不带协议的IP和端口号
                return '{}:{}'.format(proxy.ip, proxy.port)

        @self.app.route('/proxies')
        def proxies():
            # 根据protocol参数获取协议
            protocol = request.args.get('protocol')
            # 根据domain参数获取域名
            domain = request.args.get('domain')

            proxies = self.proxy_pool.get_proxies(protocol=protocol, domain=domain, count=settings.AVAILABLE_IP_COUNT)
            lis = []
            for proxy in proxies:
                lis.append(proxy.__dict__)
            return json.dumps(lis)

        @self.app.route('/disable_domain')
        def disable_domain():
            # 获取IP地址
            ip = request.args.get('ip')
            # 获取不可用域名
            domain = request.args.get('domain')
            if ip is None:
                return '请传入ip参数'
            if domain is None:
                return '请传入domain参数'

            # 更新域名成功
            self.proxy_pool.disable_domain(ip=ip, domain=domain)
            return '该IP添加不可用域名成功'

    def run(self):
        self.app.run(host="0.0.0.0", port=6868)

    @classmethod
    def start(cls):
        proxy_api = cls()
        proxy_api.run()

if __name__ == '__main__':
    ProxyApi.start()


"""empty message

Revision ID: f412434b3ca6
Revises: d24eddc5e40d
Create Date: 2017-07-04 14:36:27.792045

"""

# revision identifiers, used by Alembic.
revision = 'f412434b3ca6'
down_revision = 'd24eddc5e40d'

from alembic import op
import sqlalchemy as sa

def upgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.add_column('activity', sa.Column('user_id', sa.Integer(), nullable=True))
    op.create_foreign_key(None, 'activity', 'users', ['user_id'], ['id'])
    op.add_column('assignment', sa.Column('public', sa.String(length=128), nullable=True))
    op.add_column('assignment', sa.Column('user_id', sa.Integer(), nullable=True))
    op.create_foreign_key(None, 'assignment', 'users', ['user_id'], ['id'])
    op.add_column('basics', sa.Column('public', sa.String(length=128), nullable=True))
    op.add_column('basics', sa.Column('user_id', sa.Integer(), nullable=True))
    op.create_foreign_key(None, 'basics', 'users', ['user_id'], ['id'])
    op.add_column('collection', sa.Column('order', sa.String(length=100), nullable=True))
    op.add_column('collection', sa.Column('public', sa.String(length=128), nullable=True))
    op.add_column('collection', sa.Column('target_id', sa.Integer(), nullable=True))
    op.add_column('collection', sa.Column('target_table', sa.String(length=200), nullable=True))
    op.add_column('policy', sa.Column('user_id', sa.Integer(), nullable=True))
    op.create_foreign_key(None, 'policy', 'users', ['user_id'], ['id'])
    op.add_column('reading', sa.Column('public', sa.String(length=128), nullable=True))
    op.add_column('reading', sa.Column('user_id', sa.Integer(), nullable=True))
    op.create_foreign_key(None, 'reading', 'users', ['user_id'], ['id'])
    ### end Alembic commands ###

def downgrade():
    ### commands auto generated by Alembic - please adjust! ###
    op.drop_constraint(None, 'reading', type_='foreignkey')
    op.drop_column('reading', 'user_id')
    op.drop_column('reading', 'public')
    op.drop_constraint(None, 'policy', type_='foreignkey')
    op.drop_column('policy', 'user_id')
    op.drop_column('collection', 'target_table')
    op.drop_column('collection', 'target_id')
    op.drop_column('collection', 'public')
    op.drop_column('collection', 'order')
    op.drop_constraint(None, 'basics', type_='foreignkey')
    op.drop_column('basics', 'user_id')
    op.drop_column('basics', 'public')
    op.drop_constraint(None, 'assignment', type_='foreignkey')
    op.drop_column('assignment', 'user_id')
    op.drop_column('assignment', 'public')
    op.drop_constraint(None, 'activity', type_='foreignkey')
    op.drop_column('activity', 'user_id')
    ### end Alembic commands ###


import requests
from bs4 import BeautifulSoup

if __name__ == '__main__':
    server = 'http://www.748219.com/meiwen/'
    target = 'http://www.748219.com/meiwen/13625.html'
    req = requests.get(url=target)
    req.encoding = req.apparent_encoding
    html = req.text
    bf = BeautifulSoup(html)
    # print(bf)
    # texts = bf.find_all('div', class_='article')  # 筛选出正文，class属性是article
    texts = bf.find_all('div', class_='box')
    a_bf = BeautifulSoup(str(texts))
    li = a_bf.find_all('li')
    lli = BeautifulSoup(str(li))
    a = lli.find_all('a')
    # print(a)
    # print(texts)
    # texts = bf.find_all('span', class_='next')
    # print(texts)
    # a_df = BeautifulSoup(str(texts[0]))
    # print(a_df)
    # a = bf.find_all('a')
    for each in a:
        # print(each)
        print(each.string, each.get('href'))


from flask import Flask, render_template, request, session
from datetime import datetime
import random

app = Flask(__name__)
app.secret_key = 'noble'

@app.route('/', methods=['get','post'])
def index():
    session['state'] = None
    session['time'] = datetime.now()
    session['gold'] = 0
    session['addgold'] = 0
    session['building']= None
    if "all" not in session:
        session['all']= []
    return render_template('index.html')

@app.route('/process_money', methods=['POST'])
def result():
    if request.form['building'] == 'farm':
        session['addgold'] = random.randint(10,20)
        session['gold'] += session['addgold']
        session['building'] = 'farm'
        message= "You entered the session['building'] and won session['addgold'] gold pieces on session['time']"
        session["all"].append(message)
    elif request.form['building'] == 'cave':
        session['addgold'] = random.randint(5,10)
        session['gold'] += session['addgold']
        session['building'] = 'cave'
        message= "You entered the session['building'] and won session['addgold'] gold pieces on session['time']"
        session["all"].append(message)
    elif request.form['building'] == 'house':
        session['addgold'] = random.randint(2,5)
        session['gold'] += session['addgold']
        session['building'] = 'house'
        message= "You entered the session['building'] and won session['addgold'] gold pieces on session['time']"
        session["all"].append(message)
    elif request.form['building'] == 'casino':
        session['addgold'] = random.randint(-50,50)
        session['gold'] += session['addgold']
        session['building'] = 'casino'
        message= "You entered the session['building'] and won session['addgold'] gold pieces on session['time']"
        session["all"].append(message)
    return render_template('index.html')

app.run(debug=True)

"""
from flask import Flask, render_template, request, session
app = Flask(__name__)
app.secret_key = 'ThisIsSecret'

@app.route('/')
def index():
    return render_template('enterSomething.html')

@app.route('/result', methods=['POST'])
def result():
    vehicle = request.form.get('vehicle')
    year = request.form.get('year')
    firstname = request.form.get("firstname")
    lastname = request.form.get("lastname")
    return render_template('results.html', vehicle=vehicle, year=year, firstname=firstname, lastname=lastname)

app.run(debug=True)
"""


''' A sprint is a collection of tasks for accomplishing part of a sub goal
    in a given amount of time.'''

import datetime
import logging
import math

from .base_element import BaseElement
from .task import compare_tasks

def sequence_evenly(duration, tasks):
    ''' Sequence the tasks evenly about the duration of the sequence.'''
    assert len(tasks) > 0, 'Must be given tasks'
    sorted_tasks = sorted(tasks, cmp=compare_tasks)
    num_days = (duration[1] - duration[0]).days
    num_tasks = len(sorted_tasks)
    tasks_per_day = math.ceil(num_days / float(num_tasks))
    sequence = []

    current = 0
    day_offest = 0
    while current < num_tasks:
        if  num_tasks < current + tasks_per_day:
            sequence.append(((duration[0] + datetime.timedelta(day_offest)),
                             sorted_tasks[current:]))
            break
        else:
            sequence.append(((duration[0] + datetime.timedelta(day_offest)),
                             sorted_tasks[current: current + tasks_per_day]))
    return sequence

def from_dict(entry):
    ''' Create a new sprint object from a database entry for that object'''
    return Sprint(entry['name'],
                  entry['description'],
                  entry['tasks'],
                  start=entry['start'],
                  end=entry['end'],
                  id=entry['_id'],
                  before=entry['before'],
                  extensions=entry['extensions'])

class Sprint(BaseElement):
    ''' A Sprint class representation'''

    def __init__(self, name, description, tasks, start=None, end=None, id=None, before=None, extensions=None):
        ''' Initialize this sprint with the given tasks
            Args:
                tasks - The list of tasks to sequence in this sprint.
                start - The start date of the sprint
                end   - The end date of the sprint
                The sprint will be sequenced evenly across the duration of the sprint.
                If start and stop are unspecified, today will be assumed with the duration
                of one week.'''
        super().__init__('sprint', name, description, id=id, before=before, extensions=extensions)
        self._tasks = tasks
        self._start = datetime.datetime.now() if start is None else start
        self._end = self._start + datetime.timedelta(7, 0) if end is None else end

        assert self._start < self._end, 'Start date must be before end date.'
        assert (self._end - self._start).days >= 1, 'Sprint must be at least 2 day long.'
        logging.debug('Initialized task %s with %s -- %s', self.name, self._start, self._end)

    def sequence(self, sequencing_strategy=sequence_evenly):
        ''' Create a sequencing for the tasks in this sprint.
            Args:
                sequencing_strategy - How to make a sequence.'''
        return sequencing_strategy(self.duration, self._tasks)

    def as_post(self):
        base = super().as_post()
        base['tasks'] = self.tasks
        base['start'] = self._start
        base['end'] = self._end
        return base

    @property
    def duration(self):
        ''' Get the duration of this sprint.'''
        return (self._start, self._end)


import requests
import urllib.request
import time
from bs4 import BeautifulSoup
import os

def Navigate(url):
    if url!="Fin du Manga":
        response = requests.get(url)
        soup = BeautifulSoup(response.text, "html.parser")
        ListeLiens= Trouve_les_liens_stp(soup)
    return [soup,ListeLiens]

def Trouve_les_liens_stp(soup):
    ListeLiens = []
    images = soup.findAll('img')
    for lien in images:
        if 'class' in lien.attrs:
            if lien['class']==['img-responsive']:
                a= lien['data-src']
                ListeLiens.append(a)
    return ListeLiens

def Next(soup,numero,url):
    NextUrl=""
    moit="https://www.lelscan-vf.com/manga/"
    def urli(numero,url):
        numero= url.split('/')[-1]
        numero=int(numero)
        numero=numero+1
        return numero
    if Trouve_les_liens_stp(soup)==[]:
        NextUrl="Fin du Manga"
        print("Fin du Manga")
    else:
        moit="https://www.lelscan-vf.com/manga/"
        ake=url.split(moit)[1]
        oaa=ake.split('/')[0]
        numero=urli(numero,url)
        NextUrl= moit+oaa+"/"+str(numero)
        print(moit+oaa+"/"+str(numero-1))
    return [NextUrl,numero]


#通过对象和数组的组合表示数据，轻量级

# 1 对象 和 数组
# 2 读取
import json
"""
str='''
[{
    "name":"Bob",
    "gender":"male",
    "birthday":"1994-09-09"
},{
    "name":"Selina",
    "gender":"female",
    "birthday":"1995-09-29"
}]
'''

"""
"""
print(type(str))
data = json.loads(str)
print(data,type(data))
print(data[0],data[0].get('name'),data[0].get('age',25))
"""
# 读取 转化 显示

with open('data.json','r') as file:
    sss = file.read()
    data = json.loads(sss)
    print(data)

# 输出JSON
"""
data='''
[{
    "name":"Bob",
    "gender":"male",
    "birthday":"1994-09-09"
},{
    "name":"Selina",
    "gender":"female",
    "birthday":"1995-09-29"
}]
'''
with open('data.json','w') as file:
    file.write(json.dumps(data,indent=2))#首行缩进2字符
    #如包含中文，会自动转化为Unicode字符格式
"""


from django.core.exceptions import PermissionDenied
from django.shortcuts import get_object_or_404
from django.views.generic.base import View
from stickable.models import User, Task
from utils.response import json_response
from django.utils.decorators import method_decorator
from django.views.decorators.csrf import csrf_exempt

class ApiView(View):

    request = None

    class Meta:
        abstract = True

    @method_decorator(csrf_exempt)
    def dispatch(self, request, *args, **kwargs):
        self.request = request
        return super(ApiView, self).dispatch(request, *args, **kwargs)

    def _error(self, message):
        data = {
            'error': True,
            'message': message
        }
        return json_response(data)

    def _success(self):
        data = {
            'error': False,
            'success': True
        }
        return json_response(data)

    def _get_user(self, username, require_auth=True):
        user = get_object_or_404(User, username=username)
        if require_auth:
            if not self.request.user.is_authenticated:
                raise PermissionDenied
            if self.request.user.id != user.id:
                raise PermissionDenied

        return user

    def _get_task(self, id):
        task = get_object_or_404(Task, id=id)
        return task


from django.conf.urls import patterns, url
from cars.views import *

urlpatterns = patterns('',
    url(r'^$', home, name = 'home'),
    url(r'^search/price/(?P<price_low>[0-9]{4,5})/(?P<price_high>[0-9]{4,5})/$', shop_by_price, name = 'shop_by_price'),
    url(r'^search/make/(?P<make>\w+)/$', shop_by_make, name = 'shop_by_make'),
    url(r'^search/year/(?P<year>[0-9]{4})/$', shop_by_year, name = 'shop_by_year'),
    url(r'^all/$', view_all, name = 'view_all'),
    url(r'^sold/$', view_sold, name = 'view_sold'),
    url(r'^details/(?P<car_id>\d+)/$', car_details, name = 'car_details'),
)


# -*- coding: utf-8 -*-
"""Copyright 2019 DScribe developers

Licensed under the Apache License, Version 2.0 (the "License");
you may not use this file except in compliance with the License.
You may obtain a copy of the License at

    http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software
distributed under the License is distributed on an "AS IS" BASIS,
WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
See the License for the specific language governing permissions and
limitations under the License.
"""
from abc import ABC, abstractmethod

import numpy as np

from scipy.sparse import coo_matrix

from ase import Atoms
from dscribe.core.system import System
from dscribe.utils.species import get_atomic_numbers

try:
    from joblib import Parallel, delayed
except ImportError:
    # Change implemented for TFYA92: if joblib is not installed,
    # use trivial "emulation" of Parallel by simply executing everything in sequence.
    def Parallel(n_jobs=None, backend=None, verbose=0, timeout=None, pre_dispatch='2 * n_jobs', batch_size='auto', temp_folder=None, max_nbytes='1M', mmap_mode='r', prefer=None, require=None):
        def eval(iterator):
            return list(iterator)
        return eval
    def delayed(arg):
        return arg

class Descriptor(ABC):
    """An abstract base class for all descriptors.
    """

    def __init__(self, periodic, flatten, sparse):
        """
        Args:
            flatten (bool): Whether the output of create() should be flattened
                to a 1D array.
        """
        self.sparse = sparse
        self.flatten = flatten
        self.periodic = periodic
        self._atomic_numbers = None
        self._atomic_number_set = None
        self._species = None

    @abstractmethod
    def create(self, system, *args, **kwargs):
        """Creates the descriptor for the given systems.

        Args:
            system (ase.Atoms): The system for which to create the descriptor.
            args: Descriptor specific positional arguments.
            kwargs: Descriptor specific keyword arguments.

        Returns:
            np.array | scipy.sparse.coo_matrix: A descriptor for the system.
        """

    @abstractmethod
    def get_number_of_features(self):
        """Used to inquire the final number of features that this descriptor
        will have.

        Returns:
            int: Number of features for this descriptor.
        """

    def get_system(self, system):
        """Used to convert the given atomic system into a custom System-object
        that is used internally. The System class inherits from ase.Atoms, but
        includes built-in caching for geometric quantities that may be re-used
        by the descriptors.

        Args:
            system (:class:`ase.Atoms` | :class:`.System`): Input system.

        Returns:
            :class:`.System`: The given system transformed into a corresponding
                System-object.
        """
        if isinstance(system, Atoms):
            if type(system) == System:
                return system
            else:
                return System.from_atoms(system)
        else:
            raise ValueError(
                "Invalid system with type: '{}'.".format(type(system))
            )

    @property
    def sparse(self):
        return self._sparse

    @sparse.setter
    def sparse(self, value):
        """Sets whether the output should be sparse or not.

        Args:
            value(float): Should the output be in sparse format.
        """
        self._sparse = value

    @property
    def periodic(self):
        return self._periodic

    @periodic.setter
    def periodic(self, value):
        """Sets whether the inputs should be considered periodic or not.

        Args:
            value(float): Are the systems periodic.
        """
        self._periodic = value

    @property
    def flatten(self):
        return self._flatten

    @flatten.setter
    def flatten(self, value):
        """Sets whether the output should be flattened or not.

        Args:
            value(float): Should the output be flattened.
        """
        self._flatten = value

    def _set_species(self, species):
        """Used to setup the species information for this descriptor. This
        information includes an ordered list of unique atomic numbers, a set
        of atomic numbers and the original variable contents.

        Args:
            species(iterable): Chemical species either as a list of atomic
                numbers or list of chemical symbols.
        """
        # The species are stored as atomic numbers for internal use.
        atomic_numbers = get_atomic_numbers(species)
        self._atomic_numbers = atomic_numbers
        self._atomic_number_set = set(self._atomic_numbers)
        self._species = species

    def check_atomic_numbers(self, atomic_numbers):
        """Used to check that the given atomic numbers have been defined for
        this descriptor.

        Args:
            species(iterable): Atomic numbers to check.

        Raises:
            ValueError: If the atomic numbers in the given system are not
            included in the species given to this descriptor.
        """
        # Check that the system does not have elements that are not in the list
        # of atomic numbers
        zs = set(atomic_numbers)
        if not zs.issubset(self._atomic_number_set):
            raise ValueError(
                "The following atomic numbers are not defined "
                "for this descriptor: {}"
                .format(zs.difference(self._atomic_number_set))
            )

    def create_parallel(self, inp, func, n_jobs, output_sizes=None, verbose=False, prefer="processes"):
        """Used to parallelize the descriptor creation across multiple systems.

        Args:
            inp(list): Contains a tuple of input arguments for each processed
                system. These arguments are fed to the function specified by
                "func".
            func(function): Function that outputs the descriptor when given
                input arguments from "inp".
            n_jobs (int): Number of parallel jobs to instantiate. Parallellizes
                the calculation across samples. Defaults to serial calculation
                with n_jobs=1.
            output_sizes(list of ints): The size of the output for each job.
                Makes the creation faster by preallocating the correct amount of
                memory beforehand. If not specified, a dynamically created list of
                outputs is used.
            verbose(bool): Controls whether to print the progress of each job
                into to the console.
            backend (str): The parallelization method. Valid options are:

                - "processes": Parallelization based on processes. Uses the
                  "loky" backend in joblib to serialize the jobs and run them
                  in separate processes. Using separate processes has a bigger
                  memory and initialization overhead than threads, but may
                  provide better scalability if perfomance is limited by the
                  Global Interpreter Lock (GIL).

                - "threads": Parallelization based on threads. Has bery low
                  memory and initialization overhead. Performance is limited by
                  the amount of pure python code that needs to run. Ideal when
                  most of the calculation time is used by C/C++ extensions that
                  release the GIL.

        Returns:
            np.ndarray | scipy.sparse.csr_matrix | list: The descriptor output
            for each given input. The return type depends on the desciptor
            setup.
        """
        # Split data into n_jobs (almost) equal jobs
        n_samples = len(inp)
        n_features = self.get_number_of_features()
        is_sparse = self._sparse
        k, m = divmod(n_samples, n_jobs)
        jobs = (inp[i * k + min(i, m):(i + 1) * k + min(i + 1, m)] for i in range(n_jobs))

        # Calculate the result in parallel with joblib
        if output_sizes is None:
            output_sizes = n_jobs*[None]
            static_size = False
        else:
            static_size = True

        def create_multiple(arguments, func, is_sparse, n_features, n_desc, index, verbose):
            """This is the function that is called by each job but with
            different parts of the data.
            """
            # Initialize output
            if n_desc is None:
                results = []
            else:
                if is_sparse:
                    data = []
                    rows = []
                    cols = []
                else:
                    results = np.empty((n_desc, n_features), dtype=np.float32)

            offset = 0
            i_sample = 0
            old_percent = 0
            n_samples = len(arguments)

            for i_sample, i_arg in enumerate(arguments):
                i_out = func(*i_arg)

                if n_desc is None:
                    results.append(i_out)
                else:
                    if is_sparse:
                        data.append(i_out.data)
                        rows.append(i_out.row + offset)
                        cols.append(i_out.col)
                    else:
                        results[offset:offset+i_out.shape[0], :] = i_out
                    offset += i_out.shape[0]

                if verbose:
                    current_percent = (i_sample+1)/n_samples*100
                    if current_percent >= old_percent + 1:
                        old_percent = current_percent
                        print("Process {0}: {1:.1f} %".format(index, current_percent))

            if n_desc is not None and is_sparse:
                data = np.concatenate(data)
                rows = np.concatenate(rows)
                cols = np.concatenate(cols)
                results = coo_matrix((data, (rows, cols)), shape=[n_desc, n_features], dtype=np.float32)

            return (results, index)

        vec_lists = Parallel(n_jobs=n_jobs, prefer=prefer)(delayed(create_multiple)(i_args, func, is_sparse, n_features, n_desc, index, verbose) for index, (i_args, n_desc) in enumerate(zip(jobs, output_sizes)))

        # Restore the caluclation order. If using the threading backend, the
        # input order may have been lost.
        vec_lists.sort(key=lambda x: x[1])

        # Remove the job index
        vec_lists = [x[0] for x in vec_lists]

        if static_size is True:
            if self._sparse:
                row_offset = 0
                data = []
                cols = []
                rows = []
                n_descs = 0
                for i, i_res in enumerate(vec_lists):
                    n_descs += i_res.shape[0]
                    i_res = i_res.tocoo()
                    i_n_desc = i_res.shape[0]
                    i_data = i_res.data
                    i_col = i_res.col
                    i_row = i_res.row

                    data.append(i_data)
                    rows.append(i_row + row_offset)
                    cols.append(i_col)

                    # Increase the row offset
                    row_offset += i_n_desc

                # Saves the descriptors as a sparse matrix
                data = np.concatenate(data)
                rows = np.concatenate(rows)
                cols = np.concatenate(cols)
                results = coo_matrix((data, (rows, cols)), shape=[n_descs, n_features], dtype=np.float32)

                # The final output is transformed into CSR form which is faster for
                # linear algebra
                results = results.tocsr()
            else:
                results = np.concatenate(vec_lists, axis=0)
        else:
            results = []
            for part in vec_lists:
                results.extend(part)

        return results

    def _check_system_list(self, lst):

        def iterable(obj):
            try:
                iter(obj)
            except Exception:
                return False
            else:
                return True
        if iterable(lst):
            self.get_system(lst[0])
        else:
           raise ValueError("Input is neither System, nor ase.Atoms object nor is it iterable")
        return


from django.conf.urls import url
from .views import CartView, ItemCountView, CheckoutView, CheckoutFinalView, CheckOutApiView

urlpatterns = [
    url(r'^count$',  ItemCountView.as_view(), name='item_count'),
    url(r'^checkout$',  CheckoutView.as_view(), name='checkout'),
    url(r'^checkout/final$',  CheckoutFinalView.as_view(), name='final'),
    url(r'^api/checkout$',  CheckOutApiView.as_view(), name='api_checkout'),
    url(r'^$',  CartView.as_view(), name='main')
]