Esempio n. 1
0
def test_set_learning_context(db_conn):
    create_test_users(db_conn)
    user = get_user_by_id(db_conn, {'id': user_a_uuid})
    set_learning_context(user, unit={'entity_id': 'abcd1234'})
    context = get_learning_context(user)
    assert context
    assert context['unit']
Esempio n. 2
0
def choose_unit_route(request, subject_id, unit_id):
    """
  Updates the learner's information based on the unit they have chosen.

  NEXT STATE
  POST Chosen Unit
    -> GET Learn Card
  """

    # TODO-3 simplify this method. should it be broken up or moved to model?
    db_conn = request['db_conn']
    current_user = get_current_user(request)
    if not current_user:
        return abort(401, 'NcrRkqIlSW-BkcWLBkwORQ')
    unit = get_latest_accepted_unit(db_conn, unit_id)
    if not unit:
        return abort(404, 'PIti_qwAQ7WXwQwNZertxw')
    # If the unit isn't in the subject...
    context = get_learning_context(current_user)
    subject_ids = [
        convert_uuid_to_slug(subject['entity_id'])
        for subject in list_subjects_by_unit_recursive(db_conn, unit_id)
    ]
    context_subject_id = context.get('subject', {}).get('entity_id')
    if context_subject_id not in subject_ids:
        return 400, {
            'errors': [{
                'message': 'Unit not in subject.',
                'ref': 'r32fH0eCRZCivJoh-hKwZQ',
            }]
        }
    # Or, the unit doesn't need to be learned...
    status = judge(db_conn, unit, current_user)
    if status == "done":
        return 400, {
            'errors': [{
                'message': 'Unit not needed.',
                'ref': 'YTU27E63Rfiy3Rqmqd6Bew',
            }]
        }
    # Choose a card for the learner to learn
    card = choose_card(db_conn, current_user, unit)
    if card:
        next_ = {
            'method':
            'GET',
            'path':
            '/s/cards/{card_id}/learn'.format(
                card_id=convert_uuid_to_slug(card['entity_id'])),
        }
    else:
        next_ = {}
    set_learning_context(current_user,
                         unit=unit,
                         card=card if card else None,
                         next=next_)
    return 200, {'next': next_}
Esempio n. 3
0
def choose_unit_route(request, set_id, unit_id):
    """
    Updates the learner's information based on the unit they have chosen.

    NEXT STATE
    POST Chosen Unit
        -> GET Learn Card
    """

    # TODO-3 simplify this method. should it be broken up or moved to model?
    db_conn = request['db_conn']

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

    unit = Unit.get_latest_accepted(db_conn, unit_id)
    if not unit:
        return abort(404)

    # If the unit isn't in the set...
    context = get_learning_context(current_user)
    set_ids = [set_['entity_id']
               for set_ in Set.list_by_unit_id(db_conn, unit_id)]
    if context.get('set', {}).get('entity_id') not in set_ids:
        return abort(400)

    status = judge(db_conn, unit, current_user)
    # Or, the unit doesn't need to be learned...
    if status == "done":
        return abort(400)

    # Choose a card for the learner to learn
    card = choose_card(db_conn, current_user, unit)

    if card:
        next_ = {
            'method': 'GET',
            'path': '/s/cards/{card_id}/learn'
                    .format(card_id=card['entity_id']),
        }
    else:
        next_ = {}

    set_learning_context(
        current_user,
        unit=unit.data,
        card=card.data if card else None,
        next=next_
    )

    return 200, {'next': next_}
Esempio n. 4
0
def choose_unit_route(request, subject_id, unit_id):
    """
    Updates the learner's information based on the unit they have chosen.

    NEXT STATE
    POST Chosen Unit
        -> GET Learn Card
    """

    # TODO-3 simplify this method. should it be broken up or moved to model?
    db_conn = request['db_conn']

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

    unit = Unit.get_latest_accepted(db_conn, unit_id)
    if not unit:
        return abort(404)

    # If the unit isn't in the subject...
    context = get_learning_context(current_user)
    subject_ids = [
        subject['entity_id']
        for subject in Subject.list_by_unit_id(db_conn, unit_id)
    ]
    if context.get('subject', {}).get('entity_id') not in subject_ids:
        return abort(400)

    status = judge(db_conn, unit, current_user)
    # Or, the unit doesn't need to be learned...
    if status == "done":
        return abort(400)

    # Choose a card for the learner to learn
    card = choose_card(db_conn, current_user, unit)

    if card:
        next_ = {
            'method': 'GET',
            'path':
            '/s/cards/{card_id}/learn'.format(card_id=card['entity_id']),
        }
    else:
        next_ = {}

    set_learning_context(current_user,
                         unit=unit.data,
                         card=card.data if card else None,
                         next=next_)

    return 200, {'next': next_}
Esempio n. 5
0
def test_set_learning_context(db_conn, users_table):
    """
    Expect to set the learning context.
    """

    users_table.insert({"id": "abcd1234", "name": "Dalton", "email": "*****@*****.**", "password": "******"}).run(
        db_conn
    )

    user = get_user({"id": "abcd1234"}, db_conn)

    set_learning_context(user, card={"entity_id": "A"})
    assert get_learning_context(user) == {"card": {"entity_id": "A"}}

    set_learning_context(
        user, unit={"entity_id": "B", "name": "Banana", "body": "Banana"}, set={"entity_id": "C", "name": "Coconut"}
    )
    assert get_learning_context(user) == {
        "card": {"entity_id": "A"},
        "unit": {"entity_id": "B", "name": "Banana", "body": "Banana"},
        "set": {"entity_id": "C", "name": "Coconut"},
    }

    set_learning_context(user, set=None)
    assert get_learning_context(user) == {
        "card": {"entity_id": "A"},
        "unit": {"entity_id": "B", "name": "Banana", "body": "Banana"},
    }

    set_learning_context(user, card=None, unit=None)
    assert get_learning_context(user) == {}
Esempio n. 6
0
def test_seq_next(db_conn, session):
    """
    Expect sequencer route to say where to go next.
    """

    request = {
        'cookies': {
            'session_id': session
        },
        'db_conn': db_conn,
    }
    user = get_user({'id': 'abcd1234'}, db_conn)
    set_learning_context(user, next={'method': 'DANCE', 'path': '/s/unicorns'})
    code, response = routes.next.next_route(request)
    assert code == 200
    assert response['next']['method'] == 'DANCE'
    set_learning_context(user, next=None)
Esempio n. 7
0
def test_set_learning_context(db_conn, users_table):
    """
    Expect to set the learning context.
    """

    users_table.insert({
        'id': 'abcd1234',
        'name': 'Dalton',
        'email': '*****@*****.**',
        'password': '******',
    }).run(db_conn)

    user = get_user({'id': 'abcd1234'}, db_conn)

    set_learning_context(user, card={'entity_id': 'A'})
    assert get_learning_context(user) == {'card': {'entity_id': 'A'}}

    set_learning_context(user,
                         unit={
                             'entity_id': 'B',
                             'name': 'Banana',
                             'body': "Banana",
                         },
                         set={
                             'entity_id': 'C',
                             'name': 'Coconut',
                         })
    assert get_learning_context(user) == {
        'card': {
            'entity_id': 'A',
        },
        'unit': {
            'entity_id': 'B',
            'name': 'Banana',
            'body': "Banana",
        },
        'set': {
            'entity_id': 'C',
            'name': 'Coconut',
        }
    }

    set_learning_context(user, set=None)
    assert get_learning_context(user) == {
        'card': {
            'entity_id': 'A',
        },
        'unit': {
            'entity_id': 'B',
            'name': 'Banana',
            'body': "Banana",
        },
    }

    set_learning_context(user, card=None, unit=None)
    assert get_learning_context(user) == {}
Esempio n. 8
0
def test_seq_next(db_conn, session):
    """
    Expect sequencer route to say where to go next.
    """

    request = {
        'cookies': {'session_id': session},
        'db_conn': db_conn,
    }
    user = get_user({'id': 'abcd1234'}, db_conn)
    set_learning_context(user, next={
        'method': 'DANCE',
        'path': '/s/unicorns'
    })
    code, response = routes.next.next_route(request)
    assert code == 200
    assert response['next']['method'] == 'DANCE'
    set_learning_context(user, next=None)
Esempio n. 9
0
def get_set_units_route(request, set_id):
    """
    Present a small number of units the learner can choose from.

    NEXT STATE
    GET Choose Unit
        -> POST Choose Unit
    """

    db_conn = request['db_conn']

    # TODO-3 simplify this method. should it be part of the models?

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

    context = get_learning_context(current_user)
    next_ = {
        'method':
        'POST',
        'path':
        '/s/sets/{set_id}/units/{unit_id}'.format(set_id=context.get(
            'set', {}).get('entity_id'),
                                                  unit_id='{unit_id}'),
    }
    set_learning_context(current_user, next=next_)

    set_ = Set.get_latest_accepted(db_conn, set_id)

    # Pull a list of up to 5 units to choose from based on priority.
    buckets = traverse(db_conn, current_user, set_)
    units = buckets['learn'][:5]
    # TODO-3 Time estimates per unit for mastery.

    return 200, {
        'next': next_,
        'units': [unit.deliver() for unit in units],
        # For the menu, it must return the name and ID of the set
        'set': set_.deliver(),
        'current_unit_id': context.get('unit', {}).get('entity_id'),
    }
Esempio n. 10
0
def learn_card_route(request, card_id):
    """
  Render the card's data, ready for learning.

  NEXT STATE
  GET Learn Card
    -> POST Respond Card
  """

    db_conn = request['db_conn']
    current_user = get_current_user(request)
    if not current_user:
        return abort(401, 'WBv3UeikTLu5AAwG9A0QZg')
    card = get_latest_accepted_card(db_conn, card_id)
    if not card:
        return abort(404, 'UgQHXzx4SSaHgJzHpRaL9g')
    # Make sure the current unit id matches the card
    context = get_learning_context(current_user)
    context_unit_id = context.get('unit', {}).get('entity_id')
    if context_unit_id != convert_uuid_to_slug(card['unit_id']):
        return 400, {
            'errors': [{
                'name': 'unit_id',
                'message': 'card not in current unit.',
                'ref': 'd6rhaoCuRdW0f9j8AlMXBQ',
            }],
        }
    next_ = {
        'method':
        'POST',
        'path':
        '/s/cards/{card_id}/responses'.format(
            card_id=convert_uuid_to_slug(card['entity_id']))
    }
    set_learning_context(current_user, card=card, next=next_)
    return 200, {
        'card': deliver_card(card, access='learn'),
        'subject': context.get('subject'),
        'unit': context.get('unit'),
        'next': next_,
    }
Esempio n. 11
0
def get_set_units_route(request, set_id):
    """
    Present a small number of units the learner can choose from.

    NEXT STATE
    GET Choose Unit
        -> POST Choose Unit
    """

    db_conn = request['db_conn']

    # TODO-3 simplify this method. should it be part of the models?

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

    context = get_learning_context(current_user)
    next_ = {
        'method': 'POST',
        'path': '/s/sets/{set_id}/units/{unit_id}'
                  .format(set_id=context.get('set', {}).get('entity_id'),
                          unit_id='{unit_id}'),
    }
    set_learning_context(current_user, next=next_)

    set_ = Set.get_latest_accepted(db_conn, set_id)

    # Pull a list of up to 5 units to choose from based on priority.
    buckets = traverse(db_conn, current_user, set_)
    units = buckets['learn'][:5]
    # TODO-3 Time estimates per unit for mastery.

    return 200, {
        'next': next_,
        'units': [unit.deliver() for unit in units],
        # For the menu, it must return the name and ID of the set
        'set': set_.deliver(),
        'current_unit_id': context.get('unit', {}).get('entity_id'),
    }
Esempio n. 12
0
def list_user_subjects_route(request, user_id):
  """
  Get the list of subjects the user has added.

  NEXT STATE
  GET Choose Subject
    -> POST Choose Subject
  """

  db_conn = request['db_conn']
  current_user = get_current_user(request)
  # Get the user in question
  if current_user and current_user['id'] == convert_slug_to_uuid(user_id):
    user = current_user
  else:
    user = get_user(db_conn, {'id': user_id})
    if not user:
      return abort(404, 'MhNh85CERQe6Zgv-qRO6Zg')
    if user['settings']['view_subjects'] != 'public':
      return abort(403, 'TcKwVsp9Q6WAkJSV-QKuSQ')
  params = request['params']
  user_subjects = list_user_subjects_entity(db_conn, user_id, params)
  response = {
    'subjects': [
      deliver_subject(subject)
      for subject in user_subjects
    ]
  }
  if current_user == user:
    next_ = {
      'method': 'POST',
      'path': '/s/users/{user_id}/subjects/{subject_id}'.format(
        user_id=current_user['id'],
        subject_id='{subject_id}'
      ),
    }
    set_learning_context(current_user, next=next_)
    response['next'] = next_
  return 200, response
Esempio n. 13
0
def get_subject_units_route(request, subject_id):
    """
  Present a small number of units the learner can choose from.

  NEXT STATE
  GET Choose Unit
    -> POST Choose Unit
  """

    db_conn = request['db_conn']
    # TODO-3 simplify this method. should it be part of the models?
    current_user = get_current_user(request)
    if not current_user:
        return abort(401, 'p_wleq0FRQ2HEuHKOJIb7Q')
    context = get_learning_context(current_user)
    next_ = {
        'method':
        'POST',
        'path':
        '/s/subjects/{subject_id}/units/{unit_id}'.format(
            subject_id=context.get('subject', {}).get('entity_id'),
            unit_id='{unit_id}'),
    }
    set_learning_context(current_user, next=next_)
    subject = get_latest_accepted_subject(db_conn, subject_id)
    if not subject:
        return abort(404, '68VOXmd6Shq2cwAAktkFtw')
    # Pull a list of up to 5 units to choose from based on priority.
    buckets = traverse(db_conn, current_user, subject)
    units = buckets['learn'][:5]
    # TODO-3 Time estimates per unit for mastery.
    return 200, {
        'next': next_,
        'units': [deliver_unit(unit) for unit in units],
        # For the menu, it must return the name and ID of the subject
        'subject': deliver_subject(subject),
        'current_unit_id': context.get('unit', {}).get('entity_id'),
    }
Esempio n. 14
0
def get_user_sets_route(request, user_id):
    """
    Get the list of sets the user has added.

    NEXT STATE
    GET Choose Set
        -> POST Choose Set
    """

    db_conn = request['db_conn']

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

    if user_id != current_user['id']:
        return abort(403)

    next_ = {
        'method':
        'POST',
        'path':
        '/s/users/{user_id}/sets/{set_id}'.format(user_id=current_user['id'],
                                                  set_id='{set_id}'),
    }
    set_learning_context(current_user, next=next_)

    uset = get_user_sets(user_id, db_conn)
    if not uset:
        return 200, {'sets': [], 'next': next_}
    return 200, {
        'sets': [
            set_.deliver() for set_ in list_user_sets_entity(
                user_id, request['params'], db_conn)
        ],
        'next':
        next_,
    }
def test_choose_unit(db_conn, session):
    """
  Expect to let a learner choose their unit.
  """

    create_route_subject_test_data(db_conn)
    current_user = get_user_by_id(db_conn, {'id': user_id})
    set_learning_context(
        user=current_user,
        subject={'entity_id': convert_uuid_to_slug(subject_a_uuid)})
    request = {
        'db_conn': db_conn,
        'cookies': {
            'session_id': session,
        },
        'params': {}
    }
    code, response = choose_unit_route(request,
                                       subject_id=subject_a_uuid,
                                       unit_id=unit_a_uuid)
    assert not response.get('errors')
    assert code == 200
    assert response['next']
Esempio n. 16
0
def select_set_route(request, user_id, set_id):
    """
    Select the set to work on.

    NEXT STATE
    POST Choose Set   (Update Learner Context)
        -> GET View Set Tree
    """

    db_conn = request['db_conn']

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

    set_ = Set.get_latest_accepted(db_conn, set_id)
    next_ = {
        'method': 'GET',
        'path': '/s/sets/{set_id}/tree'.format(set_id=set_id),
    }
    set_learning_context(current_user, set=set_.data, next=next_)

    return 200, {'next': next_}
Esempio n. 17
0
def learn_card_route(request, card_id):
    """
    Render the card's data, ready for learning.

    NEXT STATE
    GET Learn Card
        -> POST Respond Card
    """

    db_conn = request['db_conn']

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

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

    # Make sure the current unit id matches the card
    context = get_learning_context(current_user)
    if context.get('unit', {}).get('entity_id') != card['unit_id']:
        return abort(400)

    next_ = {
        'method': 'POST',
        'path': '/s/cards/{card_id}/responses'
                .format(card_id=card['entity_id'])
    }
    set_learning_context(current_user, card=card.data, next=next_)

    return 200, {
        'card': card.deliver(access='learn'),
        'set': context.get('set'),
        'unit': context.get('unit'),
        'next': next_,
    }
Esempio n. 18
0
def learn_card_route(request, card_id):
    """
    Render the card's data, ready for learning.

    NEXT STATE
    GET Learn Card
        -> POST Respond Card
    """

    db_conn = request['db_conn']

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

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

    # Make sure the current unit id matches the card
    context = get_learning_context(current_user)
    if context.get('unit', {}).get('entity_id') != card['unit_id']:
        return abort(400)

    next_ = {
        'method': 'POST',
        'path':
        '/s/cards/{card_id}/responses'.format(card_id=card['entity_id'])
    }
    set_learning_context(current_user, card=card.data, next=next_)

    return 200, {
        'card': card.deliver(access='learn'),
        'set': context.get('set'),
        'unit': context.get('unit'),
        'next': next_,
    }
Esempio n. 19
0
def get_user_sets_route(request, user_id):
    """
    Get the list of sets the user has added.

    NEXT STATE
    GET Choose Set
        -> POST Choose Set
    """

    db_conn = request['db_conn']

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

    if user_id != current_user['id']:
        return abort(403)

    next_ = {
        'method': 'POST',
        'path': '/s/users/{user_id}/sets/{set_id}'
                .format(user_id=current_user['id'],
                        set_id='{set_id}'),
    }
    set_learning_context(current_user, next=next_)

    uset = UserSets.get(db_conn, user_id=user_id)
    if not uset:
        return 200, {'sets': [], 'next': next_}
    return 200, {
        'sets': [s.deliver()
                 for s in uset.list_sets(
                     db_conn,
                     **request['params'])],
        'next': next_,
    }
Esempio n. 20
0
def select_set_route(request, user_id, set_id):
    """
    Select the set to work on.

    NEXT STATE
    POST Choose Set   (Update Learner Context)
        -> GET View Set Tree
    """

    db_conn = request['db_conn']

    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

    set_ = Set.get_latest_accepted(db_conn, set_id)
    next_ = {
        'method': 'GET',
        'path': '/s/sets/{set_id}/tree'
                .format(set_id=set_id),
    }
    set_learning_context(current_user, set=set_.data, next=next_)

    return 200, {'next': next_}
Esempio n. 21
0
def select_subject_route(request, user_id, subject_id):
  """
  Select the subject to work on.

  NEXT STATE
  POST Choose Subject   (Update Learner Context)
    -> GET Choose Subject ...when subject is complete
    -> GET Choose Unit  ...when in learn or review mode
    -> GET Learn Card   ...when in diagnosis
      (Unit auto chosen)
  """

  db_conn = request['db_conn']
  current_user = get_current_user(request)
  if not current_user:
    return abort(401, 'f8IynoM9RLmW0Ae14_Hukw')
  subject = get_latest_accepted_subject(db_conn, subject_id)
  set_learning_context(current_user, subject=subject)
  buckets = traverse(db_conn, current_user, subject)
  # When in diagnosis, choose the unit and card automagically.
  # if buckets.get('diagnose'):
  #   unit = buckets['diagnose'][0]
  #   card = choose_card(db_conn, current_user, unit)
  #   next_ = {
  #     'method': 'GET',
  #     'path': '/s/cards/{card_id}/learn'
  #         .format(card_id=convert_uuid_to_slug(card['entity_id'])),
  #   }
  #   set_learning_context(
  #     current_user,
  #     next=next_, unit=unit, card=card)
  # When in learn or review mode, lead me to choose a unit.
  # elif buckets.get('review') or
  if buckets.get('learn'):
    next_ = {
      'method': 'GET',
      'path': '/s/subjects/{subject_id}/units'.format(
        subject_id=convert_uuid_to_slug(subject_id)
      ),
    }
    set_learning_context(current_user, next=next_)
  # If the subject is complete, lead the learner to choose another subject.
  else:
    next_ = {
      'method': 'GET',
      'path': '/s/users/{user_id}/subjects'.format(
        user_id=convert_uuid_to_slug(current_user['id'])
      ),
    }
    set_learning_context(current_user, next=next_, unit=None, subject=None)
  return 200, {'next': next_}
Esempio n. 22
0
def respond_to_card_route(request, card_id):
    """
  Record and process a learner's response to a card.

  NEXT STATE
  POST Respond Card
    -> GET Learn Card    ...when not ready
    -> GET Choose Unit   ...when ready, but still units
    -> GET View Subject Tree   ...when ready and done
  """

    # TODO-3 simplify this method.
    #    perhaps smaller methods or move to model layer?
    db_conn = request['db_conn']
    current_user = get_current_user(request)
    if not current_user:
        return abort(401, 'XDVEHHLRSZqQNJW4Zi_iqw')
    card = get_latest_accepted_card(db_conn, card_id)
    if not card:
        return abort(404, 'TQZ3SmAhS1qBd274C9DG0w')
    # Make sure the card is the current one
    context = get_learning_context(current_user)
    context_card_id = context.get('card', {}).get('entity_id')
    if context_card_id != convert_uuid_to_slug(card['entity_id']):
        return 400, {
            'errors': [{
                'message': 'Not the current card.',
                'ref': 'XfmF52NmQnK_bbaxx-p8dg',
            }]
        }
    result = seq_update(db_conn, current_user, card,
                        request['params'].get('response'))
    errors, response, feedback = (result.get('errors'), result.get('response'),
                                  result.get('feedback'))
    if errors:
        return 400, {
            'errors': errors,
            'ref': 'HfuW7_B-TByy8yh4FwgdrA',
        }

    subject = context.get('subject')
    unit = context.get('unit')

    status = judge(db_conn, unit, current_user)

    # If we are done with this current unit...
    if status == "done":
        buckets = traverse(db_conn, current_user, subject)

        # If there are units to be diagnosed...
        if buckets.get('diagnose'):
            unit = buckets['diagnose'][0]
            next_card = choose_card(db_conn, current_user, unit)
            next_ = {
                'method':
                'GET',
                'path':
                '/s/cards/{card_id}/learn'.format(
                    card_id=convert_uuid_to_slug(next_card['entity_id'])),
            }
            set_learning_context(current_user,
                                 card=next_card.data,
                                 unit=unit,
                                 next=next_)

        # If there are units to be learned or reviewed...
        elif buckets.get('learn') or buckets.get('review'):
            next_ = {
                'method':
                'GET',
                'path':
                '/s/subjects/{subject_id}/units'.format(
                    subject_id=convert_uuid_to_slug(subject['entity_id'])),
            }
            set_learning_context(current_user,
                                 card=None,
                                 unit=None,
                                 next=next_)

        # If we are out of units...
        else:
            next_ = {
                'method':
                'GET',
                'path':
                '/s/subjects/{subject_id}/tree'.format(
                    subject_id=convert_uuid_to_slug(subject['entity_id'])),
            }
            set_learning_context(current_user,
                                 card=None,
                                 unit=None,
                                 next=next_)

    # If we are still reviewing, learning or diagnosing this unit...
    else:
        next_card = choose_card(db_conn, current_user, unit)
        if next_card:
            next_ = {
                'method':
                'GET',
                'path':
                '/s/cards/{card_id}/learn'.format(
                    card_id=convert_uuid_to_slug(next_card['entity_id'])),
            }
            set_learning_context(current_user, card=next_card, next=next_)
        else:
            next_ = {}
            set_learning_context(current_user, next=next_)

    return 200, {
        'response': deliver_response(response),
        'feedback': feedback,
        'next': next_,
    }
Esempio n. 23
0
def get_set_tree_route(request, set_id):
    """
    Render the tree of units that exists within a set.

    Contexts:
    - Search set, preview units in set
    - Pre diagnosis
    - Learner view progress in set
    - Set complete

    NEXT STATE
    GET View Set Tree
        -> GET Choose Set    ...when set is complete
        -> GET Choose Unit   ...when in learn or review mode
        -> GET Learn Card    ...when in diagnosis
            (Unit auto chosen)

    TODO-2 merge with get_set_units_route
    TODO-2 simplify this method
    """

    db_conn = request['db_conn']

    set_ = Set.get(db_conn, entity_id=set_id)

    if not set_:
        return abort(404)

    units = set_.list_units(db_conn)

    # For the menu, it must return the name and ID of the set
    output = {
        'set': set_.deliver(),
        'units': [u.deliver() for u in units],
    }

    current_user = get_current_user(request)

    if not current_user:
        return 200, output

    context = get_learning_context(current_user) if current_user else {}
    buckets = traverse(db_conn, current_user, set_)
    output['buckets'] = {
        'diagnose': [u['entity_id'] for u in buckets['diagnose']],
        'review': [u['entity_id'] for u in buckets['review']],
        'learn': [u['entity_id'] for u in buckets['learn']],
        'done': [u['entity_id'] for u in buckets['done']],
    }

    # If we are just previewing, don't update anything
    if set_id != context.get('set', {}).get('entity_id'):
        return 200, output

    # When in diagnosis, choose the unit and card automagically.
    if buckets['diagnose']:
        unit = buckets['diagnose'][0]
        card = choose_card(db_conn, current_user, unit)
        next_ = {
            'method': 'GET',
            'path':
            '/s/cards/{card_id}/learn'.format(card_id=card['entity_id']),
        }
        set_learning_context(current_user,
                             next=next_,
                             unit=unit.data,
                             card=card.data)

    # When in learn or review mode, lead me to choose a unit.
    elif buckets['review'] or buckets['learn']:
        next_ = {
            'method': 'GET',
            'path': '/s/sets/{set_id}/units'.format(set_id=set_id),
        }
        set_learning_context(current_user, next=next_)

    # If the set is complete, lead the learner to choose another set.
    else:
        next_ = {
            'method': 'GET',
            'path':
            '/s/users/{user_id}/sets'.format(user_id=current_user['id']),
        }
        set_learning_context(current_user, next=next_, unit=None, set=None)

    output['next'] = next_
    return 200, output
Esempio n. 24
0
def respond_to_card_route(request, card_id):
    """
    Record and process a learner's response to a card.

    NEXT STATE
    POST Respond Card
        -> GET Learn Card      ...when not ready
        -> GET Choose Unit     ...when ready, but still units
        -> GET View Set Tree   ...when ready and done
    """

    # TODO-3 simplify this method.
    #      perhaps smaller methods or move to model layer?

    db_conn = request['db_conn']
    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

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

    # Make sure the card is the current one
    context = get_learning_context(current_user)
    if context.get('card', {}).get('entity_id') != card['entity_id']:
        return abort(400)

    r = seq_update(db_conn, current_user, card,
                   request['params'].get('response'))
    errors, response, feedback = (r.get('errors'), r.get('response'),
                                  r.get('feedback'))
    if errors:
        return 400, {
            'errors': errors,
            'ref': 'wtyOJPoy4bh76OIbYp8mS3LP',
        }

    set_ = Set(context.get('set'))
    unit = Unit(context.get('unit'))

    status = judge(db_conn, unit, current_user)

    # If we are done with this current unit...
    if status == "done":
        buckets = traverse(db_conn, current_user, set_)

        # If there are units to be diagnosed...
        if buckets['diagnose']:
            unit = buckets['diagnose'][0]
            next_card = choose_card(db_conn, current_user, unit)
            next_ = {
                'method': 'GET',
                'path': '/s/cards/{card_id}/learn'
                        .format(card_id=next_card['entity_id']),
            }
            set_learning_context(
                current_user,
                card=next_card.data, unit=unit.data, next=next_)

        # If there are units to be learned or reviewed...
        elif buckets['learn'] or buckets['review']:
            next_ = {
                'method': 'GET',
                'path': '/s/sets/{set_id}/units'
                        .format(set_id=set_['entity_id']),
            }
            set_learning_context(current_user,
                                 card=None, unit=None, next=next_)

        # If we are out of units...
        else:
            next_ = {
                'method': 'GET',
                'path': '/s/sets/{set_id}/tree'
                        .format(set_id=set_['entity_id']),
            }
            set_learning_context(current_user,
                                 card=None, unit=None, next=next_)

    # If we are still reviewing, learning or diagnosing this unit...
    else:
        next_card = choose_card(db_conn, current_user, unit)
        if next_card:
            next_ = {
                'method': 'GET',
                'path': '/s/cards/{card_id}/learn'
                        .format(card_id=next_card['entity_id']),
            }
            set_learning_context(current_user, card=next_card.data, next=next_)
        else:
            next_ = {}
            set_learning_context(current_user, next=next_)

    return 200, {
        'response': response.deliver(),
        'feedback': feedback,
        'next': next_,
    }
Esempio n. 25
0
def get_set_tree_route(request, set_id):
    """
    Render the tree of units that exists within a set.

    Contexts:
    - Search set, preview units in set
    - Pre diagnosis
    - Learner view progress in set
    - Set complete

    NEXT STATE
    GET View Set Tree
        -> GET Choose Set    ...when set is complete
        -> GET Choose Unit   ...when in learn or review mode
        -> GET Learn Card    ...when in diagnosis
            (Unit auto chosen)

    TODO-2 merge with get_set_units_route
    TODO-2 simplify this method
    """

    db_conn = request['db_conn']

    set_ = Set.get(db_conn, entity_id=set_id)

    if not set_:
        return abort(404)

    units = set_.list_units(db_conn)

    # For the menu, it must return the name and ID of the set
    output = {
        'set': set_.deliver(),
        'units': [u.deliver() for u in units],
    }

    current_user = get_current_user(request)

    if not current_user:
        return 200, output

    context = get_learning_context(current_user) if current_user else {}
    buckets = traverse(db_conn, current_user, set_)
    output['buckets'] = {
        'diagnose': [u['entity_id'] for u in buckets['diagnose']],
        'review': [u['entity_id'] for u in buckets['review']],
        'learn': [u['entity_id'] for u in buckets['learn']],
        'done': [u['entity_id'] for u in buckets['done']],
    }

    # If we are just previewing, don't update anything
    if set_id != context.get('set', {}).get('entity_id'):
        return 200, output

    # When in diagnosis, choose the unit and card automagically.
    if buckets['diagnose']:
        unit = buckets['diagnose'][0]
        card = choose_card(db_conn, current_user, unit)
        next_ = {
            'method': 'GET',
            'path': '/s/cards/{card_id}/learn'
                    .format(card_id=card['entity_id']),
        }
        set_learning_context(
            current_user,
            next=next_, unit=unit.data, card=card.data)

    # When in learn or review mode, lead me to choose a unit.
    elif buckets['review'] or buckets['learn']:
        next_ = {
            'method': 'GET',
            'path': '/s/sets/{set_id}/units'
                    .format(set_id=set_id),
        }
        set_learning_context(current_user, next=next_)

    # If the set is complete, lead the learner to choose another set.
    else:
        next_ = {
            'method': 'GET',
            'path': '/s/users/{user_id}/sets'
                    .format(user_id=current_user['id']),
        }
        set_learning_context(current_user, next=next_, unit=None, set=None)

    output['next'] = next_
    return 200, output
Esempio n. 26
0
def respond_to_card_route(request, card_id):
    """
    Record and process a learner's response to a card.

    NEXT STATE
    POST Respond Card
        -> GET Learn Card      ...when not ready
        -> GET Choose Unit     ...when ready, but still units
        -> GET View Set Tree   ...when ready and done
    """

    # TODO-3 simplify this method.
    #      perhaps smaller methods or move to model layer?

    db_conn = request['db_conn']
    current_user = get_current_user(request)
    if not current_user:
        return abort(401)

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

    # Make sure the card is the current one
    context = get_learning_context(current_user)
    if context.get('card', {}).get('entity_id') != card['entity_id']:
        return abort(400)

    r = seq_update(db_conn, current_user, card,
                   request['params'].get('response'))
    errors, response, feedback = (r.get('errors'), r.get('response'),
                                  r.get('feedback'))
    if errors:
        return 400, {
            'errors': errors,
            'ref': 'wtyOJPoy4bh76OIbYp8mS3LP',
        }

    set_ = Set(context.get('set'))
    unit = Unit(context.get('unit'))

    status = judge(db_conn, unit, current_user)

    # If we are done with this current unit...
    if status == "done":
        buckets = traverse(db_conn, current_user, set_)

        # If there are units to be diagnosed...
        if buckets['diagnose']:
            unit = buckets['diagnose'][0]
            next_card = choose_card(db_conn, current_user, unit)
            next_ = {
                'method':
                'GET',
                'path':
                '/s/cards/{card_id}/learn'.format(
                    card_id=next_card['entity_id']),
            }
            set_learning_context(current_user,
                                 card=next_card.data,
                                 unit=unit.data,
                                 next=next_)

        # If there are units to be learned or reviewed...
        elif buckets['learn'] or buckets['review']:
            next_ = {
                'method': 'GET',
                'path':
                '/s/sets/{set_id}/units'.format(set_id=set_['entity_id']),
            }
            set_learning_context(current_user,
                                 card=None,
                                 unit=None,
                                 next=next_)

        # If we are out of units...
        else:
            next_ = {
                'method': 'GET',
                'path':
                '/s/sets/{set_id}/tree'.format(set_id=set_['entity_id']),
            }
            set_learning_context(current_user,
                                 card=None,
                                 unit=None,
                                 next=next_)

    # If we are still reviewing, learning or diagnosing this unit...
    else:
        next_card = choose_card(db_conn, current_user, unit)
        if next_card:
            next_ = {
                'method':
                'GET',
                'path':
                '/s/cards/{card_id}/learn'.format(
                    card_id=next_card['entity_id']),
            }
            set_learning_context(current_user, card=next_card.data, next=next_)
        else:
            next_ = {}
            set_learning_context(current_user, next=next_)

    return 200, {
        'response': deliver_response(response),
        'feedback': feedback,
        'next': next_,
    }