add html/jsonapi armor builder
- make decoration calculator use 1-slot decorations multiple times
This commit is contained in:
27
mhapi/db.py
27
mhapi/db.py
@@ -299,27 +299,31 @@ class MHDB(object):
|
||||
|
||||
def get_weapon_by_name(self, name):
|
||||
return self._query_one("weapon", """
|
||||
SELECT * FROM weapons
|
||||
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)
|
||||
|
||||
def get_armors(self):
|
||||
return self._query_all("armors", """
|
||||
SELECT * FROM armor
|
||||
SELECT items._id, items.name, items.buy, armor.*
|
||||
FROM armor
|
||||
LEFT JOIN items ON armor._id = items._id
|
||||
""", model_cls=model.Armor)
|
||||
|
||||
def get_armor(self, armor_id):
|
||||
return self._query_one("armor", """
|
||||
SELECT * FROM armor
|
||||
SELECT items._id, items.name, items.buy, armor.*
|
||||
FROM armor
|
||||
LEFT JOIN items ON armor._id = items._id
|
||||
WHERE armor._id=?
|
||||
""", (armor_id,), model_cls=model.Armor)
|
||||
|
||||
def get_armor_by_name(self, name):
|
||||
return self._query_one("armor", """
|
||||
SELECT * FROM armor
|
||||
SELECT items._id, items.name, items.buy, armor.*
|
||||
FROM armor
|
||||
LEFT JOIN items ON armor._id = items._id
|
||||
WHERE items.name=?
|
||||
""", (name,), model_cls=model.Armor)
|
||||
@@ -335,7 +339,7 @@ class MHDB(object):
|
||||
|
||||
def get_decorations(self):
|
||||
return self._query_all("decorations", """
|
||||
SELECT *
|
||||
SELECT items._id, items.name, items.buy, decorations.*
|
||||
FROM decorations
|
||||
INNER JOIN items
|
||||
ON items._id = decorations._id
|
||||
@@ -343,7 +347,7 @@ class MHDB(object):
|
||||
|
||||
def get_decoration(self, decoration_id):
|
||||
return self._query_one("decoration", """
|
||||
SELECT *
|
||||
SELECT items._id, items.name, items.buy, decorations.*
|
||||
FROM decorations
|
||||
INNER JOIN items
|
||||
ON items._id = decorations._id
|
||||
@@ -352,13 +356,18 @@ class MHDB(object):
|
||||
|
||||
def get_decoration_by_name(self, name):
|
||||
return self._query_all("decoration", """
|
||||
SELECT *
|
||||
SELECT items._id, items.name, items.buy, decorations.*
|
||||
FROM decorations
|
||||
INNER JOIN items
|
||||
ON items._id = decorations._id
|
||||
WHERE items.name = ?
|
||||
""", (name,), model_cls=model.Decoration)
|
||||
|
||||
def get_skill_trees(self):
|
||||
return self._query_all("skills", """
|
||||
SELECT _id, name FROM skill_trees
|
||||
""", model_cls=model.SkillTree)
|
||||
|
||||
def get_skill_tree_id(self, skill_tree_name):
|
||||
result = self._query_one("skill", """
|
||||
SELECT _id FROM skill_trees
|
||||
@@ -372,7 +381,7 @@ class MHDB(object):
|
||||
args = sorted(skill_tree_ids)
|
||||
placeholders = ", ".join(["?"] * len(skill_tree_ids))
|
||||
return self._query_all("decorations", """
|
||||
SELECT items.*, decorations.*
|
||||
SELECT items._id, items.name, items.buy, decorations.*
|
||||
FROM item_to_skill_tree
|
||||
LEFT JOIN items
|
||||
ON items._id = item_to_skill_tree.item_id
|
||||
@@ -389,7 +398,7 @@ class MHDB(object):
|
||||
placeholders = ", ".join(["?"] * len(skill_tree_ids))
|
||||
args += [hunter_type]
|
||||
return self._query_all("decorations", """
|
||||
SELECT items.*, armor.*
|
||||
SELECT items._id, items.name, items.buy, armor.*
|
||||
FROM item_to_skill_tree
|
||||
LEFT JOIN items
|
||||
ON items._id = item_to_skill_tree.item_id
|
||||
|
||||
@@ -76,7 +76,10 @@ class RowModel(ModelBase):
|
||||
self.update_index(key_field, value_fields, data[key_field])
|
||||
|
||||
def update_index(self, key_field, value_fields, data):
|
||||
item = dict((k, self[k]) for k in value_fields)
|
||||
if isinstance(value_fields, str):
|
||||
item = self[value_fields]
|
||||
else:
|
||||
item = dict((k, self[k]) for k in value_fields)
|
||||
key_value = self[key_field]
|
||||
if key_value not in data:
|
||||
data[key_value] = []
|
||||
@@ -212,16 +215,29 @@ class ItemWithSkills(RowModel):
|
||||
return self.skills.get(skill_id_or_name, 0)
|
||||
|
||||
def one_line_skills_u(self, skill_names=None):
|
||||
"""
|
||||
Get comma separated list of skills on the item. If @skill_names
|
||||
is passed, only include skills that are in that list.
|
||||
"""
|
||||
if skill_names is None:
|
||||
skill_names = sorted(self.skill_names)
|
||||
return ", ".join("%s %d" % (name, self.skills[name])
|
||||
for name in skill_names
|
||||
if name in self.skills)
|
||||
|
||||
def as_data(self):
|
||||
data = super(ItemWithSkills, self).as_data()
|
||||
if self.skills is not None:
|
||||
data["skills"] = dict((name, self.skills[name])
|
||||
for name in self.skill_names)
|
||||
#data["skills_by_id"] = dict((sid, self.skills[sid])
|
||||
# for sid in self.skill_ids)
|
||||
return data
|
||||
|
||||
|
||||
class Armor(ItemWithSkills):
|
||||
_indexes = { "name": ["id"],
|
||||
"slot": ["id", "name"] }
|
||||
_indexes = { "name": "id",
|
||||
"slot": "name" }
|
||||
|
||||
_one_line_template = string.Template(
|
||||
"$name ($slot) Def $defense-$max_defense Slot $num_slots"
|
||||
@@ -236,9 +252,10 @@ class Armor(ItemWithSkills):
|
||||
def skill(self, skill_id_or_name, decoration_values=()):
|
||||
"""
|
||||
decoration_values should be a list of points from the given
|
||||
number of slots, e.g. [1, 3] means that one slot gets 1 point
|
||||
and two slots get 3 points, [1, 0, 4] means that one slot gets 1 point,
|
||||
there is no two slot gem, and three slots gets 4 points.
|
||||
number of slots, e.g. [1, 3] or [1, 3, 0] means that one slot
|
||||
gets 1 point and two slots get 3 points, [1, 0, 4] means that
|
||||
one slot gets 1 point, there is no two slot gem, and three slots
|
||||
gets 4 points. If not passed, just returns native skill points.
|
||||
"""
|
||||
assert self.skills is not None
|
||||
total = self.skills.get(skill_id_or_name, 0)
|
||||
@@ -249,7 +266,7 @@ class Armor(ItemWithSkills):
|
||||
decoration_value = decoration_values[slots-1]
|
||||
if not decoration_value:
|
||||
continue
|
||||
if slots <= slots_left:
|
||||
while slots <= slots_left:
|
||||
total += decoration_value
|
||||
slots_left -= slots
|
||||
return total
|
||||
@@ -263,6 +280,27 @@ class ItemSkill(RowModel):
|
||||
pass
|
||||
|
||||
|
||||
class SkillTree(RowModel):
|
||||
def __init__(self, skill_tree_row):
|
||||
super(SkillTree, self).__init__(skill_tree_row)
|
||||
self.decoration_values = None
|
||||
self.decoration_ids = None
|
||||
|
||||
def set_decorations(self, decorations):
|
||||
if decorations is None:
|
||||
self.decoration_values = None
|
||||
else:
|
||||
self.decoration_ids, self.decoration_values = \
|
||||
get_decoration_values(self.id, decorations)
|
||||
|
||||
def as_data(self):
|
||||
data = super(SkillTree, self).as_data()
|
||||
if self.decoration_values is not None:
|
||||
data["decoration_values"] = self.decoration_values
|
||||
data["decoration_ids"] = self.decoration_ids
|
||||
return data
|
||||
|
||||
|
||||
class Weapon(RowModel):
|
||||
_list_fields = ["id", "wtype", "name"]
|
||||
_indexes = { "name": ["id"],
|
||||
@@ -401,6 +439,22 @@ class MonsterDamage(ModelBase):
|
||||
part_damage.breakable = True
|
||||
|
||||
|
||||
def get_decoration_values(skill_id, decorations):
|
||||
# TODO: write script to compute this and shove into skill_tree table
|
||||
values = [0, 0, 0]
|
||||
ids = [None, None, None]
|
||||
for d in decorations:
|
||||
assert d.num_slots is not None
|
||||
# some skills like Handicraft have multiple decorations with
|
||||
# same number of slots - use the best one
|
||||
new = d.skills[skill_id]
|
||||
current = values[d.num_slots-1]
|
||||
if new > current:
|
||||
values[d.num_slots-1] = new
|
||||
ids[d.num_slots-1] = d.id
|
||||
return (ids, values)
|
||||
|
||||
|
||||
def _break_find(part, parts, breaks):
|
||||
# favor 'Tail Tip' over Tail for Basarios
|
||||
if part == "Tail" and "Tail Tip" in parts:
|
||||
|
||||
@@ -2,6 +2,8 @@
|
||||
Shared utility classes and functions.
|
||||
"""
|
||||
|
||||
import codecs
|
||||
|
||||
|
||||
class EnumBase(object):
|
||||
_names = dict()
|
||||
@@ -9,3 +11,7 @@ class EnumBase(object):
|
||||
@classmethod
|
||||
def name(cls, enum_value):
|
||||
return cls._names[enum_value]
|
||||
|
||||
|
||||
def get_utf8_writer(writer):
|
||||
return codecs.getwriter("utf8")(writer)
|
||||
|
||||
Reference in New Issue
Block a user