コード例 #1
0
ファイル: test_user.py プロジェクト: s3609685/prove-math
def test_unlearn_node():
	mo = User({'type': 'google', 'id': 'xPr' })
	mo.learn_node('vertex')
	assert 'vertex' in mo.dict['learned_node_ids']
	mo.unlearn_node('vertex')
	assert 'vertex' not in mo.dict['learned_node_ids']
コード例 #2
0
ファイル: main.py プロジェクト: s3609685/prove-math
class SocketHandler (WebSocketHandler):


	def __init__(self, application, request, **kwargs):
		WebSocketHandler.__init__(self, application, request, **kwargs)
		self.user = None

	def jsend(self, dic):
		if self.user:
			user_identifier = self.user.dict['account']
			dic['identifier'] = user_identifier
		else:
			dic['identifier'] = None
		self.write_message(dic)

	def open(self):
		# this happens BEFORE first-steps
		self.jsend({
			'command': 'populate-oauth-urls',
			'url_dict': auth.auth_url_dict(host=self.request.host),
		})

	def on_message(self, message):
		log.debug('got message: ' + message+"\n")
		ball = json.loads(message)

		if ball['command'] == 'print':
			print(ball['message'])

		elif ball['command'] == 'first-steps':
			self.user = User(ball['identifier'])
			self.jsend({'command': 'update-user'})
			if self.ids(ball):
				self.send_graph(ball)
			else: # they've learned nothing yet
				self.jsend({
					'command': 'prompt-starting-nodes',
				})

		elif ball['command'] == 'get-starting-nodes':
			subject = ball['subject']
			self.user.set_pref({'subject': subject})
			self.send_graph(ball)

		elif ball['command'] == 'get-curriculum':
			goal = ball['goal']

		elif ball['command'] == 'learn-node':
			command = self.user.learn_node(ball['node_id'])
			if command is not None:
				self.jsend(command)
			if ball['mode'] == 'learn':
				self.send_graph(ball)
			else:
				raise Exception('mode is not learn')

		elif ball['command'] == 'unlearn-node':
			self.user.unlearn_node(ball['node_id'])

		elif ball['command'] == 'set-pref':
			self.user.set_pref(ball['pref_dict'])

		elif ball['command'] == 'save-node': # hopefully this can handle both new nodes and changes to nodes
			node_dict = ball['node_dict']
			if 'importance' in node_dict.keys():
				node_dict['importance'] = int(node_dict['importance'])
			try:
				node_obj = node.create_appropriate_node(node_dict)
				log.debug('\nnode made.  looks like: '+str(node_obj)+'.  Now time to put it into the DB...\n')
				# take a look at the dependencies now

				# TODO if the node is brand new (mongo can't find it), then let previous_dep_ids = []
				previous_dependency_ids = [node.reduce_string(dependency) for dependency in list(our_mongo.find({"_id": node_obj.id}))[0]["_dependencies"]] # if this works, try using set() instead of list and elimination the set()s below
				log.debug('prev deps are: '+str(previous_dependency_ids))
				current_dependency_ids = node_obj.dependency_ids
				log.debug('curr deps are: '+str(current_dependency_ids))
				new_dependency_ids = set(current_dependency_ids) - set(previous_dependency_ids)
				removed_dependency_ids = set(previous_dependency_ids) - set(current_dependency_ids)


				# VERIFY THAT THE GRAPH WITH THESE NEW ARCS IS STILL ACYCLIC:
				H = our_MG.copy()
				for new_dependency_id in new_dependency_ids:
					print('from '+str(our_MG.n(new_dependency_id))+' to '+str(node_obj))
					H.add_edge(new_dependency_id, node_obj.id)
					H.validate(node_obj.name + ' cannot depend on ' + our_MG.n(new_dependency_id).name + ' because ' + our_MG.n(new_dependency_id).name + ' already depends on ' + node_obj.name + '!')

				our_mongo.upsert({ "_id": node_obj.id }, node_obj.__dict__)
				update_our_MG()

				# send an update of the graph to the user if there are new dependencies:
				self.request_nodes(new_dependency_ids, ball)
				self.remove_client_edges(node_obj.id, removed_dependency_ids)
			except Exception as error:
				# stuff didn't work, send error back to user
				log.warning('ERROR: '+str(error))
				self.jsend({
					'command': 'display-error',
					'message': str(error),
				})

		elif ball['command'] == 're-center-graph':
			# We get the 5th nearest neighbors
			neighbors = our_MG.single_source_shortest_anydirectional_path_length(ball['central_node_id'], 1) # can just use digraph.anydirectional_neighbors
			H = our_MG.subgraph(list(neighbors.keys()))
			dict_graph = H.as_js_ready_dict()
			self.jsend({
				'command': 'load-graph',
				'new_graph': dict_graph,
			})

		elif ball['command'] == 'request-node':
			self.request_nodes([ball['node_id']], ball)

		elif ball['command'] == 'search':
			search_results = our_mongo.find({'$text':{'$search':ball['search_term']}},{'score':{'$meta':"textScore"}})
			self.jsend({
				'command': 'search-results',
				'results': list(search_results.sort([('score', {'$meta': 'textScore'})]).limit(10)),
			})

		elif ball['command'] == 'get-goal-suggestion':
			goal_id = our_MG.choose_goal(self.user)
			goal_node = our_MG.n(goal_id)
			self.jsend({
				'command': 'suggest-goal',
				'goal': goal_node.__dict__,
			})

		elif ball['command'] == 'set-goal':
			goal_id = ball['goal_id']
			goal_node = our_MG.n(goal_id)
			self.user.set_pref({'goal_id': goal_id})
			self.send_graph(ball)
			self.jsend({
				'command': 'highlight-goal',
				'goal': goal_node.__dict__,
			})

		elif ball['command'] == 'get-pregoal-suggestion':
			pregoal_id = our_MG.choose_learnable_pregoals(self.user, number=1)[0]
			pregoal_node = our_MG.n(pregoal_id)
			self.jsend({
				'command': 'suggest-pregoal',
				'pregoal': pregoal_node.__dict__,
			})

		elif ball['command'] == 'set-pregoal':
			pregoal_id = ball['pregoal_id']
			pregoal_node = our_MG.n(pregoal_id)
			self.user.set_pref({'requested_pregoal_id': pregoal_id})
			self.send_graph(ball)
			self.jsend({
				'command': 'highlight-pregoal',
				'pregoal': pregoal_node.__dict__,
			})

	def request_nodes(self, node_ids, ball):
		# user manually requests a node.  So we want to preserve client_node_ids as not to change anything for them.  We only want to ADD the requested nodes additionally.
		for node_id in node_ids:
			if node_id not in our_MG.nodes():
				raise ValueError('The node_id "'+node_id+'" does not exist.')
		ids = set(self.ids(ball)).union(set(node_ids))
		H = our_MG.subgraph(ids)
		dict_graph = H.as_js_ready_dict()
		self.jsend({
			'command': 'load-graph',
			'new_graph': dict_graph,
		})

	def ids(self, ball):
		learned_ids = self.user.dict['learned_node_ids']
		return list(set(learned_ids).union(set(ball['client_node_ids'])))

	def remove_client_edges(self, node_id, dependency_ids):
		self.jsend({
			'command': 'remove-edges',
			'node_id': node_id,
			'dependency_ids': list(dependency_ids),
		})

	def send_graph(self, ball):
		subject = self.user.dict['prefs']['subject']
		log.debug('SUBJECT IS: ' + str(subject))
		log.debug('LOGGED IN AS: ' + str(self.user.identifier))
		nodes_to_send = our_MG.nodes_to_send(self.user, client_node_ids=ball['client_node_ids'])
		subgraph_to_send = our_MG.subgraph(nodes_to_send)
		dict_graph = subgraph_to_send.as_js_ready_dict()
		self.jsend({
			'command': 'load-graph',
			'new_graph': dict_graph,
		})

	def starting_nodes(self, subject):
		return config.starting_nodes[subject]

	def on_close(self):
		print('A websocket has been closed.')