From ad0e57a28501446143ad84cdea722b5db4a41767 Mon Sep 17 00:00:00 2001
From: Jonathan Harris <jonathan@marginal.org.uk>
Date: Thu, 25 Feb 2016 05:39:34 +0000
Subject: [PATCH] Add "entitlement" field to collation

---
 collate.py    |  21 +++++++++------------
 coriolis.py   |   3 +++
 loadout.py    |   5 +++--
 modules.p     | Bin 20543 -> 20629 bytes
 outfitting.py |  33 +++++++++++++++++++++++----------
 5 files changed, 38 insertions(+), 24 deletions(-)

diff --git a/collate.py b/collate.py
index f3910af5..e3df2c1e 100755
--- a/collate.py
+++ b/collate.py
@@ -68,29 +68,28 @@ def addmodules(data):
 
     outfile = 'outfitting.csv'
     modules = {}
-    schemakeys = ['category', 'name', 'mount', 'guidance', 'ship', 'class', 'rating']
+    fields = ['id', 'category', 'name', 'mount', 'guidance', 'ship', 'class', 'rating', 'entitlement']
 
     # slurp existing
     if isfile(outfile):
         with open(outfile) as csvfile:
-            reader = csv.DictReader(csvfile)
+            reader = csv.DictReader(csvfile, restval='')
             for row in reader:
-                key = int(row.pop('id'))	# index by int for easier lookup and sorting
-                modules[key] = row
+                modules[int(row['id'])] = row	# index by int for easier lookup and sorting
     size_pre = len(modules)
 
     for key,module in data['lastStarport'].get('modules').iteritems():
         # sanity check
         if int(key) != module.get('id'): raise AssertionError('id: %s!=%s' % (key, module['id']))
-        new = outfitting.lookup(module, ship_map)
+        new = outfitting.lookup(module, ship_map, True)
         if new:
             old = modules.get(int(key))
             if old:
                 # check consistency with existing data
-                for thing in schemakeys:
-                    if new.get(thing,'') != old.get(thing): raise AssertionError('%s: %s "%s"!="%s"' % (key, thing, new.get(thing), old.get(thing)))
+                for thing in fields:
+                    if str(new.get(thing,'')) != old.get(thing): raise AssertionError('%s: %s "%s"!="%s"' % (key, thing, new.get(thing), old.get(thing)))
             else:
-                modules[int(key)] = { k: new[k] for k in schemakeys if k in new }
+                modules[int(key)] = new
 
     if len(modules) > size_pre:
 
@@ -100,12 +99,10 @@ def addmodules(data):
             os.rename(outfile, outfile+'.bak')
 
         with open(outfile, 'wb') as csvfile:
-            writer = csv.DictWriter(csvfile, ['id', 'category', 'name', 'mount', 'guidance', 'ship', 'class', 'rating'])
+            writer = csv.DictWriter(csvfile, fields, extrasaction='ignore')
             writer.writeheader()
             for key in sorted(modules):
-                row = modules[key]
-                row['id'] = key
-                writer.writerow(row)
+                writer.writerow(modules[key])
 
         print 'Added %d new modules' % (len(modules) - size_pre)
 
diff --git a/coriolis.py b/coriolis.py
index 9dc6af02..a1a70200 100755
--- a/coriolis.py
+++ b/coriolis.py
@@ -326,5 +326,8 @@ if __name__ == "__main__":
                     }
                 else:
                     modules[key] = { 'mass': m.get('mass', 0) }	# Some modules don't have mass
+
+    modules[('Planetary Approach Suite', None, '1', 'I')] = { 'mass': 0 }	# not in data at time of writing
+
     cPickle.dump(modules, open('modules.p', 'wb'), protocol = cPickle.HIGHEST_PROTOCOL)
 
diff --git a/loadout.py b/loadout.py
index 194f030a..7c07791b 100644
--- a/loadout.py
+++ b/loadout.py
@@ -86,10 +86,11 @@ def export(data, filename=None):
             else:
                 if slot.lower().startswith('slot'):
                     loadout[slot[-1]].append(cr + name)
-                elif __debug__: print 'Loadout: Unknown slot %s' % slot
+                elif __debug__ and not slot.lower().startswith('planetaryapproachsuite'):
+                    print 'EDShipyard: Unknown slot %s' % slot
 
         except AssertionError as e:
-            if __debug__: print 'Loadout: %s' % e
+            if __debug__: print 'EDShipyard: %s' % e
             continue	# Silently skip unrecognized modules
         except:
             if __debug__: raise
diff --git a/modules.p b/modules.p
index c6358e9c5b6a96c86f87847f5c7ea0dfb8b4af2a..200e1af97ab4dca64cca3a3c66d04f57b9466af5 100644
GIT binary patch
literal 20629
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

literal 20543
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
D`s}rO

diff --git a/outfitting.py b/outfitting.py
index d1b3f90d..77ce8881 100644
--- a/outfitting.py
+++ b/outfitting.py
@@ -187,6 +187,7 @@ standard_map = {
     'fueltank'         : 'Fuel Tank',
     'hyperdrive'       : 'Frame Shift Drive',
     'lifesupport'      : 'Life Support',
+    # 'planetapproachsuite' : handled separately
     'powerdistributor' : 'Power Distributor',
     'powerplant'       : 'Power Plant',
     'sensors'          : 'Sensors',
@@ -200,7 +201,6 @@ internal_map = {
     'fuelscoop'         : 'Fuel Scoop',
     'fueltransfer'      : 'Fuel Transfer Limpet Controller',
     'hullreinforcement' : 'Hull Reinforcement Package',
-    # 'planetapproachsuite' : 'Planetary Approach Suite',	# Don't report
     'prospector'        : 'Prospector Limpet Controller',
     'refinery'          : 'Refinery',
     'repairer'          : 'Auto Field-Maintenance Unit',
@@ -223,7 +223,7 @@ moduledata = cPickle.load(open(join(config.respath, 'modules.p'),  'rb'))
 #
 # Returns None if the module is user-specific (i.e. decal, paintjob) or PP-specific in station outfitting.
 # (Given the ad-hocery in this implementation a big lookup table might have been simpler and clearer).
-def lookup(module, ship_map):
+def lookup(module, ship_map, entitled=False):
 
     # if not module.get('category'): raise AssertionError('%s: Missing category' % module['id'])	# only present post 1.3, and not present in ship loadout
     if not module.get('name'): raise AssertionError('%s: Missing name' % module['id'])
@@ -249,15 +249,11 @@ def lookup(module, ship_map):
     # elif 'category' in module and module['category'].lower() == 'powerplay':
     #     return None
 
-    # Shouldn't be listing player-specific paid stuff, other than Horizons
-    elif module.get('sku') and module['sku'].lower() != 'elite_horizons_v_planetary_landings':
+    # Shouldn't be listing player-specific paid stuff in outfitting, other than Horizons
+    elif not entitled and module.get('sku') and module['sku'] != 'ELITE_HORIZONS_V_PLANETARY_LANDINGS':
         # raise AssertionError('%s: Unexpected sku "%s"' % (module['id'], module['sku']))
         return None
 
-    # Skip Horizons Planetary Approach Suite
-    elif name[1] in ['planetapproachsuite']:
-        return None
-
     # Hardpoints - e.g. Hpt_Slugshot_Fixed_Medium
     elif name[0]=='hpt' and name[1] in weapon_map:
         if name[2] not in weaponmount_map: raise AssertionError('%s: Unknown weapon mount "%s"' % (module['id'], name[2]))
@@ -298,8 +294,16 @@ def lookup(module, ship_map):
     elif name[0]!='int':
         raise AssertionError('%s: Unknown prefix "%s"' % (module['id'], name[0]))
 
+    # Horizons Planetary Approach Suite
+    elif name[1] == 'planetapproachsuite':
+        new['category'] = 'standard'
+        new['name'] = 'Planetary Approach Suite'
+        new['class'] = '1'
+        new['rating'] = 'I'
+        new['entitlement'] = 'horizons'	# only listed in outfitting if the user is *playing* Horizons
+
     # Miscellaneous Class 1 - e.g. Int_StellarBodyDiscoveryScanner_Advanced, Int_DockingComputer_Standard
-    elif (name[1],name[2]) in misc_internal_map:
+    elif len(name) > 2 and (name[1],name[2]) in misc_internal_map:
         # Reported category is not necessarily helpful. e.g. "Int_DockingComputer_Standard" has category "utility"
         new['category'] = 'internal'
         new['name'], new['rating'] = misc_internal_map[(name[1],name[2])]
@@ -327,6 +331,14 @@ def lookup(module, ship_map):
     if 'on' in module and 'priority' in module:
         new['enabled'], new['priority'] = module['on'], module['priority']	# priority is zero-based
 
+    # Entitlements
+    if not entitled or not module.get('sku'):
+        pass
+    elif module['sku'].startswith('ELITE_SPECIFIC_V_POWER'):
+        new['entitlement'] = 'powerplay'
+    elif module['sku'] != 'ELITE_HORIZONS_V_PLANETARY_LANDINGS':
+        assert False, '%s: Unknown sku "%s"' % (module['id'], module['sku'])
+
     # Extra module data
     key = (new['name'], 'ship' in new and companion.ship_map.get(name[0]) or None, new['class'], new['rating'])
     if __debug__:
@@ -339,7 +351,8 @@ def lookup(module, ship_map):
     new.update(moduledata.get(key, {}))
 
     # check we've filled out mandatory fields
-    for thing in ['category', 'name', 'class', 'rating']:	# Don't consider mass etc as mandatory
+    new['id'] = module['id']
+    for thing in ['id', 'category', 'name', 'class', 'rating']:	# Don't consider mass etc as mandatory
         if not new.get(thing): raise AssertionError('%s: failed to set %s' % (module['id'], thing))
     if new['category'] == 'hardpoint' and not new.get('mount'):
         raise AssertionError('%s: failed to set %s' % (module['id'], 'mount'))