add html/jsonapi armor builder
- make decoration calculator use 1-slot decorations multiple times
This commit is contained in:
@@ -7,9 +7,9 @@ import codecs
|
|||||||
import _pathfix
|
import _pathfix
|
||||||
|
|
||||||
from mhapi.db import MHDB
|
from mhapi.db import MHDB
|
||||||
|
from mhapi.model import get_decoration_values
|
||||||
|
from mhapi.util import get_utf8_writer
|
||||||
|
|
||||||
def get_utf8_writer(writer):
|
|
||||||
return codecs.getwriter("utf8")(writer)
|
|
||||||
|
|
||||||
def parse_args(argv):
|
def parse_args(argv):
|
||||||
parser = argparse.ArgumentParser(description=
|
parser = argparse.ArgumentParser(description=
|
||||||
@@ -46,7 +46,7 @@ def find_armors(args):
|
|||||||
ds = db.get_decorations_by_skills([sid])
|
ds = db.get_decorations_by_skills([sid])
|
||||||
for d in ds:
|
for d in ds:
|
||||||
d.set_skills(db.get_item_skills(d.id))
|
d.set_skills(db.get_item_skills(d.id))
|
||||||
decoration_values = get_decoration_values(sid, ds)
|
decoration_values = get_decoration_values(sid, ds)[1]
|
||||||
decorations[sid] = (ds, decoration_values)
|
decorations[sid] = (ds, decoration_values)
|
||||||
print "%s[%s]:" % (skill_name, sid), ", ".join(d.name for d in ds), \
|
print "%s[%s]:" % (skill_name, sid), ", ".join(d.name for d in ds), \
|
||||||
decoration_values
|
decoration_values
|
||||||
@@ -88,20 +88,6 @@ def find_armors(args):
|
|||||||
print " ", a.one_line_skills_u(args.skills)
|
print " ", a.one_line_skills_u(args.skills)
|
||||||
|
|
||||||
|
|
||||||
def get_decoration_values(skill_id, decorations):
|
|
||||||
# TODO: write script to compute this and shove innto skill_tree table
|
|
||||||
values = [0, 0, 0]
|
|
||||||
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
|
|
||||||
return values
|
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
args = parse_args(None)
|
args = parse_args(None)
|
||||||
|
|
||||||
|
|||||||
@@ -35,13 +35,21 @@ def file_path(path, model_object, use_name=False):
|
|||||||
def write_list_file(path, model_list):
|
def write_list_file(path, model_list):
|
||||||
list_path = os.path.join(path, "_list.json")
|
list_path = os.path.join(path, "_list.json")
|
||||||
with open(list_path, "w") as f:
|
with open(list_path, "w") as f:
|
||||||
json.dump([o.as_list_data() for o in model_list], f, indent=2)
|
json.dump([o.as_list_data() for o in model_list],
|
||||||
|
f, cls=model.ModelJSONEncoder, indent=2)
|
||||||
|
|
||||||
|
|
||||||
def write_index_file(path, indexes):
|
def write_index_file(path, indexes):
|
||||||
index_path = os.path.join(path, "_index.json")
|
for key, data in indexes.iteritems():
|
||||||
with open(index_path, "w") as f:
|
index_path = os.path.join(path, "_index_%s.json" % key)
|
||||||
json.dump(indexes, f, indent=2)
|
with open(index_path, "w") as f:
|
||||||
|
json.dump(data, f, cls=model.ModelJSONEncoder, indent=2)
|
||||||
|
|
||||||
|
|
||||||
|
def write_all_file(path, all_data):
|
||||||
|
all_path = os.path.join(path, "_all.json")
|
||||||
|
with open(all_path, "w") as f:
|
||||||
|
json.dump(all_data, f, cls=model.ModelJSONEncoder, indent=2)
|
||||||
|
|
||||||
|
|
||||||
def monster_json(db, path):
|
def monster_json(db, path):
|
||||||
@@ -63,6 +71,73 @@ def monster_json(db, path):
|
|||||||
write_index_file(path, indexes)
|
write_index_file(path, indexes)
|
||||||
|
|
||||||
|
|
||||||
|
def armor_json(db, path):
|
||||||
|
armors = db.get_armors()
|
||||||
|
mkdirs_p(path)
|
||||||
|
write_list_file(path, armors)
|
||||||
|
all_data = []
|
||||||
|
|
||||||
|
indexes = {}
|
||||||
|
for a in armors:
|
||||||
|
armor_path = file_path(path, a)
|
||||||
|
a.update_indexes(indexes)
|
||||||
|
skills = db.get_item_skills(a.id)
|
||||||
|
if not skills:
|
||||||
|
print "WARN: armor '%s' (%d) has no skills" % (a.name, a.id)
|
||||||
|
a.set_skills(skills)
|
||||||
|
|
||||||
|
all_data.append(a.as_data())
|
||||||
|
|
||||||
|
with open(armor_path, "w") as f:
|
||||||
|
a.json_dump(f)
|
||||||
|
|
||||||
|
write_index_file(path, indexes)
|
||||||
|
write_all_file(path, all_data)
|
||||||
|
|
||||||
|
|
||||||
|
def decoration_json(db, path):
|
||||||
|
decorations = db.get_decorations()
|
||||||
|
mkdirs_p(path)
|
||||||
|
write_list_file(path, decorations)
|
||||||
|
all_data = []
|
||||||
|
|
||||||
|
indexes = {}
|
||||||
|
for a in decorations:
|
||||||
|
decoration_path = file_path(path, a)
|
||||||
|
a.update_indexes(indexes)
|
||||||
|
skills = db.get_item_skills(a.id)
|
||||||
|
if not skills:
|
||||||
|
print "WARN: decoration '%s' (%d) has no skills" % (a.name, a.id)
|
||||||
|
a.set_skills(skills)
|
||||||
|
|
||||||
|
all_data.append(a.as_data())
|
||||||
|
|
||||||
|
with open(decoration_path, "w") as f:
|
||||||
|
a.json_dump(f)
|
||||||
|
|
||||||
|
write_index_file(path, indexes)
|
||||||
|
write_all_file(path, all_data)
|
||||||
|
|
||||||
|
|
||||||
|
def skilltree_json(db, path):
|
||||||
|
skill_trees = db.get_skill_trees()
|
||||||
|
mkdirs_p(path)
|
||||||
|
write_list_file(path, skill_trees)
|
||||||
|
|
||||||
|
all_data = {}
|
||||||
|
for st in skill_trees:
|
||||||
|
ds = db.get_decorations_by_skills([st.id])
|
||||||
|
for d in ds:
|
||||||
|
d.set_skills(db.get_item_skills(d.id))
|
||||||
|
st.set_decorations(ds)
|
||||||
|
skilltree_path = file_path(path, st)
|
||||||
|
all_data[st.name] = st
|
||||||
|
with open(skilltree_path, "w") as f:
|
||||||
|
st.json_dump(f)
|
||||||
|
|
||||||
|
write_all_file(path, all_data)
|
||||||
|
|
||||||
|
|
||||||
def weapon_json(db, path):
|
def weapon_json(db, path):
|
||||||
weapons = db.get_weapons()
|
weapons = db.get_weapons()
|
||||||
mkdirs_p(path)
|
mkdirs_p(path)
|
||||||
@@ -104,7 +179,10 @@ def main():
|
|||||||
items_json(db, os.path.join(outpath, "item"))
|
items_json(db, os.path.join(outpath, "item"))
|
||||||
weapon_json(db, os.path.join(outpath, "weapon"))
|
weapon_json(db, os.path.join(outpath, "weapon"))
|
||||||
monster_json(db, os.path.join(outpath, "monster"))
|
monster_json(db, os.path.join(outpath, "monster"))
|
||||||
#quest_json
|
armor_json(db, os.path.join(outpath, "armor"))
|
||||||
|
skilltree_json(db, os.path.join(outpath, "skilltree"))
|
||||||
|
decoration_json(db, os.path.join(outpath, "decoration"))
|
||||||
|
#quest_json(db, os.path.join(outpath, "quest"))
|
||||||
|
|
||||||
|
|
||||||
if __name__ == '__main__':
|
if __name__ == '__main__':
|
||||||
|
|||||||
27
mhapi/db.py
27
mhapi/db.py
@@ -299,27 +299,31 @@ class MHDB(object):
|
|||||||
|
|
||||||
def get_weapon_by_name(self, name):
|
def get_weapon_by_name(self, name):
|
||||||
return self._query_one("weapon", """
|
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
|
LEFT JOIN items ON weapons._id = items._id
|
||||||
WHERE items.name=?
|
WHERE items.name=?
|
||||||
""", (name,), model_cls=model.Weapon)
|
""", (name,), model_cls=model.Weapon)
|
||||||
|
|
||||||
def get_armors(self):
|
def get_armors(self):
|
||||||
return self._query_all("armors", """
|
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
|
LEFT JOIN items ON armor._id = items._id
|
||||||
""", model_cls=model.Armor)
|
""", model_cls=model.Armor)
|
||||||
|
|
||||||
def get_armor(self, armor_id):
|
def get_armor(self, armor_id):
|
||||||
return self._query_one("armor", """
|
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
|
LEFT JOIN items ON armor._id = items._id
|
||||||
WHERE armor._id=?
|
WHERE armor._id=?
|
||||||
""", (armor_id,), model_cls=model.Armor)
|
""", (armor_id,), model_cls=model.Armor)
|
||||||
|
|
||||||
def get_armor_by_name(self, name):
|
def get_armor_by_name(self, name):
|
||||||
return self._query_one("armor", """
|
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
|
LEFT JOIN items ON armor._id = items._id
|
||||||
WHERE items.name=?
|
WHERE items.name=?
|
||||||
""", (name,), model_cls=model.Armor)
|
""", (name,), model_cls=model.Armor)
|
||||||
@@ -335,7 +339,7 @@ class MHDB(object):
|
|||||||
|
|
||||||
def get_decorations(self):
|
def get_decorations(self):
|
||||||
return self._query_all("decorations", """
|
return self._query_all("decorations", """
|
||||||
SELECT *
|
SELECT items._id, items.name, items.buy, decorations.*
|
||||||
FROM decorations
|
FROM decorations
|
||||||
INNER JOIN items
|
INNER JOIN items
|
||||||
ON items._id = decorations._id
|
ON items._id = decorations._id
|
||||||
@@ -343,7 +347,7 @@ class MHDB(object):
|
|||||||
|
|
||||||
def get_decoration(self, decoration_id):
|
def get_decoration(self, decoration_id):
|
||||||
return self._query_one("decoration", """
|
return self._query_one("decoration", """
|
||||||
SELECT *
|
SELECT items._id, items.name, items.buy, decorations.*
|
||||||
FROM decorations
|
FROM decorations
|
||||||
INNER JOIN items
|
INNER JOIN items
|
||||||
ON items._id = decorations._id
|
ON items._id = decorations._id
|
||||||
@@ -352,13 +356,18 @@ class MHDB(object):
|
|||||||
|
|
||||||
def get_decoration_by_name(self, name):
|
def get_decoration_by_name(self, name):
|
||||||
return self._query_all("decoration", """
|
return self._query_all("decoration", """
|
||||||
SELECT *
|
SELECT items._id, items.name, items.buy, decorations.*
|
||||||
FROM decorations
|
FROM decorations
|
||||||
INNER JOIN items
|
INNER JOIN items
|
||||||
ON items._id = decorations._id
|
ON items._id = decorations._id
|
||||||
WHERE items.name = ?
|
WHERE items.name = ?
|
||||||
""", (name,), model_cls=model.Decoration)
|
""", (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):
|
def get_skill_tree_id(self, skill_tree_name):
|
||||||
result = self._query_one("skill", """
|
result = self._query_one("skill", """
|
||||||
SELECT _id FROM skill_trees
|
SELECT _id FROM skill_trees
|
||||||
@@ -372,7 +381,7 @@ class MHDB(object):
|
|||||||
args = sorted(skill_tree_ids)
|
args = sorted(skill_tree_ids)
|
||||||
placeholders = ", ".join(["?"] * len(skill_tree_ids))
|
placeholders = ", ".join(["?"] * len(skill_tree_ids))
|
||||||
return self._query_all("decorations", """
|
return self._query_all("decorations", """
|
||||||
SELECT items.*, decorations.*
|
SELECT items._id, items.name, items.buy, decorations.*
|
||||||
FROM item_to_skill_tree
|
FROM item_to_skill_tree
|
||||||
LEFT JOIN items
|
LEFT JOIN items
|
||||||
ON items._id = item_to_skill_tree.item_id
|
ON items._id = item_to_skill_tree.item_id
|
||||||
@@ -389,7 +398,7 @@ class MHDB(object):
|
|||||||
placeholders = ", ".join(["?"] * len(skill_tree_ids))
|
placeholders = ", ".join(["?"] * len(skill_tree_ids))
|
||||||
args += [hunter_type]
|
args += [hunter_type]
|
||||||
return self._query_all("decorations", """
|
return self._query_all("decorations", """
|
||||||
SELECT items.*, armor.*
|
SELECT items._id, items.name, items.buy, armor.*
|
||||||
FROM item_to_skill_tree
|
FROM item_to_skill_tree
|
||||||
LEFT JOIN items
|
LEFT JOIN items
|
||||||
ON items._id = item_to_skill_tree.item_id
|
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])
|
self.update_index(key_field, value_fields, data[key_field])
|
||||||
|
|
||||||
def update_index(self, key_field, value_fields, data):
|
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]
|
key_value = self[key_field]
|
||||||
if key_value not in data:
|
if key_value not in data:
|
||||||
data[key_value] = []
|
data[key_value] = []
|
||||||
@@ -212,16 +215,29 @@ class ItemWithSkills(RowModel):
|
|||||||
return self.skills.get(skill_id_or_name, 0)
|
return self.skills.get(skill_id_or_name, 0)
|
||||||
|
|
||||||
def one_line_skills_u(self, skill_names=None):
|
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:
|
if skill_names is None:
|
||||||
skill_names = sorted(self.skill_names)
|
skill_names = sorted(self.skill_names)
|
||||||
return ", ".join("%s %d" % (name, self.skills[name])
|
return ", ".join("%s %d" % (name, self.skills[name])
|
||||||
for name in skill_names
|
for name in skill_names
|
||||||
if name in self.skills)
|
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):
|
class Armor(ItemWithSkills):
|
||||||
_indexes = { "name": ["id"],
|
_indexes = { "name": "id",
|
||||||
"slot": ["id", "name"] }
|
"slot": "name" }
|
||||||
|
|
||||||
_one_line_template = string.Template(
|
_one_line_template = string.Template(
|
||||||
"$name ($slot) Def $defense-$max_defense Slot $num_slots"
|
"$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=()):
|
def skill(self, skill_id_or_name, decoration_values=()):
|
||||||
"""
|
"""
|
||||||
decoration_values should be a list of points from the given
|
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
|
number of slots, e.g. [1, 3] or [1, 3, 0] means that one slot
|
||||||
and two slots get 3 points, [1, 0, 4] means that one slot gets 1 point,
|
gets 1 point and two slots get 3 points, [1, 0, 4] means that
|
||||||
there is no two slot gem, and three slots gets 4 points.
|
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
|
assert self.skills is not None
|
||||||
total = self.skills.get(skill_id_or_name, 0)
|
total = self.skills.get(skill_id_or_name, 0)
|
||||||
@@ -249,7 +266,7 @@ class Armor(ItemWithSkills):
|
|||||||
decoration_value = decoration_values[slots-1]
|
decoration_value = decoration_values[slots-1]
|
||||||
if not decoration_value:
|
if not decoration_value:
|
||||||
continue
|
continue
|
||||||
if slots <= slots_left:
|
while slots <= slots_left:
|
||||||
total += decoration_value
|
total += decoration_value
|
||||||
slots_left -= slots
|
slots_left -= slots
|
||||||
return total
|
return total
|
||||||
@@ -263,6 +280,27 @@ class ItemSkill(RowModel):
|
|||||||
pass
|
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):
|
class Weapon(RowModel):
|
||||||
_list_fields = ["id", "wtype", "name"]
|
_list_fields = ["id", "wtype", "name"]
|
||||||
_indexes = { "name": ["id"],
|
_indexes = { "name": ["id"],
|
||||||
@@ -401,6 +439,22 @@ class MonsterDamage(ModelBase):
|
|||||||
part_damage.breakable = True
|
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):
|
def _break_find(part, parts, breaks):
|
||||||
# favor 'Tail Tip' over Tail for Basarios
|
# favor 'Tail Tip' over Tail for Basarios
|
||||||
if part == "Tail" and "Tail Tip" in parts:
|
if part == "Tail" and "Tail Tip" in parts:
|
||||||
|
|||||||
@@ -2,6 +2,8 @@
|
|||||||
Shared utility classes and functions.
|
Shared utility classes and functions.
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
import codecs
|
||||||
|
|
||||||
|
|
||||||
class EnumBase(object):
|
class EnumBase(object):
|
||||||
_names = dict()
|
_names = dict()
|
||||||
@@ -9,3 +11,7 @@ class EnumBase(object):
|
|||||||
@classmethod
|
@classmethod
|
||||||
def name(cls, enum_value):
|
def name(cls, enum_value):
|
||||||
return cls._names[enum_value]
|
return cls._names[enum_value]
|
||||||
|
|
||||||
|
|
||||||
|
def get_utf8_writer(writer):
|
||||||
|
return codecs.getwriter("utf8")(writer)
|
||||||
|
|||||||
402
web/armor.html
Normal file
402
web/armor.html
Normal file
@@ -0,0 +1,402 @@
|
|||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<title>Poogie Outfitters</title>
|
||||||
|
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
|
||||||
|
|
||||||
|
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/themes/smoothness/jquery-ui.css" />
|
||||||
|
<script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script>
|
||||||
|
|
||||||
|
<script type="text/javascript" src="js/ejs_production.js"></script>
|
||||||
|
|
||||||
|
<style>
|
||||||
|
label {
|
||||||
|
font-weight: bold;
|
||||||
|
}
|
||||||
|
|
||||||
|
body {
|
||||||
|
font-family: sans, sans-serif;
|
||||||
|
}
|
||||||
|
|
||||||
|
td.num {
|
||||||
|
text-align: right;
|
||||||
|
}
|
||||||
|
|
||||||
|
/*@media (max-width: 600) {*/
|
||||||
|
#flexbox {
|
||||||
|
display: flex;
|
||||||
|
flex-direction: row;
|
||||||
|
flex-wrap: wrap;
|
||||||
|
}
|
||||||
|
|
||||||
|
</style>
|
||||||
|
|
||||||
|
<script type="text/javascript">
|
||||||
|
var DATA_PATH = get_base_path() + "/jsonapi/";
|
||||||
|
var TYPES = ["Head", "Body", "Arms", "Waist", "Legs"];
|
||||||
|
var ELEMENTS = ["fire", "water", "thunder", "ice", "dragon"];
|
||||||
|
|
||||||
|
// dict mapping armor name to list containing id
|
||||||
|
var armor_ids = {};
|
||||||
|
|
||||||
|
// dict mapping skill name to object
|
||||||
|
var skill_trees = {};
|
||||||
|
|
||||||
|
// dict mapping type to armor name
|
||||||
|
var armors = {};
|
||||||
|
|
||||||
|
var decorations = { "Head": [], "Body": [], "Arms": [],
|
||||||
|
"Waist": [], "Legs": [] };
|
||||||
|
var slots_left = {};
|
||||||
|
|
||||||
|
$(document).ready(function(){
|
||||||
|
$.getJSON(DATA_PATH + "armor/_index_name.json",
|
||||||
|
function(data) {
|
||||||
|
armor_ids = data;
|
||||||
|
setup_autocomplete();
|
||||||
|
$.getJSON(DATA_PATH + "skilltree/_all.json",
|
||||||
|
function(data) {
|
||||||
|
skill_trees = data;
|
||||||
|
load_armors();
|
||||||
|
load_decorations();
|
||||||
|
// if nothing is loaded update won't be
|
||||||
|
// called, so force an update
|
||||||
|
update_skills();
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$("#armor_table").on("click", "button.add_decoration",
|
||||||
|
function (evt) {
|
||||||
|
add_decoration_by_element(evt.target.id);
|
||||||
|
});
|
||||||
|
$("#armor_table").on("click", "button.remove_decoration",
|
||||||
|
function (evt) {
|
||||||
|
remove_decoration_by_element(evt.target.id);
|
||||||
|
});
|
||||||
|
// TODO: update skills
|
||||||
|
});
|
||||||
|
|
||||||
|
function load_armors() {
|
||||||
|
armors_saved = localStorage.getItem("armor_names");
|
||||||
|
if (armors_saved != null) {
|
||||||
|
armor_names = JSON.parse(armors_saved);
|
||||||
|
$.each(armor_names, function(type, name) {
|
||||||
|
if (name) {
|
||||||
|
$("#" + type).val(name);
|
||||||
|
set_armor(type, name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function load_decorations() {
|
||||||
|
decorations_saved = localStorage.getItem("decoration_name_lists");
|
||||||
|
if (decorations_saved != null) {
|
||||||
|
dname_list = JSON.parse(decorations_saved);
|
||||||
|
$.each(dname_list, function(type, names) {
|
||||||
|
$.each(names, function(i, name) {
|
||||||
|
add_decoration(type, name);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_decoration_by_element(element_id) {
|
||||||
|
parts = element_id.split("_");
|
||||||
|
type = parts[0];
|
||||||
|
value = $("#" + type + "_decoration").val();
|
||||||
|
add_decoration(type, value);
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_decoration_by_element(element_id) {
|
||||||
|
parts = element_id.split("_");
|
||||||
|
type = parts[0];
|
||||||
|
index = parts[3];
|
||||||
|
remove_decoration(type, index);
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_decoration_autocomplete(type, max_slots) {
|
||||||
|
options = [];
|
||||||
|
$.each(skill_trees, function(skill_name, stree) {
|
||||||
|
$.each(stree["decoration_values"], function(i, points) {
|
||||||
|
nslots = i + 1;
|
||||||
|
if (nslots <= max_slots && points > 0) {
|
||||||
|
option_name = stree["name"] + " +" + points;
|
||||||
|
options.push(option_name);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
$("#" + type + "_decoration").autocomplete({ source: options });
|
||||||
|
$("#" + type + "_decoration").keypress(function(e) {
|
||||||
|
if (e.which == 13) {
|
||||||
|
value = $("#" + type + "_decoration").val();
|
||||||
|
add_decoration(type, value);
|
||||||
|
}
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
function save_armors() {
|
||||||
|
var armor_names = {};
|
||||||
|
$.each(armors, function(type, armor) {
|
||||||
|
armor_names[type] = armor["name"];
|
||||||
|
});
|
||||||
|
localStorage.setItem("armor_names", JSON.stringify(armor_names));
|
||||||
|
}
|
||||||
|
|
||||||
|
function save_decorations() {
|
||||||
|
var decoration_name_lists = {};
|
||||||
|
$.each(decorations, function(type, dlist) {
|
||||||
|
$.each(dlist, function(i, d) {
|
||||||
|
if (! (type in decoration_name_lists)) {
|
||||||
|
decoration_name_lists[type] = [];
|
||||||
|
}
|
||||||
|
decoration_name_lists[type].push(d["display_name"]);
|
||||||
|
});
|
||||||
|
});
|
||||||
|
localStorage.setItem("decoration_name_lists",
|
||||||
|
JSON.stringify(decoration_name_lists));
|
||||||
|
}
|
||||||
|
|
||||||
|
function get_base_path() {
|
||||||
|
var path = document.location.pathname;
|
||||||
|
return path.substring(0, path.lastIndexOf('/'));
|
||||||
|
}
|
||||||
|
|
||||||
|
function setup_autocomplete() {
|
||||||
|
$.getJSON(DATA_PATH + "armor/_index_slot.json",
|
||||||
|
function(data) {
|
||||||
|
$.each(TYPES,
|
||||||
|
function(i, type) {
|
||||||
|
$("#" + type).autocomplete(
|
||||||
|
{ source: data[type],
|
||||||
|
change: function (event, ui) {
|
||||||
|
set_armor(this.id, ui.item["value"]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
$("#" + type).keypress(function(e) {
|
||||||
|
if (e.which == 13) {
|
||||||
|
set_armor(this.id, $("#" + this.id).val());
|
||||||
|
}
|
||||||
|
});
|
||||||
|
});
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function add_decoration(type, value) {
|
||||||
|
parts = value.split(" +");
|
||||||
|
skill = parts[0]
|
||||||
|
points = parts[1]
|
||||||
|
slots = 0;
|
||||||
|
for (i=0; i < 3; i++) {
|
||||||
|
if (skill_trees[skill]["decoration_values"][i] == points) {
|
||||||
|
slots = i + 1;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
decoration_id = skill_trees[skill]["decoration_ids"][slots-1];
|
||||||
|
$.getJSON(DATA_PATH + "decoration/" + decoration_id + ".json",
|
||||||
|
function (data) {
|
||||||
|
if (! (type in decorations)) {
|
||||||
|
decorations[type] = []
|
||||||
|
}
|
||||||
|
data["display_name"] = value;
|
||||||
|
decorations[type].push(data);
|
||||||
|
slots_left[type] -= data["num_slots"];
|
||||||
|
save_decorations();
|
||||||
|
update_slots(type);
|
||||||
|
update_skills();
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function remove_decoration(type, index) {
|
||||||
|
d = decorations[type][index];
|
||||||
|
slots_left[type] += d["num_slots"];
|
||||||
|
decorations[type].splice(index, 1);
|
||||||
|
save_decorations();
|
||||||
|
update_slots(type);
|
||||||
|
update_skills();
|
||||||
|
}
|
||||||
|
|
||||||
|
function set_armor(type, name, noupdate) {
|
||||||
|
armor_id = armor_ids[name][0];
|
||||||
|
$.getJSON(DATA_PATH + "armor/" + armor_id + ".json",
|
||||||
|
function(data) {
|
||||||
|
armors[type] = data;
|
||||||
|
if (noupdate == undefined) {
|
||||||
|
save_armors();
|
||||||
|
decorations[type] = [];
|
||||||
|
slots_left[type] = data["num_slots"];
|
||||||
|
var skill_names = Object.keys(data["skills"]);
|
||||||
|
skill_names.sort();
|
||||||
|
var slist = "";
|
||||||
|
$.each(skill_names, function(i, sname) {
|
||||||
|
if (i != 0) {
|
||||||
|
slist += ", ";
|
||||||
|
}
|
||||||
|
slist += sname + " " + data["skills"][sname];
|
||||||
|
});
|
||||||
|
$("#" + type + "_skills").html(slist);
|
||||||
|
update_slots(type);
|
||||||
|
update_skills();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_slots(type) {
|
||||||
|
var free_slots = slots_left[type];
|
||||||
|
var slots_html = new EJS(
|
||||||
|
{ url: "templates/decorations.ejs" }
|
||||||
|
).render({ decorations: decorations[type],
|
||||||
|
free_slots: free_slots,
|
||||||
|
type: type });
|
||||||
|
$("#" + type + "_slots").html(slots_html);
|
||||||
|
if (free_slots > 0) {
|
||||||
|
setup_decoration_autocomplete(type, free_slots);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function update_skills() {
|
||||||
|
// map of skill name to total
|
||||||
|
var skills = {};
|
||||||
|
|
||||||
|
// map of type to dict map of skill name to total including decoration
|
||||||
|
var tskills_by_type = {};
|
||||||
|
|
||||||
|
// map of type to dict map of skill name to total from decorations only
|
||||||
|
var dskills_by_type = {};
|
||||||
|
|
||||||
|
var element_resist = {};
|
||||||
|
var slots = 0;
|
||||||
|
var slots_free = 0;
|
||||||
|
|
||||||
|
$.each(armors, function(type, armor) {
|
||||||
|
dskills_by_type[type] = {};
|
||||||
|
tskills_by_type[type] = {};
|
||||||
|
$.each(armor["skills"], function(skill_name, skill_value) {
|
||||||
|
if (! (skill_name in skills)) {
|
||||||
|
skills[skill_name] = 0;
|
||||||
|
}
|
||||||
|
skills[skill_name] += skill_value;
|
||||||
|
|
||||||
|
if (! (skill_name in tskills_by_type[type])) {
|
||||||
|
tskills_by_type[type][skill_name] = 0;
|
||||||
|
}
|
||||||
|
tskills_by_type[type][skill_name] += skill_value;
|
||||||
|
})
|
||||||
|
$.each(decorations[type], function(i, decoration) {
|
||||||
|
$.each(decoration["skills"],
|
||||||
|
function(skill_name, skill_value) {
|
||||||
|
if (! (skill_name in skills)) {
|
||||||
|
skills[skill_name] = 0;
|
||||||
|
}
|
||||||
|
skills[skill_name] += skill_value;
|
||||||
|
|
||||||
|
if (! (skill_name in dskills_by_type[type])) {
|
||||||
|
dskills_by_type[type][skill_name] = 0;
|
||||||
|
}
|
||||||
|
dskills_by_type[type][skill_name] += skill_value;
|
||||||
|
|
||||||
|
if (! (skill_name in tskills_by_type[type])) {
|
||||||
|
tskills_by_type[type][skill_name] = 0;
|
||||||
|
}
|
||||||
|
tskills_by_type[type][skill_name] += skill_value;
|
||||||
|
}
|
||||||
|
);
|
||||||
|
})
|
||||||
|
$.each(ELEMENTS, function(i, element) {
|
||||||
|
key = element + "_res";
|
||||||
|
if (! (element in element_resist)) {
|
||||||
|
element_resist[element] = 0;
|
||||||
|
}
|
||||||
|
element_resist[element] += armor[key];
|
||||||
|
$("#" + type + "_" + element).html(armor[key]);
|
||||||
|
})
|
||||||
|
slots += armor["num_slots"];
|
||||||
|
slots_free += slots_left[type];
|
||||||
|
//$("#" + type + "_slots").html(armor["num_slots"]);
|
||||||
|
});
|
||||||
|
$("#Total_slots").html((slots - slots_free)
|
||||||
|
+ " used / " + slots + " slots");
|
||||||
|
|
||||||
|
var skill_names = Object.keys(skills);
|
||||||
|
skill_names.sort(function(a, b) {
|
||||||
|
sa = skills[a] ? skills[a] : 0;
|
||||||
|
sb = skills[b] ? skills[b] : 0;
|
||||||
|
return sb - sa;
|
||||||
|
});
|
||||||
|
|
||||||
|
var skills_table = new EJS(
|
||||||
|
{ url: "templates/skills.ejs" }
|
||||||
|
).render({ TYPES: TYPES,
|
||||||
|
skills: skills,
|
||||||
|
dskills_by_type: dskills_by_type,
|
||||||
|
tskills_by_type: tskills_by_type,
|
||||||
|
active_skills: skill_names,
|
||||||
|
armors: armors });
|
||||||
|
$("#skills_div").html(skills_table);
|
||||||
|
|
||||||
|
var resist_table = new EJS(
|
||||||
|
{ url: "templates/resistance.ejs" }
|
||||||
|
).render({ TYPES: TYPES,
|
||||||
|
ELEMENTS: ELEMENTS,
|
||||||
|
armors: armors,
|
||||||
|
element_resist: element_resist });
|
||||||
|
$("#resist_div").html(resist_table);
|
||||||
|
|
||||||
|
}
|
||||||
|
</script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<table id="armor_table" cellpadding="2" cellspacing="2">
|
||||||
|
<tr>
|
||||||
|
<td><label for="Head">Head:</label></td>
|
||||||
|
<td><input id="Head" type="text" size="15" /></td>
|
||||||
|
<td id="Head_slots"> </td>
|
||||||
|
<td id="Head_skills"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><label for="Body">Body:</label></td>
|
||||||
|
<td><input id="Body" type="text" size="15" /></td>
|
||||||
|
<td id="Body_slots"> </td>
|
||||||
|
<td id="Body_skills"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><label for="Arms">Arms:</label></td>
|
||||||
|
<td><input id="Arms" type="text" size="15" /></td>
|
||||||
|
<td id="Arms_slots"> </td>
|
||||||
|
<td id="Arms_skills"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><label for="Waist">Waist:</label></td>
|
||||||
|
<td><input id="Waist" type="text" size="15" /></td>
|
||||||
|
<td id="Waist_slots"> </td>
|
||||||
|
<td id="Waist_skills"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td><label for="Legs">Legs:</label></td>
|
||||||
|
<td><input id="Legs" type="text" size="15" /></td>
|
||||||
|
<td id="Legs_slots"> </td>
|
||||||
|
<td id="Legs_skills"> </td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<th> </th>
|
||||||
|
<td> </td>
|
||||||
|
<td id="Total_slots">0</td>
|
||||||
|
<td> </td>
|
||||||
|
</tr>
|
||||||
|
</table>
|
||||||
|
<div id="flexbox">
|
||||||
|
<fieldset>
|
||||||
|
<legend>Skills</legend>
|
||||||
|
<div id="skills_div"></div>
|
||||||
|
</fieldset>
|
||||||
|
<fieldset>
|
||||||
|
<legend>Elemental Resistance</legend>
|
||||||
|
<div id="resist_div"></div>
|
||||||
|
</fieldset>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</body>
|
||||||
1
web/js/ejs_production.js
Normal file
1
web/js/ejs_production.js
Normal file
File diff suppressed because one or more lines are too long
18
web/templates/decorations.ejs
Normal file
18
web/templates/decorations.ejs
Normal file
@@ -0,0 +1,18 @@
|
|||||||
|
<table>
|
||||||
|
<% for(var i=0; i<decorations.length; i++) { %>
|
||||||
|
<tr>
|
||||||
|
<td><%= Array(decorations[i]["num_slots"] + 1).join("\u26ab") %></td>
|
||||||
|
<td><%= decorations[i]["display_name"] %>
|
||||||
|
<button id="<%= type %>_remove_decoration_<%= i %>"
|
||||||
|
class="remove_decoration">-</button></td>
|
||||||
|
</tr>
|
||||||
|
<% } %>
|
||||||
|
<% if (free_slots > 0) { %>
|
||||||
|
<tr>
|
||||||
|
<td><%= Array(free_slots + 1).join("\u26aa") %><%= Array(3- free_slots + 1).join(" ") %></td>
|
||||||
|
<td><input id="<%= type %>_decoration" type="text" size="12">
|
||||||
|
<button id="<%= type %>_add_decoration"
|
||||||
|
class="add_decoration">+</button></td>
|
||||||
|
</tr>
|
||||||
|
<% } %>
|
||||||
|
</table>
|
||||||
21
web/templates/resistance.ejs
Normal file
21
web/templates/resistance.ejs
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
<table id="resist_table" cellpadding="2" border="0">
|
||||||
|
<tr>
|
||||||
|
<th> </th>
|
||||||
|
<th>Total</th>
|
||||||
|
<th>Head</th>
|
||||||
|
<th>Body</th>
|
||||||
|
<th>Arms</th>
|
||||||
|
<th>Waist</th>
|
||||||
|
<th>Legs</th>
|
||||||
|
</tr>
|
||||||
|
<% for(var i=0; i<ELEMENTS.length; i++) { %>
|
||||||
|
<tr>
|
||||||
|
<th><%= ELEMENTS[i] %></th>
|
||||||
|
<td class="num"><%= element_resist[ELEMENTS[i]] %></td>
|
||||||
|
<% for(var j=0; j<TYPES.length; j++) { %>
|
||||||
|
<td class="num">
|
||||||
|
<%= armors[TYPES[j]]
|
||||||
|
? armors[TYPES[j]][ELEMENTS[i] + "_res"] : " " %></td>
|
||||||
|
<% } %>
|
||||||
|
<% } %>
|
||||||
|
</table>
|
||||||
25
web/templates/skills.ejs
Normal file
25
web/templates/skills.ejs
Normal file
@@ -0,0 +1,25 @@
|
|||||||
|
<table id="skills_table" cellpadding="2" border="0">
|
||||||
|
<tr>
|
||||||
|
<th> </th>
|
||||||
|
<th>Total</th>
|
||||||
|
<% for(var i=0; i<TYPES.length; i++) { %>
|
||||||
|
<td><%= TYPES[i] %></td>
|
||||||
|
<% } %>
|
||||||
|
</tr>
|
||||||
|
<% for(var i=0; i<active_skills.length; i++) { %>
|
||||||
|
<tr>
|
||||||
|
<td><%= active_skills[i] %></td>
|
||||||
|
<td class="num"><%= skills[active_skills[i]] %></td>
|
||||||
|
<% for(var j=0; j<TYPES.length; j++) { %>
|
||||||
|
<td class="num">
|
||||||
|
<%= (armors[TYPES[j]] && tskills_by_type[TYPES[j]][active_skills[i]])
|
||||||
|
? tskills_by_type[TYPES[j]][active_skills[i]]
|
||||||
|
: " " %>
|
||||||
|
<%= 0 && (armors[TYPES[j]] && dskills_by_type[TYPES[j]][active_skills[i]])
|
||||||
|
? " (" + dskills_by_type[TYPES[j]][active_skills[i]] + ")"
|
||||||
|
: " " %>
|
||||||
|
</td>
|
||||||
|
<% } %>
|
||||||
|
</tr>
|
||||||
|
<% } %>
|
||||||
|
</table>
|
||||||
24
web/templates/skills.ejs.bak
Normal file
24
web/templates/skills.ejs.bak
Normal file
@@ -0,0 +1,24 @@
|
|||||||
|
<table id="skills_table" cellpadding="2">
|
||||||
|
<tr>
|
||||||
|
<th>Skill</th>
|
||||||
|
<th>Total</th>
|
||||||
|
<% for(var i=0; i<TYPES.length; i++) { %>
|
||||||
|
<th><%= TYPES[i] %></th>
|
||||||
|
<% } %>
|
||||||
|
</tr>
|
||||||
|
<% for(var i=0; i<active_skills.length; i++) { %>
|
||||||
|
<tr>
|
||||||
|
<td><%= active_skills[i] %></td>
|
||||||
|
<td><%= skills[active_skills[i]] %></td>
|
||||||
|
<% for(var j=0; j<TYPES.length; j++) { %>
|
||||||
|
<td>
|
||||||
|
<%= (armors[TYPES[j]] && armors[TYPES[j]]["skills"][active_skills[i]])
|
||||||
|
? armors[TYPES[j]]["skills"][active_skills[i]] : " " %>
|
||||||
|
<%= (armors[TYPES[j]] && dskills_by_type[TYPES[j]][active_skills[i]])
|
||||||
|
? " (" + dskills_by_type[TYPES[j]][active_skills[i]] + ")"
|
||||||
|
: " " %>
|
||||||
|
</td>
|
||||||
|
<% } %>
|
||||||
|
</tr>
|
||||||
|
<% } %>
|
||||||
|
</table>
|
||||||
Reference in New Issue
Block a user