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

Dashboard: campaigns fail to load on unconverted settlements #309

Closed toconnell closed 7 years ago

toconnell commented 7 years ago

Gnarly:

==> /var/log/kdm-manager/error.log <==
[2017-10-13 09:22:18] ERROR:    400 - The handle 'Paint' is not in ['accept_darkness', 'albedo', 'ammonia', 'aquarobics', 'arena', 'barbaric', 'bed', 'black_mask', 'bloodletting', 'bloodline', 'cannibalize', 'choreia', 'citrinitas', 'clan_of_death', 'collective_toil', 'cooking', 'crimson_candy', 'dark_water_research', 'dragon_speech', 'drums', 'empire', 'face_painting', 'family', 'filleting_table', 'final_fighting_art', 'forbidden_dance', 'graves', 'guidepost', 'hands_of_the_sun', 'heart_flute', 'hovel', 'inner_lantern', 'language', 'lantern_oven', 'legless_ball', 'mastery_axe', 'mastery_bow', 'mastery_club', 'mastery_dagger', 'mastery_fist_and_tooth', 'mastery_grand_weapon', 'mastery_katana', 'mastery_katar', 'mastery_scythe', 'mastery_shield', 'mastery_spear', 'mastery_sword', 'mastery_twilight_sword', 'mastery_whip', 'memento_mori', 'nightmare_training', 'nigredo', 'paint', 'partnership', 'petal_spiral', 'pictograph', 'pottery', 'protect_the_young', 'radiating_orb', 'records', 'romantic', 'round_stone_training', 'rubedo', 'sacrifice', 'saga', 'sauna_shrine', 'scarification', 'scrap_smelting', 'sculpture', 'settlement_watch', 'shadow_dancing', 'shrine', 'silk_refining', 'song_of_the_brave', 'stoic_statue', 'storytelling', 'subterranean_agriculture', 'sun_language', 'survival_of_the_fittest', 'symposium', 'the_knowledge_worm', 'ultimate_weapon', 'umbilical_bank', 'war_room', 'white_mask'] and could not be retrieved!
[2017-10-13 09:22:18] ERROR:    Could not serialize {u'quarries': [u'screaming_antelope', u'white_lion'], u'campaign': u'People of the Lantern', u'principles': [u'Accept Darkness', u'Graves', u'Protect the Young'], u'innovations': [u'Paint', u'Ammonia', u'Language'], u'created_on': datetime.datetime(2015, 12, 3, 19, 43, 27, 889000), u'timeline_version': 1.1, u'defeated_monsters': [u'White Lion lv.1', u'White Lion (prologue)', u'Screaming Antelope lv.1'], u'monsters_version': 1.0, u'storage': [u'Beast Steak', u'Beast Steak', u'Bone Axe', u'Bone Blade', u'Bone Blade', u'Bone Blade', u'Bone Darts', u'Cat Gut Bow', u'Cloth', u'Cloth', u'Cloth', u'Cloth', u'Dried Acanthus', u'Dried Acanthus', u'Founding Stone', u'Founding Stone', u'Large Flat Tooth', u'Large Flat Tooth', u'Monster Bone', u'Muscly Gums', u'Portcullis Key', u'Rawhide Boots', u'Rawhide Gloves', u'Rawhide Headband', u'Rawhide Vest', u'Skull Helm', u'Skull Helm', u'White Fur', u'White Lion Coat', u'White Lion Helm'], u'created_by': ObjectId('565f3d67421aa95c4af1e230'), u'population': u'4', u'nemesis_encounters': {u'butcher': []}, u'lost_settlements': u'0', u'timeline': [{u'settlement_event': [{u'handle': u'core_first_day', u'type': u'settlement_event', u'name': u'First Day'}], u'showdown_event': [{u'name': u'White Lion (First Story)'}], u'year': 0}, {u'custom': [], u'story_event': [{u'type': u'story_event', u'handle': u'core_returning_survivors', u'name': u'Returning Survivors', u'page': 151}], u'year': 1}, {u'custom': [], u'story_event': [{u'type': u'story_event', u'handle': u'core_endless_screams', u'name': u'Endless Screams', u'page': 115}], u'year': 2}, {u'custom': [], u'year': 3}, {u'custom': [], u'nemesis_encounter': [{u'name': u'Nemesis Encounter: Butcher'}], u'story_event': [{u'handle': u'core_death', u'type': u'story_event', u'name': u'Principle: Death', u'page': 143}, {u'handle': u'core_new_life', u'type': u'story_event', u'name': u'Principle: New Life', u'page': 145}, {u'handle': u'core_society', u'type': u'story_event', u'name': u'Principle: Society', u'page': 147}], u'year': 4}, {u'custom': [], u'story_event': [{u'type': u'story_event', u'handle': u'core_hands_of_heat', u'name': u'Hands of Heat', u'page': 117}], u'year': 5}, {u'custom': [{u'handle': u'core_murder', u'type': u'settlement_event', u'name': u'Murder'}], u'story_event': [{u'type': u'story_event', u'handle': u'core_armored_strangers', u'name': u'Armored Strangers', u'page': 103}], u'year': 6}, {u'custom': [], u'story_event': [{u'type': u'story_event', u'handle': u'core_phoenix_feather', u'name': u'Phoenix Feather', u'page': 139}], u'year': 7}, {u'custom': [], u'year': 8}, {u'custom': [], u'nemesis_encounter': [{u'name': u"Nemesis Encounter: King's Man"}], u'year': 9}, {u'custom': [], u'year': 10}, {u'custom': [], u'story_event': [{u'type': u'story_event', u'handle': u'core_regal_visit', u'name': u'Regal Visit', u'page': 149}], u'year': 11}, {u'custom': [], u'story_event': [{u'type': u'story_event', u'handle': u'core_conviction', u'name': u'Principle: Conviction', u'page': 141}], u'year': 12}, {u'custom': [], u'year': 13}, {u'custom': [], u'year': 14}, {u'custom': [], u'year': 15}, {u'custom': [], u'nemesis_encounter': [{u'name': u'Nemesis Encounter'}], u'year': 16}, {u'custom': [], u'year': 17}, {u'custom': [], u'year': 18}, {u'custom': [], u'nemesis_encounter': [{u'name': u'Nemesis Encounter'}], u'year': 19}, {u'custom': [], u'story_event': [{u'type': u'story_event', u'handle': u'core_watched', u'name': u'Watched', u'page': 175}], u'year': 20}, {u'custom': [], u'year': 21}, {u'custom': [], u'year': 22}, {u'custom': [], u'nemesis_encounter': [{u'name': u'Nemesis Encounter: Level 3'}], u'year': 23}, {u'custom': [], u'year': 24}, {u'custom': [], u'year': 25}, {u'custom': [], u'nemesis_encounter': [{u'name': u'Nemesis Encounter: Watcher'}], u'year': 26}, {u'custom': [], u'year': 27}, {u'custom': [], u'year': 28}, {u'custom': [], u'year': 29}, {u'custom': [], u'year': 30}, {u'custom': [], u'year': 31}, {u'custom': [], u'year': 32}, {u'custom': [], u'year': 33}, {u'custom': [], u'year': 34}, {u'custom': [], u'year': 35}, {u'custom': [], u'year': 36}, {u'custom': [], u'year': 37}, {u'custom': [], u'year': 38}, {u'custom': [], u'year': 39}, {u'custom': [], u'year': 40}], u'modify': u'settlement', u'locations': [u'Skinnery', u'Lantern Hoard', u'Bone Smith', u'Organ Grinder'], u'expansions_version': 1.0, u'nemesis_monsters': [u'butcher'], u'name': u'Galactica', u'abandoned': datetime.datetime(2016, 1, 23, 19, 52, 35, 762000), u'milestone_story_events': [u'First time death count is updated', u'First child is born', u'Population reaches 15'], u'lantern_year': 4, u'expansions': [], u'death_count': u'7', u'admins': [u'toconnell@tyrannybelle.com'], u'_id': ObjectId('5660e1af421aa94c35cfb198'), u'survival_limit': u'2'}
[2017-10-13 09:22:18] ERROR:
Traceback (most recent call last):
  File "/home/toconnell/kdm-manager/v2/api/models/users.py", line 556, in get_settlements
    sheet = json.loads(S.serialize('dashboard'))
  File "/home/toconnell/kdm-manager/v2/api/models/settlements.py", line 326, in serialize
    output['sheet']['population_by_sex'] = self.get_population('sex')
  File "/home/toconnell/kdm-manager/v2/api/models/settlements.py", line 1590, in get_population
    for s in self.get_survivors():
  File "/home/toconnell/kdm-manager/v2/api/models/settlements.py", line 1638, in get_survivors
    s_dict = json.loads(S.serialize())
  File "/home/toconnell/kdm-manager/v2/api/models/survivors.py", line 421, in serialize
    output.update({"survival_actions": self.get_survival_actions("JSON")})
  File "/home/toconnell/kdm-manager/v2/api/models/survivors.py", line 1780, in get_survival_actions
    available_actions = self.Settlement.get_survival_actions()
  File "/home/toconnell/kdm-manager/v2/api/models/settlements.py", line 1728, in get_survival_actions
    for k,v in self.get_innovations(dict).iteritems():
  File "/home/toconnell/kdm-manager/v2/api/models/settlements.py", line 1475, in get_innovations
    i_dict = I.get_asset(i_handle)
  File "/home/toconnell/kdm-manager/v2/api/Models.py", line 186, in get_asset
    raise utils.InvalidUsage(msg)
InvalidUsage
toconnell commented 7 years ago

I'm gonna hack around this with a quick backoff to name:

1462     def get_innovations(self, return_type=None, include_principles=False):
1463         """ Returns self.settlement["innovations"] by default; specify 'dict' as
1464         the 'return_type' to get a dictionary back instead. """
1465
1466         s_innovations = copy(self.settlement["innovations"])
1467         if include_principles:
1468             s_innovations.extend(self.settlement["principles"])
1469
1470         I = innovations.Assets()
1471
1472         if return_type == dict:
1473             output = {}
1474             for i_handle in s_innovations:
1475                 i_dict = I.get_asset(i_handle, backoff_to_name=True)
1476                 if i_dict is not None:
1477                     output[i_handle] = i_dict
1478                 else:
1479                     self.logger.error("Ignoring unknown Innovation handle '%s'!" % i_handle)
1480             return output
1481
1482         return s_innovations
toconnell commented 7 years ago

...and now we're throwing a traceback when we try to load parents that don't exist...

toconnell commented 7 years ago

Hack around it!

diff --git a/v2/api/models/survivors.py b/v2/api/models/survivors.py
index c0c572f..d4be1ff 100644
--- a/v2/api/models/survivors.py
+++ b/v2/api/models/survivors.py
@@ -1711,12 +1711,13 @@ class Survivor(Models.UserAsset):
             output = {'mother': None, 'father': None}
             for p_oid in parents:
                 p = utils.mdb.survivors.find_one({'_id': p_oid})
-                if p["sex"] == 'M':
-                    output['father'] = p
-                elif p['sex'] == 'F':
-                    output['mother'] = p
-                else:
-                    raise
+                if p is not None:
+                    if p["sex"] == 'M':
+                        output['father'] = p
+                    elif p['sex'] == 'F':
+                        output['mother'] = p
+                    else:
+                        raise
             return output

         return parents
toconnell commented 7 years ago

OK, this seems like it's resolved, so I'm closing it and it will go out in the next release.