def judge(db_conn, unit, user): """ Given a unit and a user, pass judgement on which bucket to file it under. """ response = get_latest_response(user['id'], unit['entity_id'], db_conn) if response: learned = response['learned'] now = time() time_delta = now - (int(response['created'].strftime("%s")) if response else now) belief = calculate_belief(learned, time_delta) else: learned = 0 belief = 0 if learned >= max_learned: if belief > max_belief: return "done" if belief <= max_belief: return "review" if belief > diag_belief: return "learn" return "diagnose"
def test_get_latest_response(db_conn): create_response_test_data(db_conn) response = get_latest_response(db_conn, user_id=user_a_uuid, unit_id=test_unit_uuid) assert response assert response['score'] == 0
def test_deliver_response(db_conn): create_response_test_data(db_conn) response = get_latest_response(db_conn, user_id=user_a_uuid, unit_id=test_unit_uuid) result = deliver_response(response, access=None) assert result
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
def test_get_latest(db_conn, responses_table): """ Expect to get the latest response by user and unit. """ responses_table.insert([{ 'id': 'A', 'user_id': 'abcd1234', 'unit_id': 'apple', 'created': r.now(), 'modified': r.now(), }, { 'id': 'B', 'user_id': 'abcd1234', 'unit_id': 'banana', 'created': r.now(), 'modified': r.now(), }]).run(db_conn) assert get_latest_response('abcd1234', 'apple', db_conn)['id'] == 'A'
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
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}
def get_learned(db_conn, user, unit): unit_id = unit['entity_id'] previous_response = get_latest_response(db_conn, user['id'], unit_id) if previous_response: return previous_response['learned'] return init_learned