refactor: separate calculations and print

This commit is contained in:
Bryce Allen
2015-03-22 12:03:55 -05:00
parent 8af6a3a577
commit a449087aba
4 changed files with 147 additions and 104 deletions

View File

@@ -34,4 +34,7 @@ if __name__ == '__main__':
item_row = rewards.find_item(db, item_name, err_out) item_row = rewards.find_item(db, item_name, err_out)
if item_row is None: if item_row is None:
sys.exit(os.EX_DATAERR) sys.exit(os.EX_DATAERR)
rewards.print_quests_and_rewards(db, item_row, out) ir = rewards.ItemRewards(db, item_row)
ir.print_recommended_hunts(out)
ir.print_monsters(out)
ir.print_quests(out)

View File

@@ -10,7 +10,7 @@ import sqlite3
class Quest(object): class Quest(object):
def __init__(self, quest_row, quest_rewards): def __init__(self, quest_row, quest_rewards):
self._row = quest_row self._row = quest_row
self._rewards = quest_rewards self.rewards = quest_rewards
self._template = string.Template( self._template = string.Template(
"$name ($hub $stars* $rank)" "$name ($hub $stars* $rank)"

View File

@@ -97,8 +97,9 @@ class QuestItemExpectedValue(object):
@param quest_rewards: list of rows from quest_rewards table for a single @param quest_rewards: list of rows from quest_rewards table for a single
quest quest
""" """
def __init__(self, item_id, quest_rewards): def __init__(self, item_id, quest):
self.item_id = item_id self.item_id = item_id
self.quest = quest
self.fixed_rewards = dict(A=0, B=0, Sub=0) self.fixed_rewards = dict(A=0, B=0, Sub=0)
self.total_reward_p = dict(A=0, B=0, Sub=0) self.total_reward_p = dict(A=0, B=0, Sub=0)
@@ -108,7 +109,7 @@ class QuestItemExpectedValue(object):
self.slot_rewards = dict(A=[], B=[], Sub=[]) self.slot_rewards = dict(A=[], B=[], Sub=[])
self.total_expected_values = [0, 0, 0] self.total_expected_values = [0, 0, 0]
self._set_rewards(quest_rewards) self._set_rewards(quest.rewards)
def is_sub(self): def is_sub(self):
"""Item is available from sub quest""" """Item is available from sub quest"""
@@ -305,9 +306,12 @@ class RankAndSkills(object):
Helper to track the best strategy with a given set of skills and hunter Helper to track the best strategy with a given set of skills and hunter
rank. rank.
""" """
def __init__(self, rank, cap_skill=stats.CAP_SKILL_NONE, def __init__(self, rank="G",
luck_skill=stats.LUCK_SKILL_NONE,
cap_skill=stats.CAP_SKILL_NONE,
carving_skill=stats.CARVING_SKILL_NONE): carving_skill=stats.CARVING_SKILL_NONE):
self.rank = rank self.rank = rank
self.luck_skill = luck_skill
self.cap_skill = cap_skill self.cap_skill = cap_skill
self.carving_skill = carving_skill self.carving_skill = carving_skill
self.best = None self.best = None
@@ -328,6 +332,12 @@ class RankAndSkills(object):
return True return True
return False return False
def add_quest_item(self, quest_item):
if self.rank == "LR" and quest_item.rank != "LR":
return False
if self.rank == "HR" and quest_item.monster_rank == "G":
return False
class HuntItemStrategy(object): class HuntItemStrategy(object):
""" """
@@ -345,8 +355,8 @@ class HuntItemStrategy(object):
cap_skill=cap_skill) cap_skill=cap_skill)
def print(self, out): def print(self, out):
out.write("%s %s %s (%5.2f)\n" out.write("%s %s %s (%5.2f)\n" %
% (self.hunt_item.monster_name, (self.hunt_item.monster_name,
self.hunt_item.monster_rank, self.hunt_item.monster_rank,
self.strat, self.ev)) self.strat, self.ev))
@@ -369,7 +379,6 @@ class HuntItemExpectedValue(object):
@param hunt_rewards: list of rows from hunt_rewards table for a single @param hunt_rewards: list of rows from hunt_rewards table for a single
monster and rank monster and rank
""" """
def __init__(self, item_id, monster_name, monster_rank, hunt_rewards): def __init__(self, item_id, monster_name, monster_rank, hunt_rewards):
self.item_id = item_id self.item_id = item_id
self.monster_name = monster_name self.monster_name = monster_name
@@ -416,27 +425,65 @@ class HuntItemExpectedValue(object):
self.matching_rewards.append(reward) self.matching_rewards.append(reward)
def print_monsters_and_rewards(db, item_row, out): class ItemRewards(object):
item_id = item_row["_id"] def __init__(self, db, item_row):
monsters = db.get_item_monsters(item_id) self.db = db
self.item_row = item_row
self.item_id = item_row["_id"]
skill_sets = OrderedDict([ self. skill_sets = OrderedDict([
("No skills" , RankAndSkills("G")), ("No skills", RankAndSkills("G")),
("Capture God" , RankAndSkills("G", cap_skill=stats.CAP_SKILL_GOD)), ("Capture God", RankAndSkills("G", cap_skill=stats.CAP_SKILL_GOD)),
("Carving God" , RankAndSkills("G", ("Carving God",
carving_skill=stats.CARVING_SKILL_GOD)), RankAndSkills("G", carving_skill=stats.CARVING_SKILL_GOD)),
("Low Rank" , RankAndSkills("LR")), ("Great Luck",
("High Rank" , RankAndSkills("HR")), RankAndSkills("G", luck_skill=stats.LUCK_SKILL_GREAT)),
("Low Rank", RankAndSkills("LR")),
("High Rank", RankAndSkills("HR")),
]) ])
self._hunt_items = OrderedDict()
self._quest_items = OrderedDict()
self._find_hunt_items()
self._find_quest_items()
def _find_hunt_items(self):
monsters = self.db.get_item_monsters(self.item_id)
for m in monsters: for m in monsters:
mid = m["monster_id"] mid = m["monster_id"]
rank = m["rank"] rank = m["rank"]
monster = db.get_monster(mid) monster = self.db.get_monster(mid)
reward_rows = db.get_monster_rewards(mid, rank) reward_rows = self.db.get_monster_rewards(mid, rank)
hunt_item = HuntItemExpectedValue(item_id, monster["name"], rank, hunt_item = HuntItemExpectedValue(self.item_id, monster["name"],
reward_rows) rank, reward_rows)
key = (mid, rank)
self._hunt_items[key] = hunt_item
out.write("%s %s\n" % (monster["name"], rank)) for s in self.skill_sets.values():
s.add_hunt_item(hunt_item)
def get_hunt_item(self, monster_id, monster_rank):
key = (monster_id, monster_rank)
return self._hunt_items.get(key)
def _find_quest_items(self):
"""
Get a list of the quests for acquiring a given item and the probability
of getting the item, depending on cap or kill and luck skills.
"""
quests = self.db.get_item_quest_objects(self.item_id)
if not quests:
return
for q in quests:
quest_item = QuestItemExpectedValue(self.item_id, q)
self._quest_items[q.id] = quest_item
def print_monsters(self, out):
for hunt_item in self._hunt_items.itervalues():
out.write("%s %s\n"
% (hunt_item.monster_name, hunt_item.monster_rank))
hunt_item.print(out, indent=2) hunt_item.print(out, indent=2)
kill_ev = [0, 0] kill_ev = [0, 0]
@@ -457,54 +504,44 @@ def print_monsters_and_rewards(db, item_row, out):
out.write(" %20s %5.2f / 100\n" % ("Shiny", shiny_ev)) out.write(" %20s %5.2f / 100\n" % ("Shiny", shiny_ev))
out.write("\n") out.write("\n")
for s in skill_sets.values(): def print_recommended_hunts(self, out):
s.add_hunt_item(hunt_item) out.write("*** Poogie Recommends ***\n")
no_skill_best = self.skill_sets["No skills"].best
for name, skill_set in self.skill_sets.iteritems():
print("*** Poogie Recommends ***", file=out)
no_skill_best = skill_sets["No skills"].best
for name, skill_set in skill_sets.iteritems():
if skill_set.best is None: if skill_set.best is None:
# Don't print out a rank with no options
continue continue
if name != "No skills" and skill_set.best.is_same_strat(no_skill_best): if (name != "No skills"
and skill_set.best.is_same_strat(no_skill_best)):
# Don't print out a skill set/rank that doesn't differ from
# no skills any rank
continue continue
out.write("[%-11s] " % name) out.write("[%-11s] " % name)
skill_set.best.print(out) skill_set.best.print(out)
out.write("\n")
print(file=out) def print_quests(self, out):
def print_quests_and_rewards(db, item_row, out):
""" """
Get a list of the quests for acquiring a given item and the probability Get a list of the quests for acquiring a given item and the probability
of getting the item, depending on cap or kill and luck skills. of getting the item, depending on cap or kill and luck skills.
""" """
item_id = item_row["_id"] for quest_item in self._quest_items.itervalues():
quests = db.get_item_quest_objects(item_id) out.write(unicode(quest_item.quest) + "\n")
print_monsters_and_rewards(db, item_row, out)
if not quests:
return
for q in quests:
out.write(unicode(q) + "\n")
out.write(" %20s" % "= Quest\n") out.write(" %20s" % "= Quest\n")
quest = QuestItemExpectedValue(item_id, q._rewards) quest_item.check_totals(out)
quest.check_totals(out) quest_item.print(out, indent=2)
quest.print(out, indent=2)
monsters = db.get_quest_monsters(q.id) quest_monsters = self.db.get_quest_monsters(quest_item.quest.id)
quest_ev = quest.expected_value() quest_ev = quest_item.expected_value()
cap_ev = [quest_ev, quest_ev] cap_ev = [quest_ev, quest_ev]
kill_ev = [quest_ev, quest_ev] kill_ev = [quest_ev, quest_ev]
shiny_ev = 0 shiny_ev = 0
for m in monsters: for m in quest_monsters:
mid = m["monster_id"] mid = m["monster_id"]
monster = db.get_monster(mid) hunt_item = self.get_hunt_item(mid, quest_item.quest.rank)
reward_rows = db.get_monster_rewards(mid, q.rank)
hunt_item = HuntItemExpectedValue(item_id, monster["name"],
q.rank, reward_rows)
kill_ev[0] += hunt_item.expected_value(STRAT_KILL) kill_ev[0] += hunt_item.expected_value(STRAT_KILL)
kill_ev[1] += hunt_item.expected_value(STRAT_KILL, kill_ev[1] += hunt_item.expected_value(STRAT_KILL,
@@ -517,7 +554,9 @@ def print_quests_and_rewards(db, item_row, out):
if kill_ev[0] == 0 and cap_ev[0] == 0 and shiny_ev == 0: if kill_ev[0] == 0 and cap_ev[0] == 0 and shiny_ev == 0:
continue continue
out.write(" %20s\n" % ("= " + monster["name"] + " " + q.rank)) out.write(" %20s\n"
% ("= " + hunt_item.monster_name
+ " " + hunt_item.monster_rank))
hunt_item.print(out, indent=2) hunt_item.print(out, indent=2)
@@ -529,4 +568,3 @@ def print_quests_and_rewards(db, item_row, out):
if shiny_ev: if shiny_ev:
out.write(" %20s %5.2f / 100\n" % ("Shiny", shiny_ev)) out.write(" %20s %5.2f / 100\n" % ("Shiny", shiny_ev))
out.write("\n") out.write("\n")

View File

@@ -81,8 +81,10 @@ class App(object):
else: else:
item_row = rewards.find_item(self.db, item_name, resp.body_file) item_row = rewards.find_item(self.db, item_name, resp.body_file)
if item_row is not None: if item_row is not None:
rewards.print_quests_and_rewards(self.db, item_row, ir = rewards.ItemRewards(self.db, item_row)
resp.body_file) ir.print_recommended_hunts(resp.body_file)
ir.print_monsters(resp.body_file)
ir.print_quests(resp.body_file)
return resp return resp
def get_all_names(self, req, resp): def get_all_names(self, req, resp):