def load_skills(sm: SmithyDB, filepath: str): """ Loads skill information from a properly-formatted tsv file, then adds it to the database. :param sm: The database object to operate on. :param filepath: The path to the desired .csv file. :return: """ if path.exists(filepath): with open(filepath) as skilltsv: columns = skilltsv.readline() data = skilltsv.readlines() skills = [] skilldesc = [] for entry in data: entry = entry.strip().split('\t') name = entry[0] skilllv = entry[2][0] skills.append((name, skilllv)) #sm.add_skills(skills) for entry in data: entry = entry.strip().split('\t') name = entry[0] skillnu = sm.get_skills_by_name([(name, )]) desc = entry[3] skilldesc.append((skillnu[0][0], desc)) sm.add_skill_desc(skilldesc) else: print("The path to the .tsv file does not exist.")
def write_charms(charms: dict, filename: str): """ Write a dictionary describing charms to a tsv file. :param charms: A dictionary specifying the charms :param filename: The name of the file to write to :return: None """ sm = SmithyDB(PASSFILE) with open(filename, 'w') as testcharms: cols = "Name\tUserId\tSlots\tSkill1\tSkill2\tSkill3\tSkill4\n" testcharms.write(cols) for ch in charms.values(): name = ch["name"] usr = ch["uid"] slots = (str(ch["sslots"])+str(ch["mslots"])+str(ch["lslots"])).replace("0", "-") skills = [] for i in range(1, 5): if ch["skillnum"+str(i)] != None: skilldet = sm.get_skill(ch["skillnum"+str(i)])[0] skills.append(skilldet[1] + " Lv. " + str(ch["skillval"+str(i)])) else: skills.append("") line = "{}\t{}\t{}\t{}\t{}\t{}\n".format(name, usr, slots, skills[0], skills[1], skills[2], skills[3]).strip() testcharms.write(line + "\n")
def load_charms(sm: SmithyDB, filepath: str): """ A method to add a set of charms given by a tsv file to the charm database. :param sm: The database object to operate on. :param filepath: a path to the charm tsv file :return: """ if path.exists(filepath): with open(filepath) as charmtsv: columns = charmtsv.readline() data = charmtsv.readlines() charms = [] for entry in data: entry = entry.strip().split('\t') name = entry[0] usrid = entry[1] slots = entry[2].replace('-', '0') slots1 = slots[0] slots2 = slots[1] slots3 = slots[2] skills = [] if len(entry) > 3: for i in range(3, len(entry)): skni = entry[i].split('Lv.')[0].strip() skidi = sm.get_skills_by_name([(skni, )]) skvi = entry[i].split('Lv.')[1].strip() skills.append((skidi[0][0], skvi)) for i in range(7 - len(entry)): skills.append((None, 0)) sm.add_charm(name, usrid, slots1, slots2, slots3, skills[0][0], skills[0][1], skills[1][0], skills[1][1], skills[2][0], skills[2][1], skills[3][0], skills[3][1])
def gen_charms(n: int): """ Generate a set of n random valid charms. :param n: The number of charms to generate. :return: A dictionary of charms """ sm = SmithyDB(PASSFILE) Faker.seed(0) fake = Faker() charms = {} for i in range(n): name = "test" + fake.pystr(min_chars=5, max_chars=10) uid = fake.pyint(min_value=pow(10, 17), max_value=pow(10, 18)) # Discord user Id's are 17 or 18 digits long sslots = fake.pyint(min_value=0, max_value=3) mslots = fake.pyint(min_value=0, max_value=3) lslots = fake.pyint(min_value=0, max_value=3) num_skills = fake.pyint(min_value=1, max_value=4) skills = [] for _ in range(num_skills): skillnu = fake.pyint(min_value=1, max_value=104) skillva = fake.pyint(min_value=1, max_value=sm.get_skill(skillnu)[0][2]) skills.append((skillnu, skillva)) charms["Charm " + str(i)] = {} charms["Charm " + str(i)]["name"] = name charms["Charm " + str(i)]["uid"] = uid charms["Charm " + str(i)]["sslots"] = sslots charms["Charm " + str(i)]["mslots"] = mslots charms["Charm " + str(i)]["lslots"] = lslots for j in range(num_skills): charms["Charm " + str(i)]["skillnum" + str(j+1)] = skills[j][0] charms["Charm " + str(i)]["skillval" + str(j+1)] = skills[j][1] for k in range(num_skills, 4): charms["Charm " + str(i)]["skillnum" + str(k+1)] = None charms["Charm " + str(i)]["skillval" + str(k+1)] = 0 return charms
def load_decos(sm: SmithyDB, filepath: str): """ A method to add a list of decorations from a given file into the deco table :param sm: The database object to operate on. :param filepath: a path to the file to use. :return: None """ if path.exists(filepath): with open(filepath) as decotsv: columns = decotsv.readline() data = decotsv.readlines() decos = [] for entry in data: entry = entry.strip().split('\t') name = entry[0] slotSize = entry[1] skni = entry[2].split('Lv.')[0].strip() skidi = sm.get_skills_by_name([(skni, )])[0][0] skvi = entry[2].split('Lv.')[1].strip() decos.append((name, slotSize, skidi, skvi)) sm.add_deco(decos)
def load_armor(sm: SmithyDB, filepath: str): """ Loads in armor data from a tsv file. Sorts loaded armors by type, then adds each to their repective tables. :param sm: The database object to operate on. :param filepath: a path to the armor tsv file :return: None """ if path.exists(filepath): with open(filepath) as armortsv: columns = armortsv.readline() data = armortsv.readlines() helms = [] chests = [] vambraces = [] faulds = [] greaves = [] for entry in data: entry = entry.strip().split('\t') name = entry[0] slots = entry[1].replace('-', '0') slots1 = slots[0] slots2 = slots[1] slots3 = slots[2] skills = [] if len(entry) > 2: for i in range(2, len(entry)): skni = entry[i].split('Lv.')[0].strip() skidi = sm.get_skills_by_name([skni]) skvi = entry[i].split('Lv.')[1].strip() skills.append((skidi[0][0], skvi)) for i in range(6 - len(entry)): skills.append((None, 0)) armtype = re.sub(r" \bS\b", "", name).strip().split(' ')[-1] if armtype in HELM_NAMES: helms.append( (name, slots1, slots2, slots3, skills[0][0], skills[0][1], skills[1][0], skills[1][1], skills[2][0], skills[2][1], skills[3][0], skills[3][1])) elif armtype in CHEST_NAMES: chests.append( (name, slots1, slots2, slots3, skills[0][0], skills[0][1], skills[1][0], skills[1][1], skills[2][0], skills[2][1], skills[3][0], skills[3][1])) elif armtype in VAMBRACE_NAMES: vambraces.append( (name, slots1, slots2, slots3, skills[0][0], skills[0][1], skills[1][0], skills[1][1], skills[2][0], skills[2][1], skills[3][0], skills[3][1])) elif armtype in FAULD_NAMES: faulds.append( (name, slots1, slots2, slots3, skills[0][0], skills[0][1], skills[1][0], skills[1][1], skills[2][0], skills[2][1], skills[3][0], skills[3][1])) elif armtype in GREAVE_NAMES: greaves.append( (name, slots1, slots2, slots3, skills[0][0], skills[0][1], skills[1][0], skills[1][1], skills[2][0], skills[2][1], skills[3][0], skills[3][1])) else: print("This armor type is not yet handled: {}".format(armtype)) return sm.add_armors('helm', helms) sm.add_armors('chest', chests) sm.add_armors('vambraces', vambraces) sm.add_armors('faulds', faulds) sm.add_armors('greaves', greaves) else: print("The path to the .tsv file does not exist.")
decos = [] for entry in data: entry = entry.strip().split('\t') name = entry[0] slotSize = entry[1] skni = entry[2].split('Lv.')[0].strip() skidi = sm.get_skills_by_name([(skni, )])[0][0] skvi = entry[2].split('Lv.')[1].strip() decos.append((name, slotSize, skidi, skvi)) sm.add_deco(decos) if __name__ == "__main__": loadtype = sys.argv[1] loadpath = sys.argv[2] sm = SmithyDB(PASSFILE) if loadtype == "skill": load_skills(sm, loadpath) elif loadtype == "armor": load_armor(sm, loadpath) elif loadtype == "charm": load_charms(sm, loadpath) elif loadtype == "deco": load_decos(sm, loadpath) else: print("The given type of element cannot be loaded.") print("Input should be of the form, 'python loaddata.py [type] [path]") print("Available types: 'armor', 'skill', 'charm'") print("Program exited correctly.")
def __init__(self, info: str): self.armordb = SmithyDB(info)
class QueryProcessor: armordb = None def __init__(self, info: str): self.armordb = SmithyDB(info) def __del__(self): pass def add_user_charm(self, charminfo: dict, uid: int): """ Adds a charm to the database from the user's given skills and other info. :param charminfo: a dictionary of charm parameters :param uid: the user's Discord Id :return: None """ try: skill_names = [charminfo["skill1Name"], charminfo["skill2Name"], charminfo["skill3Name"], charminfo["skill4Name"]] skill_data = self.armordb.get_skills_by_name(skill_names) skill_ids = [s[0] for s in skill_data] + [None for i in range(len(skill_data), 4)] self.armordb.add_charm(charminfo["name"], uid, charminfo["slot1"], charminfo["slot2"], charminfo["slot3"], skill_ids[0], charminfo["skill1Val"], skill_ids[1], charminfo["skill2Val"], skill_ids[2], charminfo["skill3Val"], skill_ids[3], charminfo["skill4Val"]) except ValueError as err: print("Charm was unable to be added to the database.") def remove_user_charm(self, charm_name: str, uid: int): """ Removes a given charm from the database of a user. :param charm_name: The name of the charm to remove :param uid: the user's Discord Id :return: None """ try: self.armordb.delete_charm(charm_name, uid) except ValueError as err: print("The given charm was not removed from the database.") def modify_user_charm(self, charm_name: str, uid : int, value_to_modify: str, new_val): """ Modifies an existing user charm. :param charm_name: The name of the charm to modify :param uid: The Discord User Id :param value_to_modify: the name of the column to modify :param new_val: the new value to place in the column :return: None. """ try: if value_to_modify == 'slots': self.armordb.update_charm(charm_name, uid, 'slot1', new_val[0]) self.armordb.update_charm(charm_name, uid, 'slot2', new_val[1]) self.armordb.update_charm(charm_name, uid, 'slot3', new_val[2]) elif value_to_modify == 'skill': skill_index = new_val[0] new_skill = new_val[1] skill_id = self.armordb.get_skills_by_name([new_skill])[0][0] new_skill_val = new_val[2] self.armordb.update_charm(charm_name, uid, 'skill'+str(skill_index)+'Id', skill_id) self.armordb.update_charm(charm_name, uid, 'skill'+str(skill_index)+'Val', new_skill_val) except ValueError as err: print("Charm was unable to be modified.") def search_armor_set(self, skills: dict, uid: int, num_results: int = 4, returned_results: int = 1): """ Generates an optimized armor set for the given set of skills :param skills: a dictionary of skills to search for :param uid: the Discord user's Id. :param num_results: the number of elements to include in the search. Default value is 4 :param returned_results: the number of results to return. default is 1. :return: armor_sets: A list of dictionaries specifying the armor set and its decorations. """ try: skill_names = [k for k in skills.keys()] skill_data = self.armordb.get_skills_by_name(skill_names) skill_ids = [s[0] for s in skill_data] skill_max_vals = [v for v in skills.values()] results = self.armordb.get_armor_by_skills(skill_ids, skill_max_vals, uid, num_results) armor_sets = [] for i in range(min(returned_results, len(results))): set_dict = {"helm": {}, "chest": {}, "vambraces": {}, "faulds": {}, "greaves": {}, "charm": {}, "totals": {}} set_res = results[i] set_dict["helm"]["name"] = set_res[0] set_dict["chest"]["name"] = set_res[1] set_dict["vambraces"]["name"] = set_res[2] set_dict["faulds"]["name"] = set_res[3] set_dict["greaves"]["name"] = set_res[4] set_dict["charm"]["name"] = set_res[5] set_dict["helm"]["decos"] = [x for x in set_res[6:9] if x is not None] set_dict["chest"]["decos"] = [x for x in set_res[9:12] if x is not None] set_dict["vambraces"]["decos"] = [x for x in set_res[12:15] if x is not None] set_dict["faulds"]["decos"] = [x for x in set_res[15:18] if x is not None] set_dict["greaves"]["decos"] = [x for x in set_res[18:21] if x is not None] set_dict["charm"]["decos"] = [x for x in set_res[21:24] if x is not None] for n in range(len(skill_names)): set_dict["totals"][skill_names[n]] = int(set_res[24 + n]) armor_sets.append(set_dict) return armor_sets except ValueError as err: print("Search could not be performed") return [] def format_sets(self, unformatted_set: list): """ Formats a set of objects from a query result. :param unformatted_set: The set of objects to format. :return: formatted_set: The set of proper dictionaries. """ formatted_set = [] for c in unformatted_set: item = {"name": c[0], "slot1": c[1], "slot2": c[2], "slot3": c[3], "skills": {}} if c[4] is not None: item["skills"][self.armordb.get_skill(c[4])[0][1]] = int(c[5]) if c[6] is not None: item["skills"][self.armordb.get_skill(c[6])[0][1]] = int(c[7]) if c[8] is not None: item["skills"][self.armordb.get_skill(c[8])[0][1]] = int(c[9]) if c[10] is not None: item["skills"][self.armordb.get_skill(c[10])[0][1]] = int(c[11]) formatted_set.append(item) return formatted_set def display(self, uid: int, armor_type: str, skill_name: str = None): """ Returns and formats all charms for a given user. :param uid: the user's Discord Id :param armor_type: the type of armor to return. :param skill_name: The name of a skill to search for. :return: charm_set: list of dictionaries of the charms. """ try: skillId = None if skill_name is not None: skillId = self.armordb.get_skills_by_name([skill_name])[0][0] if armor_type == "helms": unformatted_set = self.armordb.get_helms(skillId) elif armor_type == "chests": unformatted_set = self.armordb.get_chests(skillId) elif armor_type == "vambraces": unformatted_set = self.armordb.get_vambraces(skillId) elif armor_type == "faulds": unformatted_set = self.armordb.get_faulds(skillId) elif armor_type == "greaves": unformatted_set = self.armordb.get_greaves(skillId) elif armor_type == "charms": unformatted_set = self.armordb.get_charms(uid, skillId) else: raise ValueError return self.format_sets(unformatted_set) except ValueError as err: print("Unable to query the set.") return [] def show_decorations(self): """ Displays all the decorations in the given database. :return: list of dictionaries of decoration info, list of decorations by slot size """ try: deco_set = [] decos = self.armordb.get_all_decos() deco_counts = self.armordb.get_deco_counts() for d in decos: dec = {} dec["name"] = d[1] dec["slot"] = d[2] dec["skillName"] = self.armordb.get_skill(d[3])[0][1] dec["skillVal"] = d[4] deco_set.append(dec) return deco_set, deco_counts except ValueError as err: print("Unable to query the set.") return [] def get_skill_desc(self, skill_name): try: skill_id = self.armordb.get_skills_by_name([skill_name])[0][0] skill_desc = self.armordb.get_skill_desc(skill_id)[0][0] return skill_desc except ValueError as err: print("Unable to get a skill description.") return ""