def get_next_recommendations(user, request):
    """Get the recommendations for the Next section, and return them as a list.

    Logic:
    Next recommendations are currently comprised of 3 main subgroups: group recommendations,
    struggling exercises, and topic tree based data. Group recommendations consist of 
    finding the most common item tackled immediately after the most recent item, struggling
    is determined by the "struggling" model attribute, and topic tree data is based off
    the graphical distance between neighboring exercise/topic nodes. 
    Args:
    user -- The current user as a facility user model object.

    """

    exercise_parents_table = get_exercise_parents_lookup_table()

    most_recent = get_most_recent_exercises(user)

    complete_exercises = set(get_completed_exercises(user))

    def filter_complete(ex):
        return ex not in complete_exercises

    if len(most_recent) > 0 and most_recent[0] in exercise_parents_table:
        current_subtopic = exercise_parents_table[most_recent[0]]['subtopic_id']
    else:
        current_subtopic = None

    #logic for recommendations based off of the topic tree structure
    if current_subtopic:
        topic_tree_based_data = generate_recommendation_data()[current_subtopic]['related_subtopics'][:settings.TOPIC_RECOMMENDATION_DEPTH]
        topic_tree_based_data = get_exercises_from_topics(topic_tree_based_data)
    else:
        topic_tree_based_data = []
    
    #for checking that only exercises that have not been accessed are returned
    topic_tree_based_data = [ex for ex in topic_tree_based_data if ex not in most_recent or filter_complete(ex)]

    #logic to generate recommendations based on exercises student is struggling with
    struggling = filter(filter_complete, get_exercise_prereqs(get_struggling_exercises(user)))

    #logic to get recommendations based on group patterns, if applicable
    group = filter(filter_complete, get_group_recommendations(user))
  
    #now append titles and other metadata to each exercise id
    final = [] # final data to return
    for exercise_id in (group[:2] + struggling[:2] + topic_tree_based_data[:1]):  #notice the concatenation

        if exercise_id in exercise_parents_table:
            subtopic_id = exercise_parents_table[exercise_id]['subtopic_id']
            exercise = get_exercise_data(request, exercise_id)
            exercise["topic"] = get_topic_data(request, subtopic_id)
            final.append(exercise)


    #final recommendations are a combination of struggling, group filtering, and topic_tree filtering
    return final
Beispiel #2
0
def get_next_recommendations(user, request):
    """Get the recommendations for the Next section, and return them as a list.

    Logic:
    Next recommendations are currently comprised of 3 main subgroups: group recommendations,
    struggling exercises, and topic tree based data. Group recommendations consist of 
    finding the most common item tackled immediately after the most recent item, struggling
    is determined by the "struggling" model attribute, and topic tree data is based off
    the graphical distance between neighboring exercise/topic nodes. 
    Args:
    user -- The current user as a facility user model object.

    """

    exercise_parents_table = get_exercise_parents_lookup_table()

    most_recent = get_most_recent_exercises(user)

    complete_exercises = set(get_completed_exercises(user))

    def filter_complete(ex):
        return ex not in complete_exercises

    if len(most_recent) > 0 and most_recent[0] in exercise_parents_table:
        current_subtopic = exercise_parents_table[most_recent[0]]['subtopic_id']
    else:
        current_subtopic = None

    #logic for recommendations based off of the topic tree structure
    if current_subtopic:
        topic_tree_based_data = generate_recommendation_data()[current_subtopic]['related_subtopics'][:settings.TOPIC_RECOMMENDATION_DEPTH]
        topic_tree_based_data = get_exercises_from_topics(topic_tree_based_data)
    else:
        topic_tree_based_data = []
    
    #for checking that only exercises that have not been accessed are returned
    topic_tree_based_data = [ex for ex in topic_tree_based_data if ex not in most_recent or filter_complete(ex)]

    #logic to generate recommendations based on exercises student is struggling with
    struggling = filter(filter_complete, get_exercise_prereqs(get_struggling_exercises(user)))

    #logic to get recommendations based on group patterns, if applicable
    group = filter(filter_complete, get_group_recommendations(user))
  
    #now append titles and other metadata to each exercise id
    final = [] # final data to return
    for exercise_id in (group[:2] + struggling[:2] + topic_tree_based_data[:1]):  #notice the concatenation

        if exercise_id in exercise_parents_table:
            subtopic_id = exercise_parents_table[exercise_id]['subtopic_id']
            exercise = get_exercise_data(request, exercise_id)
            exercise["topic"] = get_topic_data(request, subtopic_id)
            final.append(exercise)


    #final recommendations are a combination of struggling, group filtering, and topic_tree filtering
    return final
def get_explore_recommendations(user, request):
    """Get the recommendations for the Explore section, and return them as a list.

    Logic:
    Looks at a preset distance away, beginning at 2 to exclude self recommendations, to 
    recommend a topic for exploration. Currently, the cap is a distance of 6 so that all
    recommendations will still be of moderate relatedness. This number is not permanent, and
    can be tweaked as needed.
    Args:
    user -- The current user as a facility user model object.

    """

    data = generate_recommendation_data()                           #topic tree alg
    exercise_parents_table = get_exercise_parents_lookup_table()    #for finding out subtopic ids
    recent_exercises = get_most_recent_exercises(user)              #most recent ex

    #simply getting a list of subtopics accessed by user
    recent_subtopics = list(set([exercise_parents_table[ex]['subtopic_id'] for ex in recent_exercises if ex in exercise_parents_table]))

    #choose sample number, up to three
    sampleNum = min(len(recent_subtopics), settings.TOPIC_RECOMMENDATION_DEPTH)
    
    random_subtopics = random.sample(recent_subtopics, sampleNum)
    added = []                                                      #keep track of what has been added (below)
    final = []                                                      #final recommendations to return
    
    for subtopic_id in random_subtopics:

        related_subtopics = data[subtopic_id]['related_subtopics'][2:7] #get recommendations based on this, can tweak numbers!

        recommended_topic = next(topic for topic in related_subtopics if not topic in added and not topic in recent_subtopics)

        if recommended_topic:

            final.append({
                'suggested_topic': get_topic_data(request, recommended_topic),
                'interest_topic': get_topic_data(request, subtopic_id),
            })

            added.append(recommended_topic)

    return final
Beispiel #4
0
def get_explore_recommendations(user, request):
    """Get the recommendations for the Explore section, and return them as a list.

    Logic:
    Looks at a preset distance away, beginning at 2 to exclude self recommendations, to 
    recommend a topic for exploration. Currently, the cap is a distance of 6 so that all
    recommendations will still be of moderate relatedness. This number is not permanent, and
    can be tweaked as needed.
    Args:
    user -- The current user as a facility user model object.

    """

    data = generate_recommendation_data()                           #topic tree alg
    exercise_parents_table = get_exercise_parents_lookup_table()    #for finding out subtopic ids
    recent_exercises = get_most_recent_exercises(user)              #most recent ex

    #simply getting a list of subtopics accessed by user
    recent_subtopics = list(set([exercise_parents_table[ex]['subtopic_id'] for ex in recent_exercises if ex in exercise_parents_table]))

    #choose sample number, up to three
    sampleNum = min(len(recent_subtopics), settings.TOPIC_RECOMMENDATION_DEPTH)
    
    random_subtopics = random.sample(recent_subtopics, sampleNum)
    added = []                                                      #keep track of what has been added (below)
    final = []                                                      #final recommendations to return
    
    for subtopic_id in random_subtopics:

        related_subtopics = data[subtopic_id]['related_subtopics'][2:7] #get recommendations based on this, can tweak numbers!

        for topic in related_subtopics:
            if topic not in added and topic not in recent_subtopics:
                final.append({
                    'suggested_topic': get_topic_data(request, topic),
                    'interest_topic': get_topic_data(request, subtopic_id),
                })
                added.append(topic)

    return final