def judge(unit, user): """ Given a unit and a user, pass judgement on which bucket to file it under. """ response = Response.get_latest(user_id=user['id'], unit_id=unit['entity_id']) 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 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': Response({}), 'feedback': '', } errors = card.validate_response(response) if errors: return {'errors': errors} score, feedback = card.score_response(response) response = Response({ 'user_id': user['id'], 'card_id': card['entity_id'], 'unit_id': card['unit_id'], 'response': response, 'score': score, }) card_parameters = CardParameters.get(db_conn, entity_id=card['entity_id']) if not card_parameters: card_parameters = CardParameters({ 'entity_id': card['entity_id'] }) previous_response = Response.get_latest(db_conn, user_id=user['id'], unit_id=card['unit_id']) 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 = card_parameters.get_distribution('guess') slip_distribution = card_parameters.get_distribution('slip') updates = formula_update(score, time_delta, learned, guess_distribution, slip_distribution) response['learned'] = updates['learned'] response, errors = response.save(db_conn) if errors: return {'errors': errors, 'feedback': feedback} card_parameters.set_distribution('guess', updates['guess_distribution']) card_parameters.set_distribution('slip', updates['slip_distribution']) card_parameters, errors = card_parameters.save(db_conn) if errors: return {'errors': errors, 'feedback': feedback} return {'response': response, 'feedback': feedback}
def judge(db_conn, unit, user): """ Given a unit and a user, pass judgement on which bucket to file it under. """ response = Response.get_latest( db_conn, user_id=user['id'], unit_id=unit['entity_id'] ) 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 choose_card(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(database.db_conn)] if not len(cards): return None previous_response = Response.get_latest(user_id=user['id'], unit_id=unit_id) 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 = CardParameters.get(entity_id=card['entity_id']) guess = params.get_distribution('guess').get_value() slip = params.get_distribution('slip').get_value() correct = calculate_correct(guess, slip, learned) if 0.25 < correct < 0.75: return card return assessment[0] if len(nonassessment): return nonassessment[0] if len(assessment): return assessment[0] return None
def update(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': Response({}), 'feedback': '', } errors = card.validate_response(response) if errors: return {'errors': errors} score, feedback = card.score_response(response) response = Response({ 'user_id': user['id'], 'card_id': card['entity_id'], 'unit_id': card['unit_id'], 'response': response, 'score': score, }) card_parameters = CardParameters.get(entity_id=card['entity_id']) previous_response = Response.get_latest(user_id=user['id'], unit_id=card['unit_id']) 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 = card_parameters.get_distribution('guess') slip_distribution = card_parameters.get_distribution('slip') updates = formula_update(score, time_delta, learned, guess_distribution, slip_distribution) response['learned'] = updates['learned'] response, errors = response.save() if errors: return {'errors': errors, 'feedback': feedback} card_parameters.set_distribution('guess', updates['guess_distribution']) card_parameters.set_distribution('slip', updates['slip_distribution']) card_parameters, errors = card_parameters.save() if errors: return {'errors': errors, 'feedback': feedback} return {'response': response, 'feedback': feedback}
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 Response.get_latest(db_conn, 'abcd1234', 'apple')['id'] == 'A'
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 Response.get_latest('abcd1234', 'apple')['id'] == 'A'