diff --git a/db/_pathfix.py b/db/_pathfix.py new file mode 100644 index 0000000..d44515e --- /dev/null +++ b/db/_pathfix.py @@ -0,0 +1,11 @@ +""" +Hack to get scripts to run from source checkout without having to set +PYTHONPATH. +""" + +import sys +from os.path import dirname, join, abspath + +db_path = dirname(__file__) +project_path = abspath(join(db_path, "..")) +sys.path.insert(0, project_path) diff --git a/db/mh4u.db b/db/mh4u.db index 3f3ea6c..9d37aa7 100644 Binary files a/db/mh4u.db and b/db/mh4u.db differ diff --git a/db/schema-update.sql b/db/schema-update.sql new file mode 100644 index 0000000..42a70c2 --- /dev/null +++ b/db/schema-update.sql @@ -0,0 +1 @@ +ALTER TABLE quests ADD COLUMN rank text; diff --git a/db/set_quest_ranks.py b/db/set_quest_ranks.py new file mode 100755 index 0000000..a394ab3 --- /dev/null +++ b/db/set_quest_ranks.py @@ -0,0 +1,111 @@ +#!/usr/bin/env python + +import os.path +import codecs + +import _pathfix + +from mhapi.db import MHDB, Quest + + +RANK_NUM = dict(LR=0, HR=1, G=2) +RANK_NAME = ["LR", "HR", "G"] + + +def get_utf8_writer(writer): + return codecs.getwriter("utf8")(writer) + + +def set_quest_ranks(db): + quests = db.get_quests() + for quest in quests: + if not quest["name"]: + assert quest["hub"] == "Event" + print "WARN: skipping non localized event quest: %d" % quest["_id"] + continue + set_quest_rank(db, quest) + + +def set_quest_rank(db, quest_row): + quest_id = quest_row["_id"] + hub = quest_row["hub"] + stars = quest_row["stars"] + rank_stars_guess = guess_rank(hub, stars) + if isinstance(rank_stars_guess, tuple): + rewards = db.get_quest_rewards(quest_id) + rank = guess_quest_rank_from_rewards(db, rewards) + if rank is None: + print "WARN: quest '%s' has no flesh rewards, assuming lower rank"\ + % (quest_row["name"].encode("utf8"),) + rank = rank_stars_guess[0] + elif rank not in rank_stars_guess: + print "ERROR: quest '%s' reward guess '%s' not in stars guess '%s'"\ + % (quest_row["name"], rank, rank_stars_guess) + else: + rank = rank_stars_guess + + assert rank in "LR HR G".split() + + quest = Quest(quest_row) + quest.rank = rank + print quest.one_line_u() + cur = db.cursor() + cur.execute("UPDATE quests SET rank=? WHERE _id=?", (rank, quest_id)) + + +def guess_rank(hub, stars): + if hub == "Caravan": + # 6 * is actually a mix of LR and HR, + # and 10 * is mix of HR and G + if stars < 6: + return "LR" + elif stars == 6: + return ("LR", "HR") + elif stars == 10: + return ("HR", "G") + return "HR" + if hub in ("Guild", "Event"): + if stars < 4: + return "LR" + elif stars < 8: + return "HR" + return "G" + else: + raise ValueError("Unknown hub '%s'" % hub) + + +def guess_quest_rank_from_rewards(db, rewards_rows): + max_min_rank = RANK_NUM["LR"] + has_flesh_rewards = False + for reward in rewards_rows: + # for each flesh quest reward, see if it's only available from + # HR or G monsters + item = db.get_item(reward["item_id"]) + if item["type"] not in ("Flesh", "Sac/Fluid"): + continue + has_flesh_rewards = True + monsters = db.get_item_monsters(reward["item_id"]) + min_rank = 3 + for m in monsters: + rank = m["rank"] + if RANK_NUM[rank] < min_rank: + min_rank = RANK_NUM[rank] + if min_rank > max_min_rank and min_rank != 3: + max_min_rank = min_rank + if not has_flesh_rewards: + # Can't make useful guess from the rewards + return None + return RANK_NAME[max_min_rank] + + +if __name__ == '__main__': + from _pathfix import db_path + db_file = os.path.join(db_path, "mh4u.db") + db = MHDB(db_file) + + import sys + sys.stdout = get_utf8_writer(sys.stdout) + sys.stderr = get_utf8_writer(sys.stderr) + set_quest_ranks(db) + db.commit() + db.close() diff --git a/mhapi/db.py b/mhapi/db.py index 3704db2..3bba446 100644 --- a/mhapi/db.py +++ b/mhapi/db.py @@ -6,16 +6,19 @@ import string import sqlite3 - class Quest(object): def __init__(self, quest_row, quest_rewards=None): self._row = quest_row self.rewards = quest_rewards - self._template = string.Template( + self._full_template = string.Template( + "$name ($hub $stars* $rank)" + "\n Goal: $goal" + "\n Sub : $sub_goal" + ) + + self._one_line_template = string.Template( "$name ($hub $stars* $rank)" - + "\n Goal: $goal" - + "\n Sub : $sub_goal" ) self.id = quest_row["_id"] @@ -24,25 +27,16 @@ class Quest(object): self.hub = quest_row["hub"] self.goal = quest_row["goal"] self.sub_goal = quest_row["sub_goal"] - self.rank = get_rank(self.hub, self.stars) + self.rank = quest_row["rank"] - def __unicode__(self): - return self._template.substitute(self.__dict__) + def one_line_u(self): + return self._one_line_template.substitute(self.__dict__) + def full_u(self): + return self._full_template.substitute(self.__dict__) -def get_rank(hub, stars): - if hub == "Caravan": - if stars < 6: - return "LR" - elif stars < 10: - return "HR" - return "G" - if hub == "Guild": - if stars < 4: - return "LR" - elif stars < 8: - return "HR" - return "G" + def __unicode__(self): + return self.full_u() class MHDB(object): @@ -66,6 +60,15 @@ class MHDB(object): self.cache[key][args] = v return v + def cursor(self): + return self.conn.cursor() + + def commit(self): + return self.conn.commit() + + def close(self): + return self.conn.close() + def get_item_names(self): v = self._get_memoized("item_names", """ SELECT _id, name FROM items @@ -129,6 +132,12 @@ class MHDB(object): """, quest_id) return v[0] if v else None + def get_quests(self): + v = self._get_memoized("quests", """ + SELECT * FROM quests + """) + return v + def get_quest_rewards(self, quest_id): v = self._get_memoized("quest_rewards", """ SELECT * FROM quest_rewards