def __init__(self, app: Flask): app.config["MONGO_URI"] = "mongodb://localhost:27017/unigames_webapp_db" self.mongo = PyMongo(app) self.fs = GridFS(self.mongo.db, 'fs') Tag.init_indices(self.mongo) AttributeOption.init_indices(self.mongo) Item.init_indices(self.mongo) Instance.init_indices(self.mongo) Role.init_indices(self.mongo) RelationOption.init_indices(self.mongo) Relation.init_indices(self.mongo) User.init_indices(self.mongo) # For actual production, to ensure certain attributes exist # create an attribute for a name self.name_attrib = AttributeOption.search_for_by_name(self.mongo, "name") if self.name_attrib is None: self.name_attrib = AttributeOption("name", AttributeTypes.SingleLineString) self.name_attrib.write_to_db(self.mongo) # create an attribute for a description self.description_attrib = AttributeOption.search_for_by_name(self.mongo, "description") if self.description_attrib is None: self.description_attrib = AttributeOption("description", AttributeTypes.MultiLineString) self.description_attrib.write_to_db(self.mongo) # create an attribute for a hidden description self.hidden_description_attrib = AttributeOption.search_for_by_name(self.mongo, "hidden_description") if self.hidden_description_attrib is None: self.hidden_description_attrib = AttributeOption("hidden_description", AttributeTypes.MultiLineString, True) self.hidden_description_attrib.write_to_db(self.mongo) # create an attribute for the main picture on an item/instance self.main_picture = AttributeOption.search_for_by_name(self.mongo, "main_picture") if self.main_picture is None: self.main_picture = AttributeOption("main_picture", AttributeTypes.Picture, True) self.main_picture.write_to_db(self.mongo) self.everyone_role = Role.search_for_by_name(self.mongo, "everyone") if self.everyone_role is None: # -1 is overridden by everything, 'everyone' is required for sake of a default self.everyone_role = Role("everyone", -1, {Permissions.CanEditItems: False, Permissions.CanEditUsers: False, Permissions.CanViewHidden: False}) self.everyone_role.write_to_db(self.mongo) self.admin_role = Role.search_for_by_name(self.mongo, "admin") if self.admin_role is None: # 0 overrides everything self.admin_role = Role("admin", 0, {Permissions.CanEditItems: True, Permissions.CanEditUsers: True, Permissions.CanViewHidden: True}) self.admin_role.write_to_db(self.mongo) self.test_role = Role.search_for_by_name(self.mongo, "testing") if self.test_role is None: # 0 overrides everything self.test_role = Role("testing", 0, {Permissions.CanEditItems: True, Permissions.CanEditUsers: True, Permissions.CanViewHidden: True}) self.test_role.write_to_db(self.mongo)
def __init__(self, app: Flask): app.config[ "MONGO_URI"] = "mongodb://localhost:27017/unigames_webapp_db" self.mongo = PyMongo(app) Tag.init_indices(self.mongo) AttributeOption.init_indices(self.mongo) Item.init_indices(self.mongo) Instance.init_indices(self.mongo) Role.init_indices(self.mongo) RelationOption.init_indices(self.mongo) Relation.init_indices(self.mongo)
def recalculate_instance_implied_tags(self, mongo: PyMongo, index: Optional[Union[int, List[int]]] = None): """ Recalculates the implied tags for instances Parameters ---------- mongo The mongo database index Returns ------- True if successfull, False otherwise """ if not self.update_from_db(mongo): return False if index is None: to_visit = range(0, len(self.instances)) elif isinstance(index, int): to_visit = [index] else: to_visit = index for i in to_visit: inst = self.instances[i] # get implied from relations relations = mongo.db.relations.find({"instance_id": inst.id}) relations = [Relation.from_dict(r) for r in relations] relation_options = mongo.db.relation_options.find({"_id": {"$in": [r.option_id for r in relations]}}) relation_options = [RelationOption.from_dict(r) for r in relation_options] inst.implied_tags = [implied for option in relation_options for implied in option.implies] # traverse implication DAG to_search = set(t.tag_id for t in inst.tags).union(t.tag_id for t in inst.implied_tags) searched = set(to_search) while to_search: top_level = mongo.db.tags.find({"_id": {"$in": list(to_search)}}) to_search = set() if top_level is None: break tags = [Tag.from_dict(tag) for tag in top_level] for tag in tags: for implied in tag.implies: if implied.tag_id not in searched: searched.add(implied.tag_id) to_search.add(implied.tag_id) inst.implied_tags.append(implied) self.write_to_db(mongo) return True
def recalculate_implied_tags(self, mongo: PyMongo): self.update_from_db(mongo) self.implied_tags = [] # get implied from relations relations = mongo.db.relations.find({"instance_id": self.id}) relations = [Relation.from_dict(r) for r in relations] relation_options = mongo.db.relation_options.find({"_id": {"$in": [r.option_id for r in relations]}}) relation_options = [RelationOption.from_dict(r) for r in relation_options] relation_implied: Dict[ObjectId, Dict[int, TagParameterImpl]] = {} for ro in relation_options: for implied in ro.implies: if implied.implied_id not in relation_implied: relation_implied[implied.implied_id] = {} for para in implied.parameters: relation_implied[implied.implied_id][para.index] = para for r in relations: for implied in r.implies: if implied.implied_id not in relation_implied: relation_implied[implied.implied_id] = {} for para in implied.parameters: relation_implied[implied.implied_id][para.index] = para self.implied_tags = [TagReference(implied_id, [p for p in parameters.values()]) for implied_id, parameters in relation_implied.items()] # traverse implication DAG to_search = set(t.tag_id for t in self.tags).union(t.tag_id for t in self.implied_tags) searched = set(to_search) while to_search: top_level = mongo.db.tags.find({"_id": {"$in": list(to_search)}}) to_search = set() if top_level is None: break tags = [Tag.from_dict(tag) for tag in top_level] for tag in tags: for implied in tag.implies: if implied.implied_id not in searched: searched.add(implied.implied_id) to_search.add(implied.implied_id) self.implied_tags.append(TagReference(implied.implied_id, implied.parameters)) self.write_to_db(mongo)
def recalculate_implied_tags(self, mongo: PyMongo, instances: bool = False, inherit: bool = True): if instances: self.recalculate_instance_implied_tags(mongo, None) else: if not self.update_from_db(mongo): return False self.implied_tags = [] # get implied from relations relations = mongo.db.relations.find({"item_id": self.id}) relations = [Relation.from_dict(r) for r in relations] relation_options = mongo.db.relation_options.find({"_id": {"$in": [r.option_id for r in relations]}}) relation_options = [RelationOption.from_dict(r) for r in relation_options] self.implied_tags = [implied for option in relation_options for implied in option.implies] # traverse implication DAG to_search = set(t.tag_id for t in self.tags).union(t.tag_id for t in self.implied_tags) searched = set(to_search) while to_search: top_level = mongo.db.tags.find({"_id": {"$in": list(to_search)}}) to_search = set() if top_level is None: break tags = [Tag.from_dict(tag) for tag in top_level] for tag in tags: for implied in tag.implies: if implied.tag_id not in searched: searched.add(implied.tag_id) to_search.add(implied.tag_id) self.implied_tags.append(implied) if inherit: possibilities = set() for inst in self.instances: possibilities.intersection_update(set(inst.tags).union(inst.implied_tags)) self.implied_tags.extend(possibilities) self.write_to_db(mongo) return True
def recalculate_implied_tags(self, mongo: PyMongo, instances: bool = False, inherit: bool = True): """ Recalculates the implied tags Parameters ---------- mongo The mongo database instances If true, then also recalculate the implied of all the instances inherit If true and a tag is on all instances of an object it will be implied on the item Returns ------- True if successfull, False otherwise """ if instances: self.recalculate_instance_implied_tags(mongo, None) else: if not self.update_from_db(mongo): return False self.implied_tags = [] # get implied from relations relations = mongo.db.relations.find({"item_id": self.id}) relations = [Relation.from_dict(r) for r in relations] relation_options = mongo.db.relation_options.find({"_id": {"$in": [r.option_id for r in relations]}}) relation_options = [RelationOption.from_dict(r) for r in relation_options] self.implied_tags = [implied for option in relation_options for implied in option.implies] # traverse implication DAG to_search = set(t.tag_id for t in self.tags).union(t.tag_id for t in self.implied_tags) searched = set(to_search) while to_search: top_level = mongo.db.tags.find({"_id": {"$in": list(to_search)}}) to_search = set() if top_level is None: break tags = [Tag.from_dict(tag) for tag in top_level] for tag in tags: for implied in tag.implies: if implied.tag_id not in searched: searched.add(implied.tag_id) to_search.add(implied.tag_id) self.implied_tags.append(implied) if inherit: possibilities = set() for inst in self.instances: possibilities.intersection_update(set(inst.tags).union(inst.implied_tags)) self.implied_tags.extend(possibilities) self.write_to_db(mongo) return True
def test(self): #create a book tag book_tag = Tag.search_for_by_name(self.mongo, "Book") if book_tag is None: book_tag = Tag("Book", [], []) book_tag.write_to_db(self.mongo) #create a multiplayer tag multiplayer_tag = Tag.search_for_by_name(self.mongo, "Multiplayer") if multiplayer_tag is None: multiplayer_tag = Tag("Multiplayer", [], []) multiplayer_tag.write_to_db(self.mongo) #create a player number tag players_tag = Tag.search_for_by_name(self.mongo, "Players: {}") if players_tag is None: players_tag = Tag("Players: {}", [TagParameter.new_integer_range(0, 2, None)], [TagImplication(multiplayer_tag.id, [])]) players_tag.write_to_db(self.mongo) #create a damaged tag damaged_tag = Tag.search_for_by_name(self.mongo, "Damaged") if damaged_tag is None: damaged_tag = Tag("Damaged", [], []) damaged_tag.write_to_db(self.mongo) #create an added by tag added_by_tag = Tag.search_for_by_name(self.mongo, "Added By: {}") if added_by_tag is None: added_by_tag = Tag("Added By: {}", [TagParameter.new_string(0)], []) added_by_tag.write_to_db(self.mongo) #create a borrowed by tag borrowed_by_tag = Tag.search_for_by_name(self.mongo, "Borrowed By: {}") if borrowed_by_tag is None: borrowed_by_tag = Tag("Borrowed By: {}", [TagParameter.new_string(0)], []) borrowed_by_tag.write_to_db(self.mongo) #create a None tag (all root tags point to this tag for easier management) root_tag = Tag.search_for_by_name(self.mongo, "None") if root_tag is None: root_tag = Tag("None", [], []) root_tag.write_to_db(self.mongo) #create an attribute for name item_name_attrib = AttributeOption.search_for_by_name( self.mongo, "name") if item_name_attrib is None: item_name_attrib = AttributeOption("name", AttributeTypes.SingleLineString) item_name_attrib.write_to_db(self.mongo) #create an attribute for author item_author_attrib = AttributeOption.search_for_by_name( self.mongo, "author") if item_author_attrib is None: item_author_attrib = AttributeOption( "author", AttributeTypes.SingleLineString) item_author_attrib.write_to_db(self.mongo) #create an attribute for description item_description_attrib = AttributeOption.search_for_by_name( self.mongo, "description") if item_description_attrib is None: item_description_attrib = AttributeOption( "description", AttributeTypes.MultiLineString) item_description_attrib.write_to_db(self.mongo) #search for item by its name attribute bob_book_item = Item.search_for_by_attribute(self.mongo, item_name_attrib, "Bob's Grand Adventure") #create a new item if no search result returned if not bob_book_item: bob_book_item = Item( { "name": "Bob's Grand Adventure", "author": "Mingchuan Tian" }, [ TagReference(book_tag.id, []), TagReference(players_tag.id, [ TagParameterImpl.new_integer_range( players_tag.parameters[0], 3, 5) ]) ]) bob_book_item.write_to_db(self.mongo) else: bob_book_item = bob_book_item[0] #recalculates all implied tags for the item bob_book_item.recalculate_implied_tags(self.mongo) print("Multiplayer items: " + str(Item.search_for_by_tag_id(self.mongo, multiplayer_tag.id))) #search for the uuid attribute instance_uuid_attrib = AttributeOption.search_for_by_name( self.mongo, "uuid") #if none returned, create a new uuid attribute if instance_uuid_attrib is None: instance_uuid_attrib = AttributeOption( "uuid", AttributeTypes.SingleLineString) instance_uuid_attrib.write_to_db(self.mongo) #search for the Damage Report attribute instance_damage_report_attrib = AttributeOption.search_for_by_name( self.mongo, "Damage Report") #if none returned, create a Damage Report attribute if instance_damage_report_attrib is None: instance_damage_report_attrib = AttributeOption( "Damage Report", AttributeTypes.MultiLineString) instance_damage_report_attrib.write_to_db(self.mongo) #search for an instance with uuid 1093.. bob_book_instance_1 = Instance.search_for_by_attribute( self.mongo, instance_uuid_attrib, "109358180") #if none returned, create a new instance with further info if not bob_book_instance_1: bob_book_instance_1 = Instance( bob_book_item.id, { "uuid": "109358180", "Damage Report": "(4/5/2017): Page 57 has a small section of the top right corner torn off, no text missing, still serviceable" }, [TagReference(damaged_tag.id, [])]) bob_book_instance_1.write_to_db(self.mongo) else: bob_book_instance_1 = bob_book_instance_1[0] #recalculate implied tags for instance bob_book_instance_1.recalculate_implied_tags(self.mongo) #search for a damaged item print("Damaged items /w Instance: " + str( Item.search_for_by_tag_id_with_instance(self.mongo, damaged_tag.id))) print("Damaged items /w Common Instance: " + str( Item.search_for_by_tag_id_with_common_instance( self.mongo, damaged_tag.id))) bob_book_instance_2 = Instance.search_for_by_attribute( self.mongo, instance_uuid_attrib, "109358181") if not bob_book_instance_2: bob_book_instance_2 = Instance(bob_book_item.id, {"uuid": "109358181"}, []) bob_book_instance_2.write_to_db(self.mongo) else: bob_book_instance_2 = bob_book_instance_2[0] bob_book_instance_2.recalculate_implied_tags(self.mongo) print("Damaged items /w Instance: " + str( Item.search_for_by_tag_id_with_instance(self.mongo, damaged_tag.id))) print("Damaged items /w Common Instance: " + str( Item.search_for_by_tag_id_with_common_instance( self.mongo, damaged_tag.id))) everyone_role = Role.search_for_by_name(self.mongo, "everyone") if everyone_role is None: # -1 is overridden by everything, an 'everyone' is required for sake of a default everyone_role = Role("everyone", -1, { Permissions.CanEditItems: False, Permissions.CanEditUsers: False }) everyone_role.write_to_db(self.mongo) admin_role = Role.search_for_by_name(self.mongo, "admin") if admin_role is None: # 0 overrides everything admin_role = Role("admin", 0, { Permissions.CanEditItems: True, Permissions.CanEditUsers: True }) admin_role.write_to_db(self.mongo) added_by_item_relation = RelationOption.search_for_by_name( self.mongo, "Added") if added_by_item_relation is None: added_by_item_relation = RelationOption("Added", [ TagImplication(added_by_tag.id, [ TagParameterImpl.new_needs_override( added_by_tag.parameters[0]) ]) ]) added_by_item_relation.write_to_db(self.mongo) borrowing_item_relation = RelationOption.search_for_by_name( self.mongo, "Borrowing") if borrowing_item_relation is None: borrowing_item_relation = RelationOption("Borrowing", [ TagImplication(borrowed_by_tag.id, [ TagParameterImpl.new_needs_override( borrowed_by_tag.parameters[0]) ]) ]) borrowing_item_relation.write_to_db(self.mongo) matthew_user = User.search_for_by_display_name(self.mongo, "Matthew") if matthew_user is None: matthew_user = User("Matthew", [admin_role.id]) matthew_user.write_to_db(self.mongo) matthew_bob_book_added_relation = Relation.search_for_by_item_id( self.mongo, bob_book_item.id) if not matthew_bob_book_added_relation: matthew_bob_book_added_relation = Relation.new_item( matthew_user.id, added_by_item_relation.id, bob_book_item.id, [ TagImplication(added_by_tag.id, [ TagParameterImpl.new_string(added_by_tag.parameters[0], "Matthew") ]) ]) matthew_bob_book_added_relation.write_to_db(self.mongo) else: matthew_bob_book_added_relation = matthew_bob_book_added_relation[ 0] matthew_bob_borrow_added_relation = Relation.search_for_by_instance_id( self.mongo, bob_book_instance_2.id) if not matthew_bob_borrow_added_relation: matthew_bob_borrow_added_relation = Relation.new_instance( matthew_user.id, borrowing_item_relation.id, bob_book_instance_2.id, [ TagImplication(borrowed_by_tag.id, [ TagParameterImpl.new_string( borrowed_by_tag.parameters[0], "Matthew") ]) ]) matthew_bob_borrow_added_relation.write_to_db(self.mongo) else: matthew_bob_borrow_added_relation = matthew_bob_borrow_added_relation[ 0] bob_book_instance_1.recalculate_implied_tags(self.mongo) bob_book_instance_2.recalculate_implied_tags(self.mongo) bob_book_item.recalculate_implied_tags(self.mongo)
def test(self): # create a book tag book_tag = Tag.search_for_by_name(self.mongo, "Book") if book_tag is None: book_tag = Tag("Book", []) book_tag.write_to_db(self.mongo) # create a multiplayer tag multiplayer_tag = Tag.search_for_by_name(self.mongo, "Multiplayer") if multiplayer_tag is None: multiplayer_tag = Tag("Multiplayer", []) multiplayer_tag.write_to_db(self.mongo) # create a player 1 tag players_tag_1 = Tag.search_for_by_name(self.mongo, "Players: 1") if players_tag_1 is None: players_tag_1 = Tag("Players: 1", []) players_tag_1.write_to_db(self.mongo) # create a player 2 tag players_tag_2 = Tag.search_for_by_name(self.mongo, "Players: 2") if players_tag_2 is None: players_tag_2 = Tag("Players: 2", [TagReference(multiplayer_tag)]) players_tag_2.write_to_db(self.mongo) # create a player 3 tag players_tag_3 = Tag.search_for_by_name(self.mongo, "Players: 3") if players_tag_3 is None: players_tag_3 = Tag("Players: 3", [TagReference(multiplayer_tag)]) players_tag_3.write_to_db(self.mongo) # create a player 4 tag players_tag_4 = Tag.search_for_by_name(self.mongo, "Players: 4") if players_tag_4 is None: players_tag_4 = Tag("Players: 4", [TagReference(multiplayer_tag)]) players_tag_4.write_to_db(self.mongo) # create a player 5 tag players_tag_5 = Tag.search_for_by_name(self.mongo, "Players: 5") if players_tag_5 is None: players_tag_5 = Tag("Players: 5", [TagReference(multiplayer_tag)]) players_tag_5.write_to_db(self.mongo) # create a player 6 tag players_tag_6 = Tag.search_for_by_name(self.mongo, "Players: 6") if players_tag_6 is None: players_tag_6 = Tag("Players: 6", [TagReference(multiplayer_tag)]) players_tag_6.write_to_db(self.mongo) # create a damaged tag damaged_tag = Tag.search_for_by_name(self.mongo, "Damaged") if damaged_tag is None: damaged_tag = Tag("Damaged", []) damaged_tag.write_to_db(self.mongo) # create a borrowed out tag borrowed_out_tag = Tag.search_for_by_name(self.mongo, "Borrowed Out") if borrowed_out_tag is None: borrowed_out_tag = Tag("Borrowed Out", []) borrowed_out_tag.write_to_db(self.mongo) # create a None tag (all root tags point to this tag for easier management) root_tag = Tag.search_for_by_name(self.mongo, "None") if root_tag is None: root_tag = Tag("None", []) root_tag.write_to_db(self.mongo) # load image from disk, normally one would upload it from the website test_image = self.fs.find_one({"filename": "dungeons.jpg"}) if test_image is None: with open("../frontend/games-img/dungeons.jpg", "rb") as f: test_image = self.fs.put(f, filename="dungeons.jpg", content_type='image/jpg') else: test_image = test_image._id # search for item by its name attribute bob_book_item = Item.search_for_by_attribute(self.mongo, self.name_attrib, "Bob's Grand Adventure") # create a new item if no search result returned if not bob_book_item: bob_book_item = Item([ SingleLineStringAttribute(self.name_attrib, "Bob's Grand Adventure"), MultiLineStringAttribute(self.description_attrib, ["No Description"]), PictureAttribute(self.main_picture, test_image) ], [ TagReference(book_tag), TagReference(players_tag_3), TagReference(players_tag_4), TagReference(players_tag_5) ], []) bob_book_item.instances.append( Instance([ MultiLineStringAttribute( self.description_attrib, ["No Description", "uuid: 109358180"]), MultiLineStringAttribute(self.hidden_description_attrib, [ "Damage Report: (4/5/2017): Page 57 has a small section of the top right corner torn off, no text missing, still serviceable" ]) ], [TagReference(damaged_tag)], True)) bob_book_item.instances.append( Instance([ MultiLineStringAttribute( self.description_attrib, ["No Description", "uuid: 109358181"]) ], [])) bob_book_item.write_to_db(self.mongo) else: bob_book_item = bob_book_item[0] # search for item by its name attribute steve_hidden_book_item = Item.search_for_by_attribute( self.mongo, self.name_attrib, "Steve's Grand Adventure") # create a new item if no search result returned if not steve_hidden_book_item: steve_hidden_book_item = Item([ SingleLineStringAttribute(self.name_attrib, "Steve's Grand Adventure") ], [TagReference(book_tag), TagReference(players_tag_4)], [], True) steve_hidden_book_item.instances.append( Instance([ MultiLineStringAttribute( self.description_attrib, ["No Description", "uuid: 109354180"]) ], [])) steve_hidden_book_item.instances.append( Instance([ MultiLineStringAttribute( self.description_attrib, ["No Description", "uuid: 109354181"]) ], [])) steve_hidden_book_item.write_to_db(self.mongo) else: steve_hidden_book_item = steve_hidden_book_item[0] # recalculates all implied tags for the item and instances bob_book_item.recalculate_implied_tags(self.mongo, True) borrowing_item_relation = RelationOption.search_for_by_name( self.mongo, "Borrowing") if borrowing_item_relation is None: borrowing_item_relation = RelationOption( "Borrowing", [TagReference(borrowed_out_tag)]) borrowing_item_relation.write_to_db(self.mongo) emptycheck = self.mongo.db.users.count() default_user = User.search_for_by_display_name(self.mongo, "DefaultAdmin") if emptycheck == 0: default_user = User("DefaultAdmin", [self.admin_role.id], "*****@*****.**", generate_password_hash("password"), "Test", "LastTest") default_user.write_to_db(self.mongo) # this code should never be needed normally, this is modeling a human performing this action, if you want to automate this properlly then properlly add a uuid attribute inst_0_id = [ inst for inst in bob_book_item.instances if len([ a for a in inst.attributes if isinstance(a, MultiLineStringAttribute) and len([ line for line in a.value if line.find("uuid: 109358180") != -1 ]) != 0 ]) != 0 ][0].id inst_1_id = [ inst for inst in bob_book_item.instances if len([ a for a in inst.attributes if isinstance(a, MultiLineStringAttribute) and len([ line for line in a.value if line.find("uuid: 109358181") != -1 ]) != 0 ]) != 0 ][0].id matthew_bob_borrow_relation = Relation.search_for_by_instance_id( self.mongo, inst_1_id) if not matthew_bob_borrow_relation: matthew_bob_borrow_relation = Relation.new_instance( default_user.id, borrowing_item_relation.id, inst_1_id) matthew_bob_borrow_relation.write_to_db(self.mongo) else: matthew_bob_borrow_relation = matthew_bob_borrow_relation[0] bob_book_item.recalculate_implied_tags(self.mongo, True) #Page load testing '''