new web index, refactor, data fixes

main
Bryce Allen 11 years ago
parent 9bad89b0af
commit f6fa342ac4

@ -7,7 +7,7 @@ import json
import _pathfix import _pathfix
from mhapi.db import MHDB from mhapi.db import MHDB
from mhapi.model import ModelJSONEncoder from mhapi.model import ModelJSONEncoder, get_costs
def parse_args(argv): def parse_args(argv):
@ -23,36 +23,6 @@ def parse_args(argv):
return parser.parse_args(argv) 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__': if __name__ == '__main__':
args = parse_args(None) args = parse_args(None)

@ -139,7 +139,7 @@ def skilltree_json(db, path):
def weapon_json(db, path): def weapon_json(db, path):
weapons = db.get_weapons() weapons = db.get_weapons(get_components=True)
mkdirs_p(path) mkdirs_p(path)
write_list_file(path, weapons) write_list_file(path, weapons)
@ -150,6 +150,14 @@ def weapon_json(db, path):
with open(weapon_path, "w") as f: with open(weapon_path, "w") as f:
w.json_dump(f) w.json_dump(f)
tree_path = os.path.join(path, "%s_tree.json" % w.id)
costs = model.get_costs(db, w)
for cost in costs:
cost["path"] = [dict(name=w.name, id=w.id)
for w in cost["path"]]
with open(tree_path, "w") as f:
json.dump(costs, f, cls=model.ModelJSONEncoder, indent=2)
write_index_file(path, indexes) write_index_file(path, indexes)
@ -176,12 +184,15 @@ def main():
else: else:
outpath = os.path.join(_pathfix.web_path, "jsonapi") outpath = os.path.join(_pathfix.web_path, "jsonapi")
items_json(db, os.path.join(outpath, "item"))
weapon_json(db, os.path.join(outpath, "weapon")) weapon_json(db, os.path.join(outpath, "weapon"))
sys.exit(0)
items_json(db, os.path.join(outpath, "item"))
monster_json(db, os.path.join(outpath, "monster")) monster_json(db, os.path.join(outpath, "monster"))
armor_json(db, os.path.join(outpath, "armor")) armor_json(db, os.path.join(outpath, "armor"))
skilltree_json(db, os.path.join(outpath, "skilltree")) skilltree_json(db, os.path.join(outpath, "skilltree"))
decoration_json(db, os.path.join(outpath, "decoration")) decoration_json(db, os.path.join(outpath, "decoration"))
#quest_json(db, os.path.join(outpath, "quest")) #quest_json(db, os.path.join(outpath, "quest"))

Binary file not shown.

@ -0,0 +1,44 @@
#!/usr/bin/env python
import os.path
import codecs
import csv
import _pathfix
from mhapi.db import MHDB
def set_upgrade_cost(db, item_id, upgrade_cost):
print "upgrade_cost", item_id, upgrade_cost
cur = db.cursor()
cur.execute("""UPDATE weapons SET
upgrade_cost=? WHERE _id=?""",
(upgrade_cost, item_id))
def set_creation_cost(db, item_id, creation_cost):
print "creation_cost", item_id, creation_cost
cur = db.cursor()
cur.execute("""UPDATE weapons SET
creation_cost=? WHERE _id=?""",
(creation_cost, item_id))
if __name__ == '__main__':
db = MHDB()
delta_file_path = os.path.join(_pathfix.db_path, "weapons-delta.csv")
with open(delta_file_path) as f:
reader = csv.DictReader(f)
for row in reader:
item_id = row["id"]
creation_cost = row["creation_cost"]
upgrade_cost = row["upgrade_cost"]
if creation_cost:
set_creation_cost(db, item_id, creation_cost)
if upgrade_cost:
set_upgrade_cost(db, item_id, upgrade_cost)
db.commit()
db.close()

@ -0,0 +1,3 @@
id,name,creation_cost,upgrade_cost
6302,"Defender's Lance",3225,2150
6808,"Demonlord Cudgel",,100000
1 id name creation_cost upgrade_cost
2 6302 Defender's Lance 3225 2150
3 6808 Demonlord Cudgel 100000

@ -284,11 +284,15 @@ class MHDB(object):
WHERE monster_id=? WHERE monster_id=?
""", (monster_id,), collection_cls=model.MonsterDamage) """, (monster_id,), collection_cls=model.MonsterDamage)
def get_weapons(self): def get_weapons(self, get_components=False):
return self._query_all("weapons", """ results = self._query_all("weapons", """
SELECT * FROM weapons SELECT * FROM weapons
LEFT JOIN items ON weapons._id = items._id LEFT JOIN items ON weapons._id = items._id
""", model_cls=model.Weapon) """, model_cls=model.Weapon)
if results and get_components:
for r in results:
self._add_components(r)
return results
def _add_components(self, item_data): def _add_components(self, item_data):
ccomps = self.get_item_components(item_data.id, "Create") ccomps = self.get_item_components(item_data.id, "Create")

@ -507,3 +507,59 @@ def _break_find(part, parts, breaks):
if matches: if matches:
return matches[0] return matches[0]
return None return None
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:
if not weapon.upgrade_cost:
# db has errors where upgrade cost is listed as create
# cost and components are listed under create. Assume
# parent_id is correct, and they are upgrade only.
if not weapon.upgrade_components and weapon.create_components:
weapon.upgrade_components = weapon.create_components
weapon.create_components = []
weapon.upgrade_cost = weapon.creation_cost
weapon.creation_cost = 0
try:
upgrade_cost = int(weapon.upgrade_cost)
except ValueError:
upgrade_cost = 0
print "WARN: bad upgrade cost for '%s' (%s): '%s'" \
% (weapon.name, weapon.id, weapon.upgrade_cost)
except UnicodeError:
upgrade_cost = 0
cost_display = urllib.quote(weapon.upgrade_cost)
print "WARN: bad upgrade cost for '%s' (%s): '%s'" \
% (weapon.name, weapon.id, cost_display)
parent_weapon = db.get_weapon(weapon.parent_id, True)
costs = get_costs(db, parent_weapon)
for cost in costs:
cost["zenny"] += upgrade_cost
cost["path"] += [weapon]
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
if weapon.create_components:
try:
zenny = int(weapon.creation_cost)
except ValueError:
print "WARN: bad creation cost for '%s': '%s'" \
% (weapon.name, weapon.creation_cost)
zenny = weapon.upgrade_cost or 0
create_cost = dict(zenny=zenny,
path=[weapon],
components={})
for item in weapon.create_components:
create_cost["components"][item.name] = item.quantity
costs = [create_cost] + costs
return costs

@ -1,65 +1,74 @@
<html> <html>
<head> <head>
<title>Monster Hunter Item Search</title> <title>Poogie's Toolbox</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> <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" /> <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 src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script>
<style> <script src="js/common.js"></script>
.flex {
width: 100%;
height: 100%;
display: flex;
flex-direction: column;
}
label {
font-weight: bold;
font-family: sans, sans-serif;
}
#output { flex: 99 1 auto; }
</style>
<script type="text/javascript"> <script type="text/javascript">
$(document).ready(function(){ $(document).ready(function(){
$("#search").click(update_search); setup_item_autocomplete("#item");
$("#item").keypress(function(e) { setup_weapon_autocomplete("#weapon_type", "#weapon");
if (e.which == 13) { update_search(); }
});
setup_autocomplete();
}); });
</script>
function setup_autocomplete() { <style>
$.getJSON("/mhapi/item_name_list", label {
function(data) { font-weight: bold;
$("#item").autocomplete({ source: data }); font-family: sans, sans-serif;
});
}
function update_search() {
var item_name = $.trim($("#item").val());
$.get("/mhapi/rewards",
{ "item_name": item_name },
function(data) {
$("#output").text(data);
});
} }
</script> </style>
</head> </head>
<body> <body>
<div class="flex"> <form action="recommends.html" method="GET">
<div> <fieldset>
<label for="item">Item:</label> <legend title="Find the best quests and armor skills for farming an item."
<input id="item" type="text" size="20" /> >Poogie Recommends</legend>
<button id="search">Ask Poogie</button> <label for="item">Item:</label>
<a href="https://github.com/bd4/monster-hunter-scripts/blob/master/RECOMMENDATIONS.adoc">Understanding Results</a> <input id="item" name="item" type="text" size="20" />
(<a href="https://github.com/bd4/monster-hunter-scripts">source</a>) <input type="submit" value="Ask Poogie" />
</div> <p></p>
<br /> </fieldset>
<textarea readonly="true" rows="10" cols="80" id="output"></textarea> </form>
</div> <form action="weaponplanner.html" method="GET">
<fieldset>
<legend title="Compare the cost of making a weapon from different starting points in the tree"
>Poogie's Weapon Planner</legend>
<table>
<tr>
<td><label for="type">Type:</label></td>
<td><select id="weapon_type" name="weapon_type">
<option value="All">All</option>
<option value="Great Sword">Great Sword</option>
<option value="Long Sword">Long Sword</option>
<option value="Sword and Shield">Sword and Shield</option>
<option value="Dual Blades">Dual Blades</option>
<option value="Hammer">Hammer</option>
<option value="Hunting Horn">Hunting Horn</option>
<option value="Lance">Lance</option>
<option value="Gunlance">Gunlance</option>
<option value="Switch Axe">Switch Axe</option>
<option value="Charge Blade">Charge Blade</option>
<option value="Insect Glaive">Insect Glaive</option>
<option value="Light Bowgun">Light Bowgun</option>
<option value="Heavy Bowgun">Heavy Bowgun</option>
<option value="Bow">Bow</option>
</select></td>
</tr>
<tr>
<td><label for="weapon">Weapon:</label></td>
<td><input id="weapon" name="weapon" weapon="text" size="20" />
<input type="submit" value="Ask Poogie" /></td>
</tr>
</table>
</fieldset>
</form>
<fieldset>
<legend title="Plan armor sets">Poogie Outfitters</legend>
<a href="outfitters.html">Armor set planner</a>
</fieldset>
</body> </body>

@ -0,0 +1,109 @@
WEAPON_NAME_IDX = {};
WEAPON_TYPE_IDX = {};
(function($) {
$.QueryString = (function(a) {
if (a == "") return {};
var b = {};
for (var i = 0; i < a.length; ++i)
{
var p=a[i].split('=');
if (p.length != 2) continue;
b[p[0]] = decodeURIComponent(p[1].replace(/\+/g, " "));
}
return b;
})(window.location.search.substr(1).split('&'))
})(jQuery);
function encode_utf8(s) {
return unescape(encodeURIComponent(s));
}
function get_base_path() {
var path = document.location.pathname;
return path.substring(0, path.lastIndexOf('/'));
}
function normalize_name(s) {
var chars = s.split("");
var cap_next = true;
var i;
for (i=0; i<chars.length; i++) {
if (cap_next) {
chars[i] = chars[i].toUpperCase();
cap_next = false;
} else if (chars[i] == "." || chars[i] == " " || chars[i] == "-") {
cap_next = true;
} else {
chars[i] = chars[i].toLowerCase();
}
}
return chars.join("");
}
function setup_item_autocomplete(selector) {
var DATA_PATH = get_base_path() + "/rewards/";
$.getJSON(DATA_PATH + "items.json",
function(data) {
$(selector).autocomplete({ source: data });
});
}
function setup_weapon_autocomplete(type_selector, weapon_selector, ready_fn,
change_fn) {
var DATA_PATH = get_base_path() + "/jsonapi/";
$.getJSON(DATA_PATH + "weapon/_index_name.json",
function(data) {
WEAPON_NAME_IDX = data;
$.getJSON(DATA_PATH + "weapon/_index_wtype.json",
function(data) {
WEAPON_TYPE_IDX = data;
if (ready_fn) {
ready_fn();
}
_setup_weapon_autocomplete(
$(type_selector).val(),
weapon_selector,
change_fn);
$(type_selector).change(function(evt) {
_setup_weapon_autocomplete(
$(type_selector).val(),
weapon_selector, change_fn);
});
});
});
}
function _setup_weapon_autocomplete(type, weapon_selector, change_fn) {
//alert("set weapon type " + type + " (" + weapon_selector + ")");
var source;
if (type == "All") {
source = Object.keys(WEAPON_NAME_IDX);
//alert(source[10]);
} else {
var object_list = WEAPON_TYPE_IDX[type];
source = [];
for (i=0; i<object_list.length; i++) {
source.push(object_list[i]["name"]);
}
}
$(weapon_selector).autocomplete(
{ source: source,
change: function (event, ui) {
if (change_fn) {
change_fn(ui.item["value"]);
}
}
}
);
$(weapon_selector).keypress(function(e) {
if (e.which == 13 && change_fn) {
change_fn($(weapon_selector).val());
}
});
}

@ -9,6 +9,8 @@
<script type="text/javascript" src="js/ejs_production.js"></script> <script type="text/javascript" src="js/ejs_production.js"></script>
<script src="js/common.js"></script>
<style> <style>
label { label {
font-weight: bold; font-weight: bold;
@ -309,11 +311,6 @@
localStorage.setItem("decoration_name_lists", svalue); localStorage.setItem("decoration_name_lists", svalue);
} }
function get_base_path() {
var path = document.location.pathname;
return path.substring(0, path.lastIndexOf('/'));
}
function setup_autocomplete() { function setup_autocomplete() {
$.getJSON(DATA_PATH + "armor/_index_slot.json", $.getJSON(DATA_PATH + "armor/_index_slot.json",
function(data) { function(data) {

@ -7,6 +7,8 @@
<link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/themes/smoothness/jquery-ui.css" /> <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 src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.3/jquery-ui.min.js"></script>
<script src="js/common.js"></script>
<style> <style>
.flex { .flex {
width: 100%; width: 100%;
@ -31,41 +33,13 @@
$("#item").keypress(function(e) { $("#item").keypress(function(e) {
if (e.which == 13) { update_search(); } if (e.which == 13) { update_search(); }
}); });
setup_autocomplete(); setup_item_autocomplete("#item");
}); var item_name = $.QueryString["item"];
if (item_name) {
function encode_utf8(s) { $("#item").val(item_name);
return unescape(encodeURIComponent(s)); update_search();
}
function get_base_path() {
var path = document.location.pathname;
return path.substring(0, path.lastIndexOf('/'));
}
function normalize_name(s) {
var chars = s.split("");
var cap_next = true;
var i;
for (i=0; i<chars.length; i++) {
if (cap_next) {
chars[i] = chars[i].toUpperCase();
cap_next = false;
} else if (chars[i] == "." || chars[i] == " " || chars[i] == "-") {
cap_next = true;
} else {
chars[i] = chars[i].toLowerCase();
}
} }
return chars.join(""); });
}
function setup_autocomplete() {
$.getJSON(DATA_PATH + "items.json",
function(data) {
$("#item").autocomplete({ source: data });
});
}
function update_search() { function update_search() {
var item_name = $.trim($("#item").val()); var item_name = $.trim($("#item").val());

@ -1,6 +1,6 @@
<html> <html>
<head> <head>
<title>Poogie's Weapon Tree</title> <title>Poogie's Weapon Planner</title>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script> <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.3/jquery.min.js"></script>
@ -9,6 +9,8 @@
<script type="text/javascript" src="js/ejs_production.js"></script> <script type="text/javascript" src="js/ejs_production.js"></script>
<script type="text/javascript" src="js/common.js"></script>
<style> <style>
label { label {
font-weight: bold; font-weight: bold;
@ -42,36 +44,23 @@
<script type="text/javascript"> <script type="text/javascript">
var DATA_PATH = get_base_path() + "/jsonapi/"; var DATA_PATH = get_base_path() + "/jsonapi/";
var WEAPON_NAME_IDX = {};
var template_path = new EJS({ url: "templates/weaponpath.ejs" }); var template_path = new EJS({ url: "templates/weaponpath.ejs" });
$(document).ready(function(){ $(document).ready(function(){
$.getJSON(DATA_PATH + "weapon/_index_name.json", setup_weapon_autocomplete("#weapon_type", "#weapon",
function(data) { load_qs, show_trees);
WEAPON_NAME_IDX = data;
setup_autocomplete();
});
}); });
function get_base_path() { function load_qs() {
var path = document.location.pathname; var wtype = $.QueryString["weapon_type"];
return path.substring(0, path.lastIndexOf('/')); var weapon = $.QueryString["weapon"];
} if (wtype) {
$("#weapon_type").val(wtype);
function setup_autocomplete() { }
$("#weapon").autocomplete( if (weapon) {
{ source: Object.keys(WEAPON_NAME_IDX), $("#weapon").val(weapon);
change: function (event, ui) { show_trees(weapon);
show_trees(ui.item["value"]); }
}
}
);
$("#weapon").keypress(function(e) {
if (e.which == 13) {
show_trees($("#weapon").val());
}
});
} }
function show_trees(weapon_name) { function show_trees(weapon_name) {
@ -115,9 +104,33 @@
</head> </head>
<body> <body>
<div> <div>
<label for="weapon">Weapon:</label> <table>
<input id="weapon" type="text" size="20" /> <tr>
<button id="search">Ask Poogie</button> <td><label for="type">Type:</label></td>
<td><select id="weapon_type" name="weapon_type">
<option value="All">All</option>
<option value="Great Sword">Great Sword</option>
<option value="Long Sword">Long Sword</option>
<option value="Sword and Shield">Sword and Shield</option>
<option value="Dual Blades">Dual Blades</option>
<option value="Hammer">Hammer</option>
<option value="Hunting Horn">Hunting Horn</option>
<option value="Lance">Lance</option>
<option value="Gunlance">Gunlance</option>
<option value="Switch Axe">Switch Axe</option>
<option value="Charge Blade">Charge Blade</option>
<option value="Insect Glaive">Insect Glaive</option>
<option value="Light Bowgun">Light Bowgun</option>
<option value="Heavy Bowgun">Heavy Bowgun</option>
<option value="Bow">Bow</option>
</select></td>
</tr>
<tr>
<td><label for="weapon">Weapon:</label></td>
<td><input id="weapon" name="weapon" weapon="text" size="20" />
<input type="submit" value="Ask Poogie" /></td>
</tr>
</table>
</div> </div>
<div id="results" class="flexbox"></div> <div id="results" class="flexbox"></div>
</body> </body>
Loading…
Cancel
Save