diff --git a/bin/mhweaponbuild.py b/bin/mhweaponbuild.py new file mode 100755 index 0000000..99f5086 --- /dev/null +++ b/bin/mhweaponbuild.py @@ -0,0 +1,77 @@ +#!/usr/bin/env python + +import sys +import argparse +import json + +import _pathfix + +from mhapi.db import MHDB +from mhapi.model import ModelJSONEncoder + + +def parse_args(argv): + parser = argparse.ArgumentParser(description= + "Determine the different paths for making a weapons and the cost" + " and parts required for each path." + ) + parser.add_argument("-j", "--json", action="store_true", + default=False, + help="output as json instead of plaintext") + parser.add_argument("weapon", + help="Full name of weapon") + return parser.parse_args(argv) + + +def get_costs(db, weapon): + """ + Get a list of alternative ways of making a weapon, as a list of dicts + containing item counts. The dicts also contain special keys _zenny + for the total zenny needed, and _path for a list of weapons that + make up the upgrade path. + """ + costs = [] + if weapon.parent_id: + parent_weapon = db.get_weapon(weapon.parent_id, True) + costs = get_costs(db, parent_weapon) + for cost in costs: + for item in weapon.upgrade_components: + if item.type == "Weapon": + continue + if item.name not in cost["components"]: + cost["components"][item.name] = 0 + cost["components"][item.name] += item.quantity + cost["zenny"] += weapon.upgrade_cost + cost["path"] += [weapon] + if weapon.creation_cost: + create_cost = dict(zenny=weapon.creation_cost, + path=[weapon], + components={}) + for item in weapon.create_components: + create_cost["components"][item.name] = item.quantity + costs = [create_cost] + costs + return costs + + +if __name__ == '__main__': + args = parse_args(None) + + db = MHDB() + + weapon = db.get_weapon_by_name(args.weapon, True) + if not weapon: + raise ValueError("Weapon '%s' not found" % name) + costs = get_costs(db, weapon) + if args.json: + for cost in costs: + cost["path"] = [dict(name=w.name, id=w.id) + for w in cost["path"]] + json.dump(costs, sys.stdout, cls=ModelJSONEncoder, indent=2) + else: + for cost in costs: + components = cost["components"] + print "=", ", ".join([w.name for w in cost["path"]]) + print " Zenny", cost["zenny"] + for item_name in sorted(components.iterkeys()): + print "%20s %2d" % (item_name, components[item_name]) + print diff --git a/mhapi/db.py b/mhapi/db.py index a0858ef..4f7e9a2 100644 --- a/mhapi/db.py +++ b/mhapi/db.py @@ -290,20 +290,31 @@ class MHDB(object): LEFT JOIN items ON weapons._id = items._id """, model_cls=model.Weapon) - def get_weapon(self, weapon_id): - return self._query_one("weapon", """ + def _add_components(self, item_data): + ccomps = self.get_item_components(item_data.id, "Create") + ucomps = self.get_item_components(item_data.id, "Improve") + item_data.set_components(ccomps, ucomps) + + def get_weapon(self, weapon_id, get_components=False): + weapon = self._query_one("weapon", """ SELECT * FROM weapons LEFT JOIN items ON weapons._id = items._id WHERE weapons._id=? """, (weapon_id,), model_cls=model.Weapon) + if weapon and get_components: + self._add_components(weapon) + return weapon - def get_weapon_by_name(self, name): - return self._query_one("weapon", """ + def get_weapon_by_name(self, name, get_components=False): + weapon = self._query_one("weapon", """ SELECT items._id, items.name, items.buy, weapons.* FROM weapons LEFT JOIN items ON weapons._id = items._id WHERE items.name=? """, (name,), model_cls=model.Weapon) + if weapon and get_components: + self._add_components(weapon) + return weapon def get_armors(self): return self._query_all("armors", """ @@ -427,3 +438,13 @@ class MHDB(object): WHERE monster_id=? AND (condition LIKE 'Break %' OR condition = 'Tail Carve') """, (monster_id,), model_cls=model) + + def get_item_components(self, item_id, method="Create"): + return self._query_all("item_components", """ + SELECT items._id, items.name, items.type, + components.quantity, components.type AS method + FROM components + LEFT JOIN items + ON items._id = components.component_item_id + WHERE created_item_id=? AND components.type=? + """, (item_id, method), model_cls=model.ItemComponent) diff --git a/mhapi/model.py b/mhapi/model.py index 771e370..502b2f7 100644 --- a/mhapi/model.py +++ b/mhapi/model.py @@ -152,13 +152,14 @@ class SharpnessLevel(EnumBase): PURPLE: "Purple", } + # source: http://kiranico.com/en/mh4u/wiki/weapons _modifier = { RED: (0.50, 0.25), ORANGE: (0.75, 0.50), YELLOW: (1.00, 0.75), - GREEN: (1.05, 1.00), - BLUE: (1.20, 1.06), - WHITE: (1.32, 1.12), + GREEN: (1.125, 1.00), + BLUE: (1.25, 1.0625), + WHITE: (1.32, 1.125), PURPLE: (1.44, 1.20), } @@ -303,13 +304,19 @@ class SkillTree(RowModel): class Weapon(RowModel): _list_fields = ["id", "wtype", "name"] - _indexes = { "name": ["id"], + _indexes = { "name": "id", "wtype": ["id", "name"] } def __init__(self, weapon_item_row): super(Weapon, self).__init__(weapon_item_row) self._parse_sharpness() + self.create_components = [] + self.upgrade_components = [] + + def set_components(self, create_components, upgrade_components): + self.create_components = create_components + self.upgrade_components = upgrade_components def _parse_sharpness(self): """ @@ -327,6 +334,17 @@ class Weapon(RowModel): self._data["sharpness"] = WeaponSharpness(normal) self._data["sharpness_plus"] = WeaponSharpness(plus) + def as_data(self): + data = super(Weapon, self).as_data() + if self.create_components is not None: + data["create_components"] = dict((item.name, item.quantity) + for item in self.create_components) + if self.upgrade_components is not None: + data["upgrade_components"] = dict((item.name, item.quantity) + for item in self.upgrade_components) + return data + + class Monster(RowModel): _list_fields = ["id", "class", "name"] @@ -338,6 +356,12 @@ class Item(RowModel): "type": ["id", "name"] } +class ItemComponent(RowModel): + _list_fields = ["id", "name"] + _indexes = { "method": ["id", "name"] } + + + class Location(RowModel): pass diff --git a/web/templates/weaponpath.ejs b/web/templates/weaponpath.ejs new file mode 100644 index 0000000..8e56514 --- /dev/null +++ b/web/templates/weaponpath.ejs @@ -0,0 +1,23 @@ +
+<%= path[0]["name"] %> (<%= path.length %>) + + + + +<% for(var i=0; i + + <% if (all_components[i] in components) { %> + + + <% } else { %> + + + <% } %> + +<% } %> +
<%= zenny %>z
<%= all_components[i] %><%= components[all_components[i]] %>  
+
diff --git a/web/weapontree.html b/web/weapontree.html new file mode 100644 index 0000000..08e39eb --- /dev/null +++ b/web/weapontree.html @@ -0,0 +1,124 @@ + + + Poogie's Weapon Tree + + + + + + + + + + + + + +
+ + + +
+
+ +