def test_duplicate_column_names(self): """Tests if duplicate column names raise an error loading a TXT file.""" with self.assertRaises(DuplicateColumnNameError): D2TXT.load_txt( StringIO( "column name\tcolumn name 2\tcolumn name 2\t" "column name\tcolumn name\tcolumn name 2\r\n" "foo\tbar\tbar\tfoo\tfoo\tbar\r\n", newline="", # Required to make csv.reader work correctly ))
def test_missing_cells(self): """Tests if missing cells corrected parsed when loading a TXT file.""" d2txt = D2TXT.load_txt( StringIO( "column 1\tcolumn 2\tcolumn 3\r\n1 tab\t\r\nno tabs\r\n\r\n", newline="", # Required to make csv.reader work correctly )) self.compare_d2txt( d2txt, ["column 1", "column 2", "column 3"], [["1 tab", "", None], ["no tabs", None, None], [None, None, None]], )
def test_empty_cell(self): """Tests if D2TXT correctly loads empty cells and rows in a TXT file.""" d2txt = D2TXT.load_txt( StringIO( "column 1\tcolumn 2\tcolumn 3\r\nempty\t\t\r\n\t\t\r\n", newline="", # Required to make csv.reader work correctly )) self.compare_d2txt( d2txt, ["column 1", "column 2", "column 3"], [["empty", "", ""], ["", "", ""]], )
def test_surrounding_quotes(self): """Tests if surrounding quotes are preserved when loading a TXT file.""" d2txt = D2TXT.load_txt( StringIO( "'single quotes'\t\"double quotes\"\t`backticks`\r\n" "'single quotes'\t\"double quotes\"\t`backticks`\r\n", newline="", # Required to make csv.reader work correctly )) self.compare_d2txt( d2txt, ["'single quotes'", '"double quotes"', "`backticks`"], [["'single quotes'", '"double quotes"', "`backticks`"]], )
def test_cell_whitespace(self): """Tests if whitespace in cells are preserved when loading a TXT file.""" d2txt = D2TXT.load_txt( StringIO( "column 1\tcolumn 2\tcolumn 3\r\n" " 2 leading spaces\t3 trailing spaces \t \r\n", newline="", # Required to make csv.reader work correctly )) self.compare_d2txt( d2txt, ["column 1", "column 2", "column 3"], [[" 2 leading spaces", "3 trailing spaces ", " "]], )
def test_column_name_whitespace(self): """Tests if whitespace in columns are preserved when loading a TXT file.""" d2txt = D2TXT.load_txt( StringIO( " column 1\tcolumn 2 \t column 3 \t\t \r\n" "3 before\t4 after\t2 both\tempty\tspaces only\r\n", newline="", # Required to make csv.reader work correctly )) self.compare_d2txt( d2txt, [" column 1", "column 2 ", " column 3 ", "", " "], [["3 before", "4 after", "2 both", "empty", "spaces only"]], )
def test_column_name_case_preserving(self): """Tests if column names are case-preserved when loading a TXT file.""" d2txt = D2TXT.load_txt( StringIO( "column name\tColumn Name\tCOLUMN NAME\r\n" "lowercase\tCapitalized\tUPPERCASE\r\n", newline="", # Required to make csv.reader work correctly )) self.compare_d2txt( d2txt, ["column name", "Column Name", "COLUMN NAME"], [["lowercase", "Capitalized", "UPPERCASE"]], )
def main(argv): """Entrypoint of the command line script.""" arg_parser = argparse.ArgumentParser(description=__doc__) arg_parser.add_argument("skills_txt", help="Path to Skills.txt") arg_parser.add_argument( "--ulvl-per-blvl", type=int, help="If provided, specifies ulvl requirement per current skill blvl", ) arg_parser.add_argument( "--use-reqlevel-as-base", action="store_true", help="If set, use reqlevel in Skills.txt as the base ulvl requirement", ) arg_parser.add_argument( "--reqskill-level", type=int, help= "If provided, specifies minimum blvl of all reqskills as a requirement", ) args = arg_parser.parse_args(argv) skills_txt = D2TXT.load_txt(args.skills_txt) num_skills_updated = 0 for skill in skills_txt: # Skip skills not owned by player classes if not skill["charclass"]: continue formulas = [] if args.ulvl_per_blvl: base_ulvl = 0 if args.use_reqlevel_as_base: reqlevel = int(skill["reqlevel"]) if reqlevel > 1: base_ulvl = reqlevel formulas.append( make_ulvl_check_formula(args.ulvl_per_blvl, base_ulvl)) if args.reqskill_level: formulas += make_prereq_level_check_formulas( skill, args.reqskill_level) skill["skpoints"] = combine_skpoints_check_formula(formulas) num_skills_updated += 1 skills_txt.to_txt(args.skills_txt) print(f"{num_skills_updated} skill(s) updated in {args.skills_txt}")
def test_load_file_object(self): """Tests if D2TXT can load a TXT file from a file object.""" d2txt = D2TXT.load_txt( StringIO( "column 1\tcolumn 2\tcolumn 3\r\n" "value 1\tvalue 2\tvalue 3\r\n" "foo\tbar\tbaz\r\n", newline="", # Required to make csv.reader work correctly )) self.compare_d2txt( d2txt, ["column 1", "column 2", "column 3"], [["value 1", "value 2", "value 3"], ["foo", "bar", "baz"]], )
def main(argv): """Entrypoint of the command line script.""" arg_parser = argparse.ArgumentParser(__doc__) arg_parser.add_argument("itemtypes_txt", help="Path to ItemTypes.txt") arg_parser.add_argument("weapons_txt", help="Path to Weapons.txt") args = arg_parser.parse_args(argv) item_types_txt = D2TXT.load_txt(args.itemtypes_txt) weapons_txt = D2TXT.load_txt(args.weapons_txt) itype_nodes = parse_itypes(item_types_txt) one_handers, two_handers, mixed_types = classify_itypes_by_hand( itype_nodes, weapons_txt ) print("One-handers: " + ", ".join(one_handers)) print("Two-handers: " + ", ".join(two_handers)) print("Mixed bags : " + ", ".join(mixed_types)) print("-" * 80) for node in itype_nodes.values(): if not node.parents: print_itype_tree(node, one_handers=one_handers, two_handers=two_handers)
def main(argv): """Entrypoint of the command line script.""" args = parse_args(argv) tcex_txt = D2TXT.load_txt(args.tcex_txt) tc_dict = make_tc_dict(tcex_txt) re_flags = 0 if args.ignore_case: re_flags = re.IGNORECASE tc_patterns = [] for pattern_index, pattern_str in enumerate(args.pattern): print(f"Pattern {pattern_index + 1}: {repr(pattern_str)}") tc_patterns.append(re.compile(pattern_str, flags=re_flags)) num_matched_tcs = 0 num_rebalanced_tcs = 0 for tc_entry in tcex_txt: name = tc_entry["Treasure Class"] if not match_in_patterns(name, tc_patterns): continue num_matched_tcs += 1 # Rebalance treasureclasses from top to bottom. Since a treasureclass # can only refer to other TCs above its row, we assume that all previous # TCs have already been rebalanced. for item_col, prob_col in TC_PROB_COLUMNS.items(): item_name = tc_entry[item_col] if not item_name: continue if item_name in tc_dict and match_in_patterns( item_name, tc_patterns): tc_entry[prob_col] = sum_probs(tc_dict[item_name]) num_rebalanced_tcs += 1 tcex_txt.to_txt(args.tcex_txt) print(f"{num_matched_tcs} treasureclass(es) matched, " f"{num_rebalanced_tcs} treasureclass(es) rebalanced.")
def test_load_path(self): """Tests if D2TXT can load a file using a file path, and its contents are preserved.""" file_path = path.join(path.dirname(path.abspath(__file__)), "sample.txt") d2txt = D2TXT.load_txt(file_path) self.compare_d2txt( d2txt, [ "column name", "column 2", "column 3", "", "COLUMN NAME", ], [ [ "lowercase column name", "next cell is empty", "", "empty column name", "UPPERCASE COLUMN NAME", ], [ "next row is empty", " leading spaces", "trailing spaces ", " surrounded by spaces ", '"double quotes"', ], ["", "", "", "", "0"], [ "this row and the next has not enough cells", None, None, None, None ], [None, None, None, None, None], ], )
def main(argv): """Entrypoint of the command line script.""" arg_parser = argparse.ArgumentParser(description=__doc__) arg_parser.add_argument("weapons_txt", help="Path to Weapons.txt") arg_parser.add_argument( "--1h", type=check_item_code, help="If provided, item code to assign to 1-hand weapons", ) arg_parser.add_argument( "--2h", type=check_item_code, help="If provided, item code to assign to 2-hand weapons", ) arg_parser.add_argument( "--both", type=check_item_code, help="If provided, item code to assign to 1-or-2-hand weapons", ) args = vars(arg_parser.parse_args(argv)) weapons_txt = D2TXT.load_txt(args["weapons_txt"]) num_1h = num_2h = num_both = 0 for row_index, weapon in enumerate(weapons_txt): if not (weapon["type"] and weapon["code"]): continue if weapon["type2"]: print(f"Warning: Row {row_index + 1} is skipped -- " f'{weapon["name"]} already has \'type2\' assigned.') continue if weapon["1or2handed"]: item_code = args["both"] num_both += 1 elif weapon["2handed"]: item_code = args["2h"] num_2h += 1 else: item_code = args["1h"] num_1h += 1 if item_code: weapon["type2"] = item_code weapons_txt.to_txt(args["weapons_txt"]) if args["1h"]: print( f'\'{args["1h"]}\' has been assigned to {num_1h} 1-hand weapon(s)') if args["2h"]: print( f'\'{args["2h"]}\' has been assigned to {num_2h} 2-hand weapon(s)') if args["both"]: print( f'\'{args["both"]}\' has been assigned to {num_both} 1-or-2-hand weapon(s)' )