def flush_entities(db_conn, descs): """ Given a list of kinds and entity_ids, return a list filled out with entities. """ output = [] for desc in descs: if desc['kind'] == 'card': card = Card.get_latest_accepted(db_conn, entity_id=desc['id']) card = flip_card_into_kind(card) if card: output.append(card) elif desc['kind'] == 'unit': output.append(Unit.get_latest_accepted( db_conn, entity_id=desc['id'] )) elif desc['kind'] == 'set': output.append(Set.get_latest_accepted( db_conn, entity_id=desc['id'] )) else: output.append(None) return output
def instance_entities(data): """ Given a kind and some json, call insert on that kind and return the results. A little safer. """ fields = ('id', 'created', 'modified', 'entity_id', 'previous_id', 'status', 'available') entities = [] if 'cards' in data: for card_data in data['cards']: kind = card_data.get('kind') if kind in card_map: entities.push( card_map[kind](omit(card_data, fields)) ) if 'units' in data: entities = entities + [ Unit(omit(unit_data, fields)) for unit_data in data['units'] ] if 'sets' in data: entities = entities + [ Set(omit(set_data, fields)) for set_data in data['sets'] ] return entities
def get_unit_route(request, unit_id): """ Get a specific unit given an ID. """ db_conn = request["db_conn"] unit = Unit.get_latest_accepted(db_conn, unit_id) if not unit: return abort(404) # TODO-2 SPLITUP create new endpoints for these instead topics = Topic.list_by_entity_id(db_conn, unit_id) versions = Unit.get_versions(db_conn, unit_id) requires = Unit.list_requires(db_conn, unit_id) required_by = Unit.list_required_by(db_conn, unit_id) sets = Set.list_by_unit_id(db_conn, unit_id) return ( 200, { "unit": unit.deliver(), # 'unit_parameters': unit.fetch_parameters(), "topics": [topic.deliver() 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], "belongs_to": [set_.deliver() for set_ in sets], }, )
def list_sets(self, limit=10, skip=0, **params): """ Join the user's set_ids with set information. Return empty list when there's no matching documents. """ return Set.list_by_entity_ids(self['set_ids'])
def get_unit_route(request, unit_id): """ Get a specific unit given an ID. """ unit = Unit.get_latest_accepted(unit_id) if not unit: return abort(404) # TODO-2 SPLITUP create new endpoints for these instead topics = Topic.list_by_entity_id(unit_id) versions = Unit.get_versions(unit_id) requires = Unit.list_requires(unit_id) required_by = Unit.list_required_by(unit_id) sets = Set.list_by_unit_id(unit_id) return 200, { 'unit': unit.deliver(), # 'unit_parameters': unit.fetch_parameters(), 'topics': [topic.deliver() 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], 'belongs_to': [set_.deliver() for set_ in sets], }
def list_sets(self, db_conn, limit=10, skip=0, **params): """ Join the user's set_ids with set information. Return empty list when there's no matching documents. """ return Set.list_by_entity_ids(db_conn, self['set_ids'])
def get_unit_route(request, unit_id): """ Get a specific unit given an ID. """ db_conn = request['db_conn'] unit = Unit.get_latest_accepted(db_conn, unit_id) if not unit: return abort(404) # TODO-2 SPLITUP create new endpoints for these instead topics = list_topics_by_entity_id(unit_id, {}, db_conn) versions = Unit.get_versions(db_conn, unit_id) requires = Unit.list_requires(db_conn, unit_id) required_by = Unit.list_required_by(db_conn, unit_id) sets = Set.list_by_unit_id(db_conn, unit_id) return 200, { 'unit': unit.deliver(), # 'unit_parameters': unit.fetch_parameters(), '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], 'belongs_to': [set_.deliver() for set_ in sets], }
def get_version(db_conn, kind, id_): if kind == 'card': card = Card.get(db_conn, id=id_) return flip_card_into_kind(card) elif kind == 'unit': return Unit.get(db_conn, id=id_) elif kind == 'set': return Set.get(db_conn, id=id_)
def get_recommended_sets(request): db_conn = request['db_conn'] sets = Set.get_all(db_conn) if not sets: return abort(404) return 200, { 'sets': [set_.deliver() for set_ in sets] }
def get_version(kind, id_): if kind == 'card': return Card.get(id=id_) # TODO-1 This needs to also get the right card kind... elif kind == 'unit': return Unit.get(id=id_) elif kind == 'set': return Set.get(id=id_)
def get_my_recently_created_sets(current_user, db_conn): """ Get the user's most recently created sets. """ proposals = get_my_recent_proposals(current_user, db_conn) unit_ids = get_proposal_entities(proposals, 'set') sets = Set.list_by_entity_ids(db_conn, unit_ids) return sets
def get_set_versions_route(request, set_id): """ Get versions set given an ID. Paginates. """ versions = Set.get_versions(entity_id=set_id, **request['params']) return 200, { 'versions': [version.deliver(access='view') for version in versions] }
def test_body(db_conn, sets_table, units_table): """ Expect a set to require a body. """ create_unit_a(db_conn, units_table) set_, errors = Set.insert(db_conn, {"name": "Statistics", "members": [{"id": "A", "kind": "unit"}]}) assert len(errors) == 1 set_["body"] = "A beginning course focused on probability." set_, errors = set_.save(db_conn) assert len(errors) == 0
def test_members(db_conn, sets_table, units_table): """ Expect a set to record a list of members. """ create_unit_a(db_conn, units_table) set_, errors = Set.insert(db_conn, {"name": "Statistics", "body": "A beginning course focused on probability."}) assert len(errors) == 1 set_["members"] = [{"id": "A", "kind": "unit"}] set_, errors = set_.save(db_conn) assert len(errors) == 0
def list_user_sets_entity(user_id, params, db_conn): """ Join the user's set_ids with set information. Return empty list when there's no matching documents. """ # TODO-2 each set -- needs review? # TODO-2 order by last reviewed time uset = get_user_sets(user_id, db_conn) # TODO-3 limit = params.get('limit') or 10 # TODO-3 skip = params.get('skip') or 0 return Set.list_by_entity_ids(db_conn, uset['set_ids'])
def get_set_route(request, set_id): """ Get a specific set given an ID. """ set_ = Set.get_latest_accepted(set_id) if not set_: return abort(404) # TODO-2 SPLITUP create new endpoints for these instead topics = Topic.list_by_entity_id(entity_id=set_id) versions = Set.get_versions(entity_id=set_id) units = set_.list_units() return 200, { 'set': set_.deliver(), # 'set_parameters': set_.fetch_parameters(), 'topics': [topic.deliver() for topic in topics], 'versions': [version.deliver() for version in versions], 'units': [unit.deliver() for unit in units], }
def get_card_info_from_name(self, name): try: print(f'Getting card info from name: {name}') name = name.replace(' ', '%20') url = f'https://db.ygoprodeck.com/api/v6/cardinfo.php?fname={name}' results = requests.get(url=url) card_info = json.loads(results.content) card_sets = [] if not 'No card matching your query was found in the database' in str(card_info): for card_set in card_info: sets = [] if 'card_sets' in str(card_set): cs = card_set['card_sets'] for s in cs: if len(sets) == 0: sets.append(Set(set_name=s['set_name'], set_code=s['set_code']).get_dict_sets()) else: item_found = False for ss in sets: if s['set_code'] == ss['set_code']: item_found = True break if not item_found: sets.append(Set(set_name=s['set_name'], set_code=s['set_code']).get_dict_sets()) sets = sorted(sets, key=lambda k:(len(k['set_code']), k['set_code'])) card_sets.append(CardSets(card_name=card_set['name'], image=card_set['card_images'][0]['image_url_small'], sets=sets).get_dict_card_sets()) print(f'Card sets: {card_sets}') return card_sets except Exception as e: print(f'TCGP - Occurred the following error trying to get card sets from name: {e}') raise Exception(e)
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_}
def get_latest_accepted(db_conn, kind, entity_id): """ Given a kind and an entity_id, pull the latest accepted version out of the database. """ if kind == 'card': card = Card.get_latest_accepted(db_conn, entity_id) return flip_card_into_kind(card) elif kind == 'unit': return Unit.get_latest_accepted(db_conn, entity_id) elif kind == 'set': return Set.get_latest_accepted(db_conn, entity_id)
def get_latest_accepted(kind, entity_id): """ Given a kind and an entity_id, pull the latest accepted version out of the database. """ if kind == 'card': return Card.get_latest_accepted(entity_id) # TODO-1 This needs to also get the right card kind... elif kind == 'unit': return Unit.get_latest_accepted(entity_id) elif kind == 'set': return Set.get_latest_accepted(entity_id)
def instance(data): """ Given a kind and some json, call insert on that kind and return the results. """ if 'card' in data: return Card(data['card']) # TODO-1 This needs to also get the right card kind... elif 'unit' in data: return Unit(data['unit']) elif 'set' in data: return Set(data['set'])
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_}
def instance_new_entity(data): """ Save as above, but a little safer. """ fields = ('id', 'created', 'modified', 'entity_id', 'previous_id', 'status', 'available') if 'card' in data: return Card(omit(data['card'], fields)) # TODO-1 This needs to also get the right card kind... elif 'unit' in data: return Unit(omit(data['unit'], fields)) elif 'set' in data: return Set(omit(data['set'], fields))
def test_traverse(db_conn, units_table, users_table, responses_table, sets_table): """ Expect to take a list of units and traverse them correctly. Basic test. """ add_test_set(db_conn, users_table, units_table, responses_table, sets_table) set_ = Set.get(db_conn, entity_id="set") user = get_user({"id": "user"}, db_conn) buckets = traverse(db_conn, user, set_) assert buckets["diagnose"][0]["entity_id"] == "divide" assert buckets["learn"][0]["entity_id"] == "multiply" assert buckets["review"][0]["entity_id"] == "subtract"
def test_entity(db_conn, sets_table): """ Expect a set to require an entity_id. """ set_, errors = Set.insert({ 'name': 'Statistics', 'body': 'A beginning course focused on probability.', 'members': [{ 'id': 'A', 'kind': 'unit', }] }) assert len(errors) == 0 assert set_['entity_id']
def test_tags(db_conn, sets_table): """ Expect a set to allow tags. """ set_, errors = Set.insert({ 'name': 'Statistics', 'body': 'A beginning course focused on probability.', 'members': [{ 'id': 'A', 'kind': 'unit', }], 'tags': ['A', 'B', 'C'] }) assert len(errors) == 0
def test_previous(db_conn, sets_table): """ Expect a set to allow a previous version id. """ set_, errors = Set.insert({ 'name': 'Statistics', 'body': 'A beginning course focused on probability.', 'members': [{ 'id': 'A', 'kind': 'unit', }], 'previous_id': 'fdsjKO', }) assert len(errors) == 0
def create_entity(data): """ Given a kind and some json, call insert on that kind and return the results. """ if 'card' in data: return Card.insert(data['card']) # TODO-1 This needs to also get the right card kind... elif 'unit' in data: return Unit.insert(data['unit']) elif 'set' in data: return Set.insert(data['set']) return None, []
def test_body(db_conn, sets_table): """ Expect a set to require a body. """ set_, errors = Set.insert({ 'name': 'Statistics', 'members': [{ 'id': 'A', 'kind': 'unit', }], }) assert len(errors) == 1 set_['body'] = 'A beginning course focused on probability.' set_, errors = set_.save() assert len(errors) == 0
def test_traverse(db_conn, units_table, users_table, responses_table, sets_table): """ Expect to take a list of units and traverse them correctly. Basic test. """ add_test_set(db_conn, users_table, units_table, responses_table, sets_table) set_ = Set.get(db_conn, entity_id='set') user = get_user({'id': 'user'}, db_conn) buckets = traverse(db_conn, user, set_) assert buckets['diagnose'][0]['entity_id'] == 'divide' assert buckets['learn'][0]['entity_id'] == 'multiply' assert buckets['review'][0]['entity_id'] == 'subtract'
def test_tags(db_conn, sets_table, units_table): """ Expect a set to allow tags. """ create_unit_a(db_conn, units_table) set_, errors = Set.insert( db_conn, { "name": "Statistics", "body": "A beginning course focused on probability.", "members": [{"id": "A", "kind": "unit"}], "tags": ["A", "B", "C"], }, ) assert len(errors) == 0
def test_previous(db_conn, sets_table, units_table): """ Expect a set to allow a previous version id. """ create_unit_a(db_conn, units_table) set_, errors = Set.insert( db_conn, { "name": "Statistics", "body": "A beginning course focused on probability.", "members": [{"id": "A", "kind": "unit"}], "previous_id": "fdsjKO", }, ) assert len(errors) == 0
def test_language(db_conn, sets_table, units_table): """ Expect a set to require a language. """ create_unit_a(db_conn, units_table) set_, errors = Set.insert( db_conn, { "name": "Statistics", "body": "A beginning course focused on probability.", "members": [{"id": "A", "kind": "unit"}], }, ) assert len(errors) == 0 assert set_["language"] == "en"
def test_traverse(db_conn, units_table, users_table, responses_table, sets_table): """ Expect to take a list of units and traverse them correctly. Basic test. """ add_test_set(db_conn, users_table, units_table, responses_table, sets_table) set_ = Set.get(entity_id='set') user = User.get(id='user') buckets = traverse(user, set_) assert buckets['diagnose'][0]['entity_id'] == 'divide' assert buckets['learn'][0]['entity_id'] == 'multiply' assert buckets['review'][0]['entity_id'] == 'subtract'
def test_language(db_conn, sets_table, units_table): """ Expect a set to require a language. """ create_unit_a(db_conn, units_table) set_, errors = Set.insert(db_conn, { 'name': 'Statistics', 'body': 'A beginning course focused on probability.', 'members': [{ 'id': 'A', 'kind': 'unit', }], }) assert len(errors) == 0 assert set_['language'] == 'en'
def test_members(db_conn, sets_table): """ Expect a set to record a list of members. """ set_, errors = Set.insert({ 'name': 'Statistics', 'body': 'A beginning course focused on probability.', }) assert len(errors) == 1 set_['members'] = [{ 'id': 'A', 'kind': 'unit', }] set_, errors = set_.save() assert len(errors) == 0
def create_or_get_set(self, next=True): """return current set, create next set automatically if next=True""" if self.current_set_number: # current set is on going return self.sets[self.current_set_number] elif next: # get next set number self.current_set_number = max( self.sets.keys()) + 1 if self.sets else 1 is_deciding_set = self.current_set_number == self._best_of self.sets[self.current_set_number] = Set(self, self.current_set_number, is_deciding_set) return self.sets[self.current_set_number] else: return None
def test_name(db_conn, sets_table, units_table): """ Expect a set to require a name. """ create_unit_a(db_conn, units_table) set_, errors = Set.insert(db_conn, { 'body': 'A beginning course focused on probability.', 'members': [{ 'id': 'A', 'kind': 'unit', }], }) assert len(errors) == 1 set_['name'] = 'Statistics' set_, errors = set_.save(db_conn) assert len(errors) == 0
def test_members(db_conn, sets_table, units_table): """ Expect a set to record a list of members. """ create_unit_a(db_conn, units_table) set_, errors = Set.insert(db_conn, { 'name': 'Statistics', 'body': 'A beginning course focused on probability.', }) assert len(errors) == 1 set_['members'] = [{ 'id': 'A', 'kind': 'unit', }] set_, errors = set_.save(db_conn) assert len(errors) == 0
def instance_new_entity(data): """ Given a kind and some json, call insert on that kind and return the results. A little safer. """ fields = ('id', 'created', 'modified', 'entity_id', 'previous_id', 'status', 'available') if 'card' in data: kind = data['card'].get('kind') if kind in card_map: return card_map[kind](omit(data['card'], fields)) elif 'unit' in data: return Unit(omit(data['unit'], fields)) elif 'set' in data: return Set(omit(data['set'], fields))
def test_status(db_conn, sets_table): """ Expect a set status to be a string. """ set_, errors = Set.insert({ 'name': 'Statistics', 'body': 'A beginning course focused on probability.', 'members': [{ 'id': 'A', 'kind': 'unit', }], }) assert len(errors) == 0 assert set_['status'] == 'pending' set_['status'] = 'accepted' set_, errors = set_.save() assert len(errors) == 0
def test_list_by_entity_ids(db_conn, sets_table): """ Expect to list sets by given entity IDs. """ sets_table.insert( [ { "entity_id": "A1", "name": "A", "body": "Apple", "created": r.now(), "modified": r.now(), "status": "accepted", }, { "entity_id": "B2", "name": "B", "body": "Banana", "created": r.now(), "modified": r.now(), "status": "accepted", }, { "entity_id": "C3", "name": "C", "body": "Coconut", "created": r.now(), "modified": r.now(), "status": "accepted", }, { "entity_id": "D4", "name": "D", "body": "Date", "created": r.now(), "modified": r.now(), "status": "accepted", }, ] ).run(db_conn) sets = Set.list_by_entity_ids(db_conn, ["A1", "C3"]) assert sets[0]["body"] in ("Apple", "Coconut") assert sets[0]["body"] in ("Apple", "Coconut")
def add_set_route(request, user_id, set_id): """ Add a set to the learner's list of sets. """ 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) set_ = Set.get(db_conn, entity_id=set_id) if not set_: return abort(404) uset = UserSets.get(db_conn, user_id=user_id) if uset and set_id in uset['set_ids']: return 400, { 'errors': [{ 'name': 'set_id', 'message': 'Set is already added.', }], 'ref': 'kPZ95zM3oxFDGGl8vBdR3J3o', } if uset: uset['set_ids'].append(set_id) uset, errors = uset.save(db_conn) else: uset, errors = UserSets.insert(db_conn, { 'user_id': user_id, 'set_ids': [set_id], }) if errors: return 400, { 'errors': errors, 'ref': 'zCFUbLBTg9n2DnTkQYbqO4X9' } return 200, {'sets': uset['set_ids']}
def test_status(db_conn, sets_table, units_table): """ Expect a set status to be a string. """ create_unit_a(db_conn, units_table) set_, errors = Set.insert( db_conn, { "name": "Statistics", "body": "A beginning course focused on probability.", "members": [{"id": "A", "kind": "unit"}], }, ) assert len(errors) == 0 assert set_["status"] == "pending" set_["status"] = "accepted" set_, errors = set_.save(db_conn) assert len(errors) == 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'), }
def add_set_route(request, user_id, set_id): """ Add a set to the learner's list of sets. """ 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) set_ = Set.get(db_conn, entity_id=set_id) if not set_: return abort(404) uset = get_user_sets(user_id, db_conn) if uset and set_id in uset['set_ids']: return 400, { 'errors': [{ 'name': 'set_id', 'message': 'Set is already added.', }], 'ref': 'kPZ95zM3oxFDGGl8vBdR3J3o', } # TODO-2 move some of this logic to the database file if uset: uset, errors = append_user_sets(user_id, set_id, db_conn) else: uset, errors = insert_user_sets( { 'user_id': user_id, 'set_ids': [set_id], }, db_conn) if errors: return 400, {'errors': errors, 'ref': 'zCFUbLBTg9n2DnTkQYbqO4X9'} return 200, {'sets': uset['set_ids']}
def flush_entities(descs): """ Given a list of kinds and entity_ids, return a list filled out with entities. """ output = [] for desc in descs: if desc['kind'] == 'card': output.append(Card.get_latest_accepted(entity_id=desc['id'])) # TODO-1 This needs to also get the right card kind... elif desc['kind'] == 'unit': output.append(Unit.get_latest_accepted(entity_id=desc['id'])) elif desc['kind'] == 'set': output.append(Set.get_latest_accepted(entity_id=desc['id'])) else: output.append(None) return output