def get_exercise_parents_lookup_table(): """Return a dictionary with exercise ids as keys and topic_ids as values.""" global exercise_parents_lookup_table if exercise_parents_lookup_table: return exercise_parents_lookup_table ### topic tree for traversal### tree = get_topic_nodes_with_children(parent="root") #3 possible layers for topic in tree: for subtopic_id in topic['children']: exercises = get_topic_contents(topic_id=subtopic_id, kinds=["Exercise"]) for ex in exercises: if ex['id'] not in exercise_parents_lookup_table: exercise_parents_lookup_table[ex['id']] = { "subtopic_id": subtopic_id, "topic_id": topic['id'], } return exercise_parents_lookup_table
def get_exercise_parents_lookup_table(): """Return a dictionary with exercise ids as keys and topic_ids as values.""" global exercise_parents_lookup_table if exercise_parents_lookup_table: return exercise_parents_lookup_table ### topic tree for traversal### tree = get_topic_nodes_with_children(parent="root") #3 possible layers for topic in tree: for subtopic_id in topic['children']: exercises = get_topic_contents(topic_id=subtopic_id, kinds=["Exercise"]) if exercises is None: raise RuntimeError("Caught exception, tried to find topic contents for {}".format(subtopic_id)) for ex in exercises: if ex['id'] not in exercise_parents_lookup_table: exercise_parents_lookup_table[ ex['id'] ] = { "subtopic_id": subtopic_id, "topic_id": topic['id'], } return exercise_parents_lookup_table
def get_neighbors_at_dist_1(topic_index, subtopic_index, topic): """Return a list of the neighbors at distance 1 from the specified subtopic.""" neighbors = [] #neighbor list to be returned tree = get_topic_nodes_with_children(parent="root") #pointers to the previous and next subtopic (list indices) prev = subtopic_index - 1 next = subtopic_index + 1 #if there is a previous topic (neighbor to left) if (prev > -1) and prev < len(topic['children']): neighbors.append(topic['children'][prev] + ' 1') # neighbor on the left side #else check if there is a neighboring topic (left) else: if (topic_index - 1) > -1 and topic_index - 1 < len(tree) and len( tree[(topic_index - 1)]['children']) > 1: neighbor_length = len(tree[(topic_index - 1)]['children']) neighbors.append(tree[(topic_index - 1)]['children'][(neighbor_length - 1)] + ' 4') else: neighbors.append(' ') # no neighbor to the left #if there is a neighbor to the right if (next < len(topic['children'])): neighbors.append(topic['children'][next] + ' 1') # neighbor on the right side #else check if there is a neighboring topic (right) else: if (topic_index + 1) < len(tree) and tree[(topic_index + 1)]['children']: #the 4 denotes the # of nodes in path to this other node, will always be 4 neighbors.append(tree[(topic_index + 1)]['children'][0] + ' 4') else: neighbors.append(' ') # no neighbor on right side return neighbors
def get_neighbors_at_dist_1(topic_index, subtopic_index, topic): """Return a list of the neighbors at distance 1 from the specified subtopic.""" neighbors = [] #neighbor list to be returned tree = get_topic_nodes_with_children(parent="root") #pointers to the previous and next subtopic (list indices) prev = subtopic_index - 1 next = subtopic_index + 1 #if there is a previous topic (neighbor to left) if (prev > -1 ) and prev < len(topic['children']): neighbors.append(topic['children'][prev] + ' 1') # neighbor on the left side #else check if there is a neighboring topic (left) else: if (topic_index-1) > -1 and topic_index - 1 < len(tree) and len(tree[(topic_index-1)]['children']) > 1: neighbor_length = len(tree[(topic_index-1)]['children']) neighbors.append(tree[(topic_index-1)]['children'][(neighbor_length-1)] + ' 4') else: neighbors.append(' ') # no neighbor to the left #if there is a neighbor to the right if(next < len(topic['children'])): neighbors.append(topic['children'][next] + ' 1') # neighbor on the right side #else check if there is a neighboring topic (right) else: if (topic_index + 1) < len(tree) and tree[(topic_index+1)]['children']: #the 4 denotes the # of nodes in path to this other node, will always be 4 neighbors.append(tree[(topic_index+1)]['children'][0] + ' 4') else: neighbors.append(' ') # no neighbor on right side return neighbors
def generate_recommendation_data(): """Traverses topic tree to generate a dictionary with related subtopics per subtopic.""" global recommendation_data if recommendation_data: return recommendation_data ### populate data exploiting structure of topic tree ### tree = get_topic_nodes_with_children(parent="root") ######## DYNAMIC ALG ######### ## # ITERATION 1 - grabs all immediate neighbors of each subtopic ## #array indices for the current topic and subtopic topic_index = 0 subtopic_index = 0 #for each topic for topic in tree: subtopic_index = 0 #for each subtopic add the neighbors at distance 0 and 1 (at dist one has 2 for each) for subtopic_id in topic['children']: neighbors_dist_1 = get_neighbors_at_dist_1(topic_index, subtopic_index, topic) #add to recommendation_data - distance 0 (itself) + distance 1 recommendation_data[subtopic_id] = { 'related_subtopics': ([subtopic_id + ' 0'] + neighbors_dist_1) } subtopic_index += 1 topic_index += 1 ## # ITERATION 2 - grabs all subsequent neighbors of each subtopic via # Breadth-first search (BFS) ## #loop through all subtopics currently in recommendation_data dict for subtopic in recommendation_data: related = recommendation_data[subtopic][ 'related_subtopics'] # list of related subtopics (right now only 2) other_neighbors = get_subsequent_neighbors(related, recommendation_data, subtopic) recommendation_data[subtopic][ 'related_subtopics'] += other_neighbors ##append new neighbors ## # ITERATION 2.5 - Sort all results by increasing distance and to strip the final # result of all distance values in recommendation_data (note that there are only 3 possible: 0,1,4). ## #for each item in recommendation_data for subtopic in recommendation_data: at_dist_4 = [] #array to hold the subtopic ids of recs at distance 4 at_dist_lt_4 = [ ] #array to hold subtopic ids of recs at distance 0 or 1 #for this item, loop through all recommendations for recc in recommendation_data[subtopic]['related_subtopics']: if recc.split(" ")[1] == '4': #if at dist 4, add to the array at_dist_4.append(recc.split(" ")[0]) else: at_dist_lt_4.append(recc.split(" ")[0]) sorted_related = at_dist_lt_4 + at_dist_4 #append later items at end of earlier recommendation_data[subtopic]['related_subtopics'] = sorted_related return recommendation_data
def generate_recommendation_data(): """Traverses topic tree to generate a dictionary with related subtopics per subtopic.""" global recommendation_data if recommendation_data: return recommendation_data ### populate data exploiting structure of topic tree ### tree = get_topic_nodes_with_children(parent="root") ######## DYNAMIC ALG ######### ## # ITERATION 1 - grabs all immediate neighbors of each subtopic ## #array indices for the current topic and subtopic topic_index = 0 subtopic_index = 0 #for each topic for topic in tree: subtopic_index = 0 #for each subtopic add the neighbors at distance 0 and 1 (at dist one has 2 for each) for subtopic_id in topic['children']: neighbors_dist_1 = get_neighbors_at_dist_1(topic_index, subtopic_index, topic) #add to recommendation_data - distance 0 (itself) + distance 1 recommendation_data[ subtopic_id ] = { 'related_subtopics' : ([subtopic_id + ' 0'] + neighbors_dist_1) } subtopic_index+=1 topic_index+=1 ## # ITERATION 2 - grabs all subsequent neighbors of each subtopic via # Breadth-first search (BFS) ## #loop through all subtopics currently in recommendation_data dict for subtopic in recommendation_data: related = recommendation_data[subtopic]['related_subtopics'] # list of related subtopics (right now only 2) other_neighbors = get_subsequent_neighbors(related, recommendation_data, subtopic) recommendation_data[subtopic]['related_subtopics'] += other_neighbors ##append new neighbors ## # ITERATION 2.5 - Sort all results by increasing distance and to strip the final # result of all distance values in recommendation_data (note that there are only 3 possible: 0,1,4). ## #for each item in recommendation_data for subtopic in recommendation_data: at_dist_4 = [] #array to hold the subtopic ids of recs at distance 4 at_dist_lt_4 = [] #array to hold subtopic ids of recs at distance 0 or 1 #for this item, loop through all recommendations for recc in recommendation_data[subtopic]['related_subtopics']: if recc.split(" ")[1] == '4': #if at dist 4, add to the array at_dist_4.append(recc.split(" ")[0]) else: at_dist_lt_4.append(recc.split(" ")[0]) sorted_related = at_dist_lt_4 + at_dist_4 #append later items at end of earlier recommendation_data[subtopic]['related_subtopics'] = sorted_related return recommendation_data