From b99060a451cdb1c6b6425db18d5c04a4fd1e6f2f Mon Sep 17 00:00:00 2001
From: Jonathan Harris <jonathan@marginal.org.uk>
Date: Wed, 26 Oct 2016 01:43:44 +0100
Subject: [PATCH] Export detailed module info to EDShipyard

Including priorities and mods.
---
 EDMarketConnector.py |  4 +--
 edshipyard.py        | 82 ++++++++++++++++++++++++++++++++++++++++++++
 2 files changed, 84 insertions(+), 2 deletions(-)
 create mode 100644 edshipyard.py

diff --git a/EDMarketConnector.py b/EDMarketConnector.py
index ec552501..25845cb1 100755
--- a/EDMarketConnector.py
+++ b/EDMarketConnector.py
@@ -41,9 +41,9 @@ from commodity import COMMODITY_BPC, COMMODITY_CSV
 import td
 from eddn import eddn
 import edsm
-import loadout
 import coriolis
 import eddb
+import edshipyard
 import stats
 import prefs
 import plug
@@ -386,7 +386,7 @@ class AppWindow:
                 # stuff we can do when not docked
                 plug.notify_newdata(data)
                 if config.getint('output') & config.OUT_SHIP_EDS:
-                    loadout.export(data)
+                    edshipyard.export(data)
                 if config.getint('output') & config.OUT_SHIP_CORIOLIS:
                     coriolis.export(data)
 
diff --git a/edshipyard.py b/edshipyard.py
new file mode 100644
index 00000000..0e7ac68c
--- /dev/null
+++ b/edshipyard.py
@@ -0,0 +1,82 @@
+# Export ship loadout in E:D Shipyard format
+
+from collections import defaultdict
+import json
+import os
+from os.path import join
+import re
+import time
+
+import companion
+
+from config import config
+
+
+def export(data, filename=None):
+
+    # Add a leaf to a dictionary, creating empty dictionaries along the branch if necessary
+    def addleaf(data, to, props):
+
+        # special handling for completely empty trees
+        p = props[0]
+        if not data[p]:
+            to[p] = data[p]
+
+        # Does the leaf exist ?
+        tail = data
+        for p in props:
+            if not hasattr(data, 'get') or p not in tail:
+                return
+            else:
+                tail = tail[p]
+
+        for p in props[:-1]:
+            if not hasattr(data, 'get') or p not in data:
+                return
+            elif p not in to:
+                to[p] = {}
+            elif not hasattr(to, 'get'):
+                return	# intermediate is not a dictionary - inconsistency!
+            data = data[p]
+            to = to[p]
+        p = props[-1]
+        to[p] = data[p]
+
+    querytime = config.getint('querytime') or int(time.time())
+
+    # subset of "ship" that's not noisy
+    ship = {}
+    for props in [
+            ('cargo', 'capacity'),
+            ('fuel', 'main', 'capacity'),
+            ('fuel', 'reserve', 'capacity'),
+            ('fuel', 'superchargedFSD'),
+            ('id',),
+            ('name',),
+    ]: addleaf(data['ship'], ship, props)
+
+    ship['modules'] = {}
+    for slot in data['ship'].get('modules', {}):
+        for prop in ('id', 'modifiers', 'name', 'on', 'priority'):
+            addleaf(data['ship']['modules'], ship['modules'], (slot, 'module', prop))
+
+    string = json.dumps(ship, ensure_ascii=False, indent=2, sort_keys=True, separators=(',', ': ')).encode('utf-8')
+
+    if filename:
+        with open(filename, 'wt') as h:
+            h.write(string)
+        return
+
+    # Look for last ship of this type
+    ship = companion.ship_map.get(data['ship']['name'].lower(), data['ship']['name'])	# Use in-game name
+    regexp = re.compile(re.escape(ship) + '\.\d\d\d\d\-\d\d\-\d\dT\d\d\.\d\d\.\d\d\.txt')
+    oldfiles = sorted([x for x in os.listdir(config.get('outdir')) if regexp.match(x)])
+    if oldfiles:
+        with open(join(config.get('outdir'), oldfiles[-1]), 'rU') as h:
+            if h.read() == string:
+                return	# same as last time - don't write
+
+    # Write
+    filename = join(config.get('outdir'), '%s.%s.txt' % (ship, time.strftime('%Y-%m-%dT%H.%M.%S', time.localtime(querytime))))
+    with open(filename, 'wt') as h:
+        h.write(string)