toconnell / kdm-manager

An interactive campaign manager for the game "Monster", by Kingdom Death. Development blog and release notes at https://blog.kdm-manager.com This project has no affiliation with Kingdom Death and is a totally independent, fan-maintained project.
http://kdm-manager.com
Other
26 stars 11 forks source link

Settlement Sheet: the rm_monster endpoint throws errors on the King's Man #480

Closed toconnell closed 6 years ago

toconnell commented 6 years ago

From auto-alerts:

Method: POST URL: http://api.thewatcher.io/settlement/rm_monster/5a9eed348740d97b34c4101c JSON: {u'handle': u'kings_man', u'serialize_on_response': True}

The full traceback is as follows:

Traceback (most recent call last):
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1639, in full_dispatch_request
 rv = self.dispatch_request()
File "/usr/local/lib/python2.7/dist-packages/flask/app.py", line 1625, in dispatch_request
 return self.view_functions[rule.endpoint](**req.view_args)
File "/home/toconnell/kdm-manager/v2/api/utils.py", line 505, in wrapped_function
 resp = make_response(f(*args, **kwargs))
File "/usr/lib/python2.7/dist-packages/celery/local.py", line 188, in __call__
 return self._get_current_object()(*a, **kw)
File "/usr/lib/python2.7/dist-packages/celery/app/task.py", line 420, in __call__
 return self.run(*args, **kwargs)
File "/home/toconnell/kdm-manager/v2/api/api.py", line 274, in collection_action
 return asset_object.request_response(action)
File "/home/toconnell/kdm-manager/v2/api/models/settlements.py", line 3636, in request_response
 self.rm_monster()
File "/home/toconnell/kdm-manager/v2/api/models/settlements.py", line 709, in rm_monster
 del self.settlement["nemesis_encounters"][monster_handle]
KeyError: u'kings_man'
toconnell commented 6 years ago

Turns out the _rmmonster() method was a really lazy/messy/not-very-well-thought-out copy of the _addmonster() method (which was itself a hasty port of a legacy webapp method: oi vey).

Anyway, I just refactored it for economy/readability and it's way mo' better now:

diff --git a/v2/api/models/settlements.py b/v2/api/models/settlements.py
index 4f1440e..52b33a3 100644
--- a/v2/api/models/settlements.py
+++ b/v2/api/models/settlements.py
@@ -729,20 +729,28 @@ class Settlement(Models.UserAsset):
         # sanity check the handle; load an asset dict for it
         m_dict = self.Monsters.get_asset(monster_handle)

-        # get the type from the asset dict
-        if m_dict["type"] == 'quarry':
-            target_list = self.settlement["quarries"]
-        elif m_dict["type"] == 'nemesis':
-            target_list = self.settlement["nemesis_monsters"]
+        # figure out what type it is or die trying
+        m_type = m_dict['type']
+        if m_type == 'quarry':
+            target_list = self.settlement['quarries']
+        elif m_type == 'nemesis':
+            target_list = self.settlement['nemesis_monsters']
+        else:
+            raise utils.InvalidUsage("%s Unable to process 'rm_monster' operation on asset: %s" % (self, m_dict))

-        # finally, add, log and save
+        # general handling for both types
         if monster_handle in target_list:
             target_list.remove(monster_handle)
-            if m_dict["type"] == 'nemesis':
-                del self.settlement["nemesis_encounters"][monster_handle]
+#            self.logger.debug("%s Removed '%s' handle from settlement %s monsters list." % (self, monster_handle, m_type))
         else:
-            self.logger.error("%s Ignoring attempt to remove non-existing item '%s' from %s" % (request.User, monster_handle, target_list))
-        self.log_event("%s removed '%s' from the settlement %s list." % (request.User.login, m_dict["name"], m_dict["type"]))
+            self.logger.error("%s Ignoring attempt to remove non-existing item '%s' from %s" % (self, monster_handle, m_type))
+
+        # additional handling for nemeses
+        if m_type == 'nemesis' and monster_handle in self.settlement['nemesis_encounters'].keys():
+            del self.settlement["nemesis_encounters"][monster_handle]
+#            self.logger.debug("%s Removed '%s' handle from settlement 'nemesis_encounters' dict..." % (self, monster_handle))
+
+        self.log_event(key="%s monsters" % m_type, value=m_dict['name'], event_type="rm_monster")
         self.save()

This will a.) resolve the issue and b.) go out in the Timeline release.