Exemplo n.º 1
0
def test_get_distribution(db_conn):
    create_card_test_data(db_conn)
    params = {
        'entity_id': card_b_uuid,
    }
    card_params = get_card_parameters(db_conn, params)
    dist = get_distribution(card_params, kind='guess')
    assert dist
    params = {
        'entity_id': card_a_uuid,
    }
    card_params = get_card_parameters(db_conn, params) or {}
    dist = get_distribution(card_params, kind='slip')
    assert dist
Exemplo n.º 2
0
def test_get_slip(db_conn):
    create_card_test_data(db_conn)
    params = {
        'entity_id': card_b_uuid,
    }
    card_params = get_card_parameters(db_conn, params)
    assert 0.27 < get_slip(card_params) < 0.28
Exemplo n.º 3
0
def test_get_guess(db_conn):
    create_card_test_data(db_conn)
    params = {
        'entity_id': card_b_uuid,
    }
    card_params = get_card_parameters(db_conn, params)
    assert get_guess(card_params) == 0.41
Exemplo n.º 4
0
def get_card_route(request, card_id):
    """
    Get a specific card given an ID. Show all relevant data, but
    not used for the learning interface.
    """

    db_conn = request['db_conn']

    card = get_card_by_kind(db_conn, card_id)
    if not card:
        return abort(404)

    unit = Unit.get_latest_accepted(db_conn, entity_id=card['unit_id'])
    if not unit:
        return abort(404)

    # TODO-2 SPLITUP create new endpoints for these instead
    topics = list_topics_by_entity_id(card_id, {}, db_conn)
    versions = Card.get_versions(db_conn, entity_id=card_id)
    requires = Card.list_requires(db_conn, entity_id=card_id)
    required_by = Card.list_required_by(db_conn, entity_id=card_id)
    params = get_card_parameters({'entity_id': card_id}, db_conn)

    return 200, {
        'card': card.deliver(access='view'),
        'card_parameters':
        (get_card_parameters_values(params) if params else None),
        'unit': unit.deliver(),
        'topics': [deliver_topic(topic) for topic in topics],
        'versions': [version.deliver() for version in versions],
        'requires': [require.deliver() for require in requires],
        'required_by': [require.deliver() for require in required_by],
    }
Exemplo n.º 5
0
def get_card_route(request, card_id):
    """
  Get a specific card given an ID. Show all relevant data, but
  not used for the learning interface.
  """

    db_conn = request['db_conn']
    card = get_latest_accepted_card(db_conn, card_id)
    if not card:
        return abort(404, 'fPebfwqfRNmOiSWqWISeaA')
    unit = get_latest_accepted_unit(db_conn, card['unit_id'])
    if not unit:
        return abort(404, 'IKSqfvHvRK6hbSAIOkQuLg')
    # TODO-2 SPLITUP create new endpoints for these instead
    requires = list_required_cards(db_conn, card_id)
    required_by = list_required_by_cards(db_conn, card_id)
    params = get_card_parameters(db_conn, {'entity_id': card_id})
    return 200, {
        'card': deliver_card(card, access='view'),
        'card_parameters':
        (get_card_parameters_values(params) if params else None),
        'unit': deliver_unit(unit),
        'requires': [deliver_card(require) for require in requires],
        'required_by': [deliver_card(require) for require in required_by],
    }
Exemplo n.º 6
0
def choose_card(db_conn, user, unit):
    """
    Given a user and a unit, choose an appropriate card.
    Return a card instance.
    """

    # TODO-3 simplify this method

    unit_id = unit['entity_id']
    query = (Card.start_accepted_query().filter({
        'unit_id': unit_id
    }).sample(10))  # TODO-2 index
    # TODO-3 does this belong as a model method?
    # TODO-2 is the sample value decent?
    # TODO-2 has the learner seen this card recently?

    cards = [Card(d) for d in query.run(db_conn)]
    if not len(cards):
        return None

    previous_response = get_latest_response(user['id'], unit_id, db_conn)
    if previous_response:
        learned = previous_response['learned']
        # Don't allow the previous card as the next card
        cards = [
            card for card in cards
            if card['entity_id'] != previous_response['card_id']
        ]
    else:
        learned = init_learned

    shuffle(cards)
    assessment, nonassessment = partition(cards, lambda c: c.has_assessment())
    choose_assessment = random() < p_assessment_map[floor(learned * 10)]

    if choose_assessment:
        if not len(assessment):
            return nonassessment[0]
        for card in assessment:
            params = get_card_parameters({'entity_id': card['entity_id']},
                                         db_conn)
            if params:
                values = get_card_parameters_values(params)
                guess = values['guess']
                slip = values['slip']
                correct = calculate_correct(guess, slip, learned)
                if 0.25 < correct < 0.75:
                    return card
            else:
                return card
        return assessment[0]

    if len(nonassessment):
        return nonassessment[0]

    if len(assessment):
        return assessment[0]

    return None
Exemplo n.º 7
0
def test_get_card_parameters_values(db_conn):
    create_card_test_data(db_conn)
    params = {
        'entity_id': card_b_uuid,
    }
    card_params = get_card_parameters(db_conn, params)
    result = get_card_parameters_values(card_params)
    assert 'guess' in result
    assert 'slip' in result
    assert 'transit' in result
    assert 'num_learners' in result
Exemplo n.º 8
0
def get_card_batch(db_conn, user, unit):
    unit_id = unit['entity_id']
    cards = list_random_cards_in_unit(db_conn, unit_id)
    if not cards:
        return None, None, None
    previous_response = get_latest_response(db_conn, user['id'], unit_id)
    if previous_response:
        # Don't allow the previous card as the next card
        cards = [
            card for card in cards
            if card['entity_id'] != previous_response['card_id']
        ]
    params = {}
    for card in cards:
        params[card['entity_id']] = get_card_parameters_values(
            get_card_parameters(db_conn, {'entity_id': card['entity_id']})
            or {})
    shuffle(cards)
    scored, unscored = partition(cards, lambda c: c['kind'] in scored_kinds)
    return scored, unscored, params
Exemplo n.º 9
0
def update(db_conn, user, card, response):
    """
    Update the card's parameters (and its parents')
    when given a response.
    """

    # TODO-3 split up into smaller methods

    if not card.has_assessment():
        return {
            'response': {},
            'feedback': '',
        }

    errors = card.validate_response(response)
    if errors:
        return {'errors': errors}

    score, feedback = card.score_response(response)
    response = {
        'user_id': user['id'],
        'card_id': card['entity_id'],
        'unit_id': card['unit_id'],
        'response': response,
        'score': score,
    }

    card_parameters = get_card_parameters(
        {'entity_id': card['entity_id']},
        db_conn
    ) or {}
    previous_response = get_latest_response(user['id'],
                                            card['unit_id'],
                                            db_conn)

    now = time()
    time_delta = now - (int(previous_response['created'].strftime("%s"))
                        if previous_response else now)

    learned = (previous_response['learned']
               if previous_response else init_learned)
    guess_distribution = get_distribution(card_parameters, 'guess')
    slip_distribution = get_distribution(card_parameters, 'slip')

    updates = formula_update(score, time_delta,
                             learned, guess_distribution, slip_distribution)

    response['learned'] = updates['learned']
    response, errors = insert_response(response, db_conn)
    if errors:
        return {'errors': errors, 'feedback': feedback}

    updated_card_parameters = {
        'entity_id': card['entity_id'],
        'guess_distribution':
            bundle_distribution(updates['guess_distribution']),
        'slip_distribution':
            bundle_distribution(updates['slip_distribution']),
    }
    if card_parameters.get('id'):
        _, errors = update_card_parameters(
            card_parameters,
            updated_card_parameters,
            db_conn
        )
    else:
        _, errors = insert_card_parameters(
            updated_card_parameters,
            db_conn
        )

    if errors:
        return {'errors': errors, 'feedback': feedback}

    return {'response': response, 'feedback': feedback}