1
0
mirror of https://github.com/EDCD/EDMarketConnector.git synced 2025-06-10 20:32:12 +03:00

Add option to output ship loadout in E:D Shipyard format.

This commit is contained in:
Jonathan Harris 2015-06-18 23:01:02 +01:00
parent b573dbe4e2
commit 0002d321ca
6 changed files with 512 additions and 29 deletions

View File

@ -17,6 +17,7 @@ import companion
import bpc import bpc
import td import td
import eddn import eddn
import loadout
import prefs import prefs
from config import appname, applongname, config from config import appname, applongname, config
@ -174,13 +175,19 @@ class AppWindow:
# Validation # Validation
if not data.get('commander') or not data['commander'].get('name','').strip(): if not data.get('commander') or not data['commander'].get('name','').strip():
self.status['text'] = "Who are you?!" # Shouldn't happen self.status['text'] = "Who are you?!" # Shouldn't happen
elif not data['commander'].get('docked'):
self.status['text'] = "You're not docked at a station!"
elif not data.get('lastSystem') or not data['lastSystem'].get('name','').strip() or not data.get('lastStarport') or not data['lastStarport'].get('name','').strip(): elif not data.get('lastSystem') or not data['lastSystem'].get('name','').strip() or not data.get('lastStarport') or not data['lastStarport'].get('name','').strip():
self.status['text'] = "Where are you?!" # Shouldn't happen self.status['text'] = "Where are you?!" # Shouldn't happen
elif not data.get('ship') or not data['ship'].get('modules') or not data['ship'].get('name','').strip():
self.status['text'] = "What are you flying?!" # Shouldn't happen
elif not data['commander'].get('docked'):
if config.getint('output') & config.OUT_SHIP:
loadout.export(data) # do loadout even if not docked
self.status['text'] = "You're not docked at a station!"
elif not data['lastStarport'].get('commodities'): elif not data['lastStarport'].get('commodities'):
self.status['text'] = "Station doesn't have a market!" self.status['text'] = "Station doesn't have a market!"
else: else:
if config.getint('output') & config.OUT_SHIP:
loadout.export(data)
if config.getint('output') & config.OUT_CSV: if config.getint('output') & config.OUT_CSV:
bpc.export(data, True) bpc.export(data, True)
if config.getint('output') & config.OUT_TD: if config.getint('output') & config.OUT_TD:

View File

@ -23,22 +23,51 @@ holdoff = 120 # be nice
# Map values reported by the Companion interface to names displayed in-game and recognized by trade tools # Map values reported by the Companion interface to names displayed in-game and recognized by trade tools
categorymap = { 'Narcotics': 'Legal Drugs', category_map = {
'Slaves': 'Slavery', 'Narcotics' : 'Legal Drugs',
'NonMarketable': False, } 'Slaves' : 'Slavery',
'NonMarketable' : False,
}
commoditymap= { 'Agricultural Medicines': 'Agri-Medicines', commodity_map= {
'Agricultural Medicines' : 'Agri-Medicines',
'Ai Relics' : 'AI Relics', 'Ai Relics' : 'AI Relics',
'Atmospheric Extractors': 'Atmospheric Processors', 'Atmospheric Extractors' : 'Atmospheric Processors',
'Auto Fabricators': 'Auto-Fabricators', 'Auto Fabricators' : 'Auto-Fabricators',
'Basic Narcotics': 'Narcotics', 'Basic Narcotics' : 'Narcotics',
'Bio Reducing Lichen': 'Bioreducing Lichen', 'Bio Reducing Lichen' : 'Bioreducing Lichen',
'Hazardous Environment Suits': 'H.E. Suits', 'Hazardous Environment Suits' : 'H.E. Suits',
'Heliostatic Furnaces': 'Microbial Furnaces', 'Heliostatic Furnaces' : 'Microbial Furnaces',
'Marine Supplies': 'Marine Equipment', 'Marine Supplies' : 'Marine Equipment',
'Non Lethal Weapons': 'Non-Lethal Weapons', 'Non Lethal Weapons' : 'Non-Lethal Weapons',
'S A P8 Core Container': 'SAP 8 Core Container', 'S A P8 Core Container' : 'SAP 8 Core Container',
'Terrain Enrichment Systems': 'Land Enrichment Systems', } 'Terrain Enrichment Systems' : 'Land Enrichment Systems',
}
ship_map = {
'Adder' : 'Adder',
'Anaconda' : 'Anaconda',
'Asp' : 'Asp',
'CobraMkIII' : 'Cobra Mk III',
'DiamondBack' : 'Diamondback Scout',
'DiamondBackXL' : 'Diamondback Explorer',
'Eagle' : 'Eagle',
'Empire_Courier' : 'Imperial Courier',
'Empire_Fighter' : 'Imperial Fighter',
'Empire_Trader' : 'Imperial Clipper',
'Federation_Dropship' : 'Federal Dropship',
'Federation_Fighter' : 'F63 Condor',
'FerDeLance' : 'Fer-de-Lance',
'Hauler' : 'Hauler',
'Orca' : 'Orca',
'Python' : 'Python',
'SideWinder' : 'Sidewinder',
'Type6' : 'Type-6 Transporter',
'Type7' : 'Type-7 Transporter',
'Type9' : 'Type-9 Heavy',
'Viper' : 'Viper',
'Vulture' : 'Vulture',
}
class ServerError(Exception): class ServerError(Exception):
@ -165,7 +194,7 @@ class Session:
if __debug__: print 'Invalid "%s":"%s" (%s) for "%s"' % (thing, commodity.get(thing), type(commodity.get(thing)), commodity.get('name', '')) if __debug__: print 'Invalid "%s":"%s" (%s) for "%s"' % (thing, commodity.get(thing), type(commodity.get(thing)), commodity.get('name', ''))
break break
else: else:
if not categorymap.get(commodity['categoryname'], True): # Check marketable if not category_map.get(commodity['categoryname'], True): # Check marketable
pass pass
elif not commodity.get('categoryname', '').strip(): elif not commodity.get('categoryname', '').strip():
if __debug__: print 'Missing "categoryname" for "%s"' % commodity.get('name', '') if __debug__: print 'Missing "categoryname" for "%s"' % commodity.get('name', '')
@ -177,9 +206,9 @@ class Session:
if __debug__: print 'Invalid "stockBracket":"%s" for "%s"' % (commodity['stockBracket'], commodity['name']) if __debug__: print 'Invalid "stockBracket":"%s" for "%s"' % (commodity['stockBracket'], commodity['name'])
else: else:
# Rewrite text fields # Rewrite text fields
commodity['categoryname'] = categorymap.get(commodity['categoryname'].strip(), commodity['categoryname'] = category_map.get(commodity['categoryname'].strip(),
commodity['categoryname'].strip()) commodity['categoryname'].strip())
commodity['name'] = commoditymap.get(commodity['name'].strip(), commodity['name'] = commodity_map.get(commodity['name'].strip(),
commodity['name'].strip()) commodity['name'].strip())
# Force demand and stock to zero if their corresponding bracket is zero # Force demand and stock to zero if their corresponding bracket is zero

View File

@ -69,6 +69,7 @@ class Config:
OUT_BPC = 2 OUT_BPC = 2
OUT_TD = 4 OUT_TD = 4
OUT_CSV = 8 OUT_CSV = 8
OUT_SHIP = 16
if platform=='darwin': if platform=='darwin':

98
loadout.py Normal file
View File

@ -0,0 +1,98 @@
# Export ship loadout
from collections import defaultdict
import os
from os.path import join
import re
import time
from config import config
import outfitting
from companion import ship_map
# API slot names to E:D Shipyard slot names
slot_map = {
'LargeHardpoint' : 'L',
'MediumHardpoint' : 'M',
'SmallHardpoint' : 'S',
'TinyHardpoint' : 'U',
'Armour' : 'BH',
'PowerPlant' : 'RB',
'MainEngines' : 'TM',
'FrameShiftDrive' : 'FH',
'LifeSupport' : 'EC',
'PowerDistributor' : 'PC',
'Radar' : 'SS',
'FuelTank' : 'FS',
}
def export(data):
def class_rating(module):
if 'guidance' in module:
return module['class'] + module['rating'] + '/' + module.get('mount', 'F')[0] + module['guidance'][0] + ' '
elif 'mount' in module:
return module['class'] + module['rating'] + '/' + module['mount'][0] + ' '
else:
return module['class'] + module['rating'] + ' '
querytime = config.getint('querytime') or int(time.time())
ship = ship_map.get(data['ship']['name'], data['ship']['name'])
loadout = defaultdict(list)
for slot in sorted(data['ship']['modules']):
v = data['ship']['modules'][slot]
if not v or not v.get('module'):
continue
try:
module = outfitting.lookup(v['module'])
if not module: continue
except AssertionError as e:
if __debug__: print 'Loadout: %s' % e
continue # Silently skip unrecognized modules
except:
if __debug__: raise
cr = class_rating(module)
# Specials
if module['name'] in ['Fuel Tank', 'Cargo Rack']:
name = '%s (Capacity: %d)' % (module['name'], 2**int(module['class']))
else:
name = module['name']
for s in slot_map:
if slot.startswith(s):
loadout[slot_map[s]].append(cr + name)
break
else:
if slot.startswith('Slot'):
loadout[slot[-1]].append(cr + name)
elif __debug__: print 'Loadout: Unknown slot %s' % slot
# Construct description
string = '[%s]\n' % ship
for slot in ['L', 'M', 'S', 'U', None, 'BH', 'RB', 'TM', 'FH', 'EC', 'PC', 'SS', 'FS', None, '9', '8', '7', '6', '5', '4', '3', '2', '1']:
if not slot:
string += '\n'
elif slot in loadout:
for name in loadout[slot]:
string += '%s: %s\n' % (slot, name)
string += '---\nCargo : %d T\nFuel : %d T\nPrice : %s CR\n' % (data['ship']['cargo']['capacity'], data['ship']['fuel']['capacity'], '{:,}'.format(data['ship']['value']['total']))
# Look for last ship of this type
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)

346
outfitting.py Executable file
View File

@ -0,0 +1,346 @@
#!/usr/bin/python
#
# Script for building table ID->module mapping table from a dump of the Companion API output
#
import csv
import json
import os
from os.path import exists, isfile
import sys
from companion import ship_map
outfile = 'outfitting.csv'
outfitting = {}
armour_map = {
'Grade1' : 'Lightweight Alloy',
'Grade2' : 'Reinforced Alloy',
'Grade3' : 'Military Grade Composite',
'Mirrored' : 'Mirrored Surface Composite',
'Reactive' : 'Reactive Surface Composite',
}
weapon_map = {
'AdvancedTorpPylon' : 'Torpedo Pylon',
'BasicMissileRack' : 'Missile Rack',
'BeamLaser' : 'Beam Laser',
'Cannon' : 'Cannon',
'DumbfireMissileRack' : 'Missile Rack',
'MineLauncher' : 'Mine Launcher',
'MiningLaser' : 'Mining Laser',
'MultiCannon' : 'Multi-Cannon',
'PlasmaAccelerator' : 'Plasma Accelerator',
'PulseLaser' : 'Pulse Laser',
'PulseLaserBurst' : 'Burst Laser',
'Railgun' : 'Rail Gun',
'Slugshot' : 'Fragment Cannon',
}
missiletype_map = {
'AdvancedTorpPylon' : 'Seeker',
'BasicMissileRack' : 'Seeker',
'DumbfireMissileRack' : 'Dumbfire',
}
weaponmount_map = {
'Fixed' : 'Fixed',
'Gimbal' : 'Gimballed',
'Turret' : 'Turreted',
}
weaponclass_map = {
'Tiny' : '0',
'Small' : '1',
'Medium' : '2',
'Large' : '3',
'Huge' : '4',
}
# There's no discernable pattern for weapon ratings, so here's a lookup table
weaponrating_map = {
'Hpt_AdvancedTorpPylon_Fixed_Small': 'I',
'Hpt_AdvancedTorpPylon_Fixed_Medium': 'I',
'Hpt_BasicMissileRack_Fixed_Small': 'B',
'Hpt_BasicMissileRack_Fixed_Medium': 'B',
'Hpt_BeamLaser_Fixed_Small': 'E',
'Hpt_BeamLaser_Fixed_Medium': 'D',
'Hpt_BeamLaser_Fixed_Large': 'C',
'Hpt_BeamLaser_Gimbal_Small': 'E',
'Hpt_BeamLaser_Gimbal_Medium': 'D',
'Hpt_BeamLaser_Gimbal_Large': 'C',
'Hpt_BeamLaser_Turret_Small': 'F',
'Hpt_BeamLaser_Turret_Medium': 'E',
'Hpt_BeamLaser_Turret_Large': 'D',
'Hpt_Cannon_Fixed_Small': 'D',
'Hpt_Cannon_Fixed_Medium': 'D',
'Hpt_Cannon_Fixed_Large': 'C',
'Hpt_Cannon_Fixed_Huge': 'B',
'Hpt_Cannon_Gimbal_Small': 'E',
'Hpt_Cannon_Gimbal_Medium': 'D',
'Hpt_Cannon_Gimbal_Large': 'C',
'Hpt_Cannon_Gimbal_Huge': 'B',
'Hpt_Cannon_Turret_Small': 'F',
'Hpt_Cannon_Turret_Medium': 'E',
'Hpt_Cannon_Turret_Large': 'D',
'Hpt_DumbfireMissileRack_Fixed_Small': 'B',
'Hpt_DumbfireMissileRack_Fixed_Medium': 'B',
'Hpt_MineLauncher_Fixed_Small': 'I',
'Hpt_MineLauncher_Fixed_Medium': 'I',
'Hpt_MiningLaser_Fixed_Small': 'D',
'Hpt_MiningLaser_Fixed_Medium': 'D',
'Hpt_MultiCannon_Fixed_Small': 'F',
'Hpt_MultiCannon_Fixed_Medium': 'E',
'Hpt_MultiCannon_Gimbal_Small': 'G',
'Hpt_MultiCannon_Gimbal_Medium': 'F',
'Hpt_MultiCannon_Turret_Small': 'G',
'Hpt_MultiCannon_Turret_Medium': 'F',
'Hpt_PlasmaAccelerator_Fixed_Medium': 'C',
'Hpt_PlasmaAccelerator_Fixed_Large': 'B',
'Hpt_PlasmaAccelerator_Fixed_Huge': 'A',
'Hpt_PulseLaser_Fixed_Small': 'F',
'Hpt_PulseLaser_Fixed_Medium': 'E',
'Hpt_PulseLaser_Fixed_Large': 'D',
'Hpt_PulseLaser_Gimbal_Small': 'G',
'Hpt_PulseLaser_Gimbal_Medium': 'F',
'Hpt_PulseLaser_Gimbal_Large': 'E',
'Hpt_PulseLaser_Turret_Small': 'G',
'Hpt_PulseLaser_Turret_Medium': 'F',
'Hpt_PulseLaser_Turret_Large': 'F',
'Hpt_PulseLaserBurst_Fixed_Small': 'F',
'Hpt_PulseLaserBurst_Fixed_Medium': 'E',
'Hpt_PulseLaserBurst_Fixed_Large': 'D',
'Hpt_PulseLaserBurst_Gimbal_Small': 'G',
'Hpt_PulseLaserBurst_Gimbal_Medium': 'F',
'Hpt_PulseLaserBurst_Gimbal_Large': 'E',
'Hpt_PulseLaserBurst_Turret_Small': 'G',
'Hpt_PulseLaserBurst_Turret_Medium': 'F',
'Hpt_PulseLaserBurst_Turret_Large': 'E',
'Hpt_Railgun_Fixed_Small': 'D',
'Hpt_Railgun_Fixed_Medium': 'B',
'Hpt_Slugshot_Fixed_Small': 'E',
'Hpt_Slugshot_Fixed_Medium': 'A',
'Hpt_Slugshot_Fixed_Large': 'C',
'Hpt_Slugshot_Gimbal_Small': 'E',
'Hpt_Slugshot_Gimbal_Medium': 'D',
'Hpt_Slugshot_Gimbal_Large': 'C',
'Hpt_Slugshot_Turret_Small': 'E',
'Hpt_Slugshot_Turret_Medium': 'D',
'Hpt_Slugshot_Turret_Large': 'C',
}
utility_map = {
'CargoScanner' : 'Cargo Scanner',
'ChaffLauncher' : 'Chaff Launcher',
'CloudScanner' : 'Frame Shift Wake Scanner',
'CrimeScanner' : 'Kill Warrant Scanner',
'ElectronicCountermeasure' : 'Electronic Countermeasure',
'HeatSinkLauncher' : 'Heat Sink Launcher',
'PlasmaPointDefence' : 'Point Defence',
'ShieldBooster' : 'Shield Booster',
}
rating_map = {
'1': 'E',
'2': 'D',
'3': 'C',
'4': 'B',
'5': 'A',
}
standard_map = {
'Armour' : 'Bulkheads',
'Engine' : 'Thrusters',
'FuelTank' : 'Fuel Tank',
'Hyperdrive' : 'Frame Shift Drive',
'LifeSupport' : 'Life Support',
'PowerDistributor' : 'Power Distributor',
'Powerplant' : 'Power Plant',
'Sensors' : 'Sensors',
}
stellar_map = {
'Standard' : ('Basic Discovery Scanner', 'E'),
'Intermediate' : ('Intermediate Discovery Scanner', 'D'),
'Advanced' : ('Advanced Discovery Scanner', 'C'),
'Tiny' : ('Detailed Surface Scanner', 'C'),
}
internal_map = {
'CargoRack' : 'Cargo Rack',
'Collection' : 'Collector Limpet Controller',
'FSDInterdictor' : 'Frame Shift Drive Interdictor',
'FuelScoop' : 'Fuel Scoop',
'FuelTransfer' : 'Fuel Transfer Limpet Controller',
'HullReinforcement' : 'Hull Reinforcement Package',
'Prospector' : 'Prospector Limpet Controller',
'Refinery' : 'Refinery',
'Repairer' : 'Auto Field-Maintenance Unit',
'ResourceSiphon' : 'Hatch Breaker Limpet Controller',
'ShieldCellBank' : 'Shield Cell Bank',
'ShieldGenerator' : 'Shield Generator',
}
# Given a module description from the Companion API returns a description of the module in the form of a
# dict { category, name, [mount], [guidance], [ship], rating, class } using the same terms found in the
# English langauge game.
# Or returns None if the module is user-specific (i.e. decal, paintjob).
# (Given the ad-hocery in this implementation a big lookup table might have been simpler and clearer).
def lookup(module):
# 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'])
name = module['name'].split('_')
new = {}
# Armour - e.g. Federation_Dropship_Armour_Grade2
if name[-2] == 'Armour':
name = module['name'].rsplit('_', 2) # Armour is ship-specific, and ship names can have underscores
new['category'] = 'standard'
new['name'] = armour_map[name[2]]
new['ship'] = ship_map.get(name[0], name[0])
new['class'] = '1'
new['rating'] = 'I'
# Skip uninteresting stuff
elif name[0].lower() in ['decal', 'paintjob']: # Have seen "paintjob" and "PaintJob"
return None
# Shouldn't be listing player-specific paid stuff
elif module.get('sku'):
raise AssertionError('%s: Unexpected sku "%s"' % (module['id'], module['sku']))
# 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]))
if name[3] not in weaponclass_map: raise AssertionError('%s: Unknown weapon class "%s"' % (module['id'], name[3]))
# if module['name'] not in weaponrating_map: raise AssertionError('%s: Unknown rating for this weapon' % module['id'])
new['category'] = 'hardpoint'
new['name'] = weapon_map[name[1]]
new['mount'] = weaponmount_map[name[2]]
if name[1] in missiletype_map: # e.g. Hpt_DumbfireMissileRack_Fixed_Small
new['guidance'] = missiletype_map[name[1]]
new['class'] = weaponclass_map[name[3]]
new['rating'] = weaponrating_map.get(module['name'], '?') # no obvious rule - needs lookup table
# Utility - e.g. Hpt_CargoScanner_Size0_Class1
elif name[0]=='Hpt' and name[1] in utility_map:
new['category'] = 'utility'
new['name'] = utility_map[name[1]]
if name[-1] in weaponclass_map: # e.g. Hpt_PlasmaPointDefence_Turret_Tiny
new['class'] = weaponclass_map[name[-1]]
new['rating'] = 'I'
else:
if not name[2].startswith('Size') or not name[3].startswith('Class'): raise AssertionError('%s: Unknown class/rating "%s/%s"' % (module['id'], name[2], name[3]))
new['class'] = name[2][4:]
new['rating'] = rating_map[name[3][5:]]
elif name[0]=='Hpt':
raise AssertionError('%s: Unknown weapon "%s"' % (module['id'], name[1]))
# Stellar scanners - e.g. Int_StellarBodyDiscoveryScanner_Standard
elif name[1] in ['StellarBodyDiscoveryScanner', 'DetailedSurfaceScanner']:
new['category'] = 'internal'
new['name'], new['rating'] = stellar_map[name[2]]
new['class'] = '1'
# Docking Computer - e.g. Int_DockingComputer_Standard
elif name[1] == 'DockingComputer' and name[2] == 'Standard':
new['category'] = 'internal'
new['name'] = 'Standard Docking Computer'
new['class'] = '1'
new['rating'] = 'E'
# Standard & Internal
else:
# Reported category is not necessarily helpful. e.g. "Int_DockingComputer_Standard" has category "utility"
if name[0] != 'Int': raise AssertionError('%s: Unknown prefix "%s"' % (module['id'], name[0]))
if name[1] == 'DroneControl': # e.g. Int_DroneControl_Collection_Size1_Class1
name.pop(0)
if name[1] in standard_map: # e.g. Int_Engine_Size2_Class1
new['category'] = 'standard'
new['name'] = standard_map[name[1]]
elif name[1] in internal_map: # e.g. Int_CargoRack_Size8_Class1
new['category'] = 'internal'
new['name'] = internal_map[name[1]]
else:
raise AssertionError('%s: Unknown module "%s"' % (module['id'], name[1]))
if not name[2].startswith('Size') or not name[3].startswith('Class'): raise AssertionError('%s: Unknown class/rating "%s/%s"' % (module['id'], name[2], name[3]))
new['class'] = name[2][4:]
new['rating'] = rating_map[name[3][5:]]
# check we've filled out mandatory fields
for thing in ['category', 'name', 'class', 'rating']:
if not new.get('name'): raise AssertionError('%s: failed to set %s' % (module['id'], thing))
return new
# add all the modules
def addmodules(data):
if not data.get('lastStarport'):
print 'No Starport!'
return
elif not data['lastStarport'].get('modules'):
print 'No outfitting here'
return
# read into outfitting
if isfile(outfile):
with open(outfile) as csvfile:
reader = csv.DictReader(csvfile)
for row in reader:
key = int(row.pop('id')) # index by int for easier lookup and sorting
outfitting[key] = row
size_pre = len(outfitting)
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 = lookup(module)
if new:
old = outfitting.get(int(key))
if old:
# check consistency with existing data
for thing in ['category', 'name', 'mount', 'guidance', 'ship', 'class', 'rating']:
if new.get(thing,'') != old.get(thing): raise AssertionError('%s: %s "%s"!="%s"' % (key, thing, new.get(thing), old.get(thing)))
else:
outfitting[int(key)] = new
if len(outfitting) > size_pre:
if isfile(outfile):
if isfile(outfile+'.bak'):
os.unlink(outfile+'.bak')
os.rename(outfile, outfile+'.bak')
with open(outfile, 'wb') as csvfile:
writer = csv.DictWriter(csvfile, ['id', 'category', 'name', 'mount', 'guidance', 'ship', 'class', 'rating'])
writer.writeheader()
for key in sorted(outfitting):
row = outfitting[key]
row['id'] = key
writer.writerow(row)
print 'Added %d new modules' % (len(outfitting) - size_pre)
else:
print
if __name__ == "__main__":
if len(sys.argv) <= 1:
print 'Usage: outfitting.py [dump.json]'
else:
# read from dumped json file(s)
for f in sys.argv[1:]:
with open(f) as h:
print f,
addmodules(json.loads(h.read()))

View File

@ -76,8 +76,8 @@ class PreferencesDialog(tk.Toplevel):
outframe.grid(padx=10, pady=10, sticky=tk.NSEW) outframe.grid(padx=10, pady=10, sticky=tk.NSEW)
outframe.columnconfigure(0, weight=1) outframe.columnconfigure(0, weight=1)
output = config.getint('output') or config.OUT_EDDN output = config.getint('output') or (config.OUT_EDDN | config.OUT_SHIP)
ttk.Label(outframe, text="Please choose where you want the market data saved").grid(row=0, columnspan=2, padx=5, pady=3, sticky=tk.W) ttk.Label(outframe, text="Please choose where you want the data saved").grid(row=0, columnspan=2, padx=5, pady=3, sticky=tk.W)
self.out_eddn= tk.IntVar(value = (output & config.OUT_EDDN) and 1 or 0) self.out_eddn= tk.IntVar(value = (output & config.OUT_EDDN) and 1 or 0)
ttk.Checkbutton(outframe, text="Online to the Elite Dangerous Data Network (EDDN)", variable=self.out_eddn).grid(row=1, columnspan=2, padx=5, sticky=tk.W) ttk.Checkbutton(outframe, text="Online to the Elite Dangerous Data Network (EDDN)", variable=self.out_eddn).grid(row=1, columnspan=2, padx=5, sticky=tk.W)
self.out_bpc = tk.IntVar(value = (output & config.OUT_BPC ) and 1 or 0) self.out_bpc = tk.IntVar(value = (output & config.OUT_BPC ) and 1 or 0)
@ -86,12 +86,14 @@ class PreferencesDialog(tk.Toplevel):
ttk.Checkbutton(outframe, text="Offline in Trade Dangerous format", variable=self.out_td, command=self.outvarchanged).grid(row=3, columnspan=2, padx=5, sticky=tk.W) ttk.Checkbutton(outframe, text="Offline in Trade Dangerous format", variable=self.out_td, command=self.outvarchanged).grid(row=3, columnspan=2, padx=5, sticky=tk.W)
self.out_csv = tk.IntVar(value = (output & config.OUT_CSV ) and 1 or 0) self.out_csv = tk.IntVar(value = (output & config.OUT_CSV ) and 1 or 0)
ttk.Checkbutton(outframe, text="Offline in CSV format", variable=self.out_csv, command=self.outvarchanged).grid(row=4, columnspan=2, padx=5, sticky=tk.W) ttk.Checkbutton(outframe, text="Offline in CSV format", variable=self.out_csv, command=self.outvarchanged).grid(row=4, columnspan=2, padx=5, sticky=tk.W)
ttk.Label(outframe, text=(platform=='darwin' and 'Where:' or 'File location:')).grid(row=5, padx=5, pady=(5,0), sticky=tk.NSEW) self.out_ship= tk.IntVar(value = (output & config.OUT_SHIP) and 1 or 0)
ttk.Checkbutton(outframe, text="Offline loadout in E:D Shipyard format", variable=self.out_ship, command=self.outvarchanged).grid(row=5, columnspan=2, padx=5, sticky=tk.W)
ttk.Label(outframe, text=(platform=='darwin' and 'Where:' or 'File location:')).grid(row=6, padx=5, pady=(5,0), sticky=tk.NSEW)
self.outbutton = ttk.Button(outframe, text=(platform=='darwin' and 'Change...' or 'Browse...'), command=self.outbrowse) self.outbutton = ttk.Button(outframe, text=(platform=='darwin' and 'Change...' or 'Browse...'), command=self.outbrowse)
self.outbutton.grid(row=5, column=1, padx=5, pady=(5,0), sticky=tk.NSEW) self.outbutton.grid(row=6, column=1, padx=5, pady=(5,0), sticky=tk.NSEW)
self.outdir = ttk.Entry(outframe) self.outdir = ttk.Entry(outframe)
self.outdir.insert(0, config.get('outdir')) self.outdir.insert(0, config.get('outdir'))
self.outdir.grid(row=6, columnspan=2, padx=5, pady=5, sticky=tk.EW) self.outdir.grid(row=7, columnspan=2, padx=5, pady=5, sticky=tk.EW)
self.outvarchanged() self.outvarchanged()
privacyframe = ttk.LabelFrame(frame, text='Privacy') privacyframe = ttk.LabelFrame(frame, text='Privacy')
@ -118,7 +120,7 @@ class PreferencesDialog(tk.Toplevel):
#self.wait_window(self) # causes duplicate events on OSX #self.wait_window(self) # causes duplicate events on OSX
def outvarchanged(self): def outvarchanged(self):
local = self.out_bpc.get() or self.out_td.get() or self.out_csv.get() local = self.out_bpc.get() or self.out_td.get() or self.out_csv.get() or self.out_ship.get()
self.outbutton['state'] = local and tk.NORMAL or tk.DISABLED self.outbutton['state'] = local and tk.NORMAL or tk.DISABLED
self.outdir['state'] = local and 'readonly' or tk.DISABLED self.outdir['state'] = local and 'readonly' or tk.DISABLED
@ -157,7 +159,7 @@ class PreferencesDialog(tk.Toplevel):
credentials = (config.get('username'), config.get('password')) credentials = (config.get('username'), config.get('password'))
config.set('username', self.username.get().strip()) config.set('username', self.username.get().strip())
config.set('password', self.password.get().strip()) config.set('password', self.password.get().strip())
config.set('output', (self.out_eddn.get() and config.OUT_EDDN or 0) + (self.out_bpc.get() and config.OUT_BPC or 0) + (self.out_td.get() and config.OUT_TD or 0) + (self.out_csv.get() and config.OUT_CSV or 0)) config.set('output', (self.out_eddn.get() and config.OUT_EDDN or 0) + (self.out_bpc.get() and config.OUT_BPC or 0) + (self.out_td.get() and config.OUT_TD or 0) + (self.out_csv.get() and config.OUT_CSV or 0) + (self.out_ship.get() and config.OUT_SHIP or 0))
config.set('outdir', self.outdir.get().strip()) config.set('outdir', self.outdir.get().strip())
config.set('anonymous', self.out_anon.get()) config.set('anonymous', self.out_anon.get())
self.destroy() self.destroy()