mirror of
https://github.com/EDCD/EDMarketConnector.git
synced 2025-04-13 15:57:14 +03:00
215 lines
6.7 KiB
Python
215 lines
6.7 KiB
Python
# Export ship loadout in E:D Shipyard plain text format
|
|
|
|
import pickle
|
|
from collections import defaultdict
|
|
import os
|
|
from os.path import join
|
|
import re
|
|
import time
|
|
|
|
from config import config
|
|
import companion
|
|
import outfitting
|
|
|
|
from typing import Dict, Union, List
|
|
__Module = Dict[str, Union[str, List[str]]]
|
|
|
|
# Map API ship names to E:D Shipyard ship names
|
|
ship_map = companion.ship_map.copy()
|
|
|
|
ship_map.update(
|
|
{
|
|
'cobramkiii': 'Cobra Mk III',
|
|
'cobramkiv' : 'Cobra Mk IV',
|
|
'viper' : 'Viper',
|
|
'viper_mkiv': 'Viper Mk IV',
|
|
}
|
|
)
|
|
|
|
|
|
# Map API slot names to E:D Shipyard slot names
|
|
slot_map = {
|
|
'hugehardpoint' : 'H',
|
|
'largehardpoint' : 'L',
|
|
'mediumhardpoint' : 'M',
|
|
'smallhardpoint' : 'S',
|
|
'tinyhardpoint' : 'U',
|
|
'armour' : 'BH',
|
|
'powerplant' : 'RB',
|
|
'mainengines' : 'TM',
|
|
'frameshiftdrive' : 'FH',
|
|
'lifesupport' : 'EC',
|
|
'powerdistributor' : 'PC',
|
|
'radar' : 'SS',
|
|
'fueltank' : 'FS',
|
|
'military' : 'MC',
|
|
}
|
|
|
|
|
|
# Ship masses
|
|
# TODO: prefer something other than pickle for this storage (dev readability, security)
|
|
ships = pickle.load(open(join(config.respath, 'ships.p'), 'rb'))
|
|
|
|
|
|
# Export ship loadout in E:D Shipyard plain text format
|
|
def export(data, filename=None):
|
|
def class_rating(module: __Module):
|
|
mod_class = module['class']
|
|
mod_rating = module['rating']
|
|
mod_mount = module.get('mount')
|
|
mod_guidance = module.get('guidance')
|
|
|
|
ret = '{mod_class}{rating}'.format(mod_class=mod_class, rating=mod_rating)
|
|
if 'guidance' in module: # Missiles
|
|
ret += "/{mount}{guidance}".format(
|
|
mount=mod_mount[0] if mod_mount is not None else 'F',
|
|
guidance=mod_guidance[0],
|
|
)
|
|
|
|
elif 'mount' in module: # Hardpoints
|
|
ret += "/{mount}".format(mount=mod_mount)
|
|
|
|
elif 'Cabin' in module['name']: # Passenger cabins
|
|
ret += "/{name}".format(name=module['name'][0])
|
|
|
|
return ret + ' '
|
|
|
|
querytime = config.get_int('querytime') or int(time.time())
|
|
|
|
loadout = defaultdict(list)
|
|
mass = 0.0
|
|
fuel = 0
|
|
cargo = 0
|
|
fsd = None
|
|
jumpboost = 0
|
|
|
|
for slot in sorted(data['ship']['modules']):
|
|
|
|
v = data['ship']['modules'][slot]
|
|
try:
|
|
if not v:
|
|
continue
|
|
|
|
module: __Module = outfitting.lookup(v['module'], ship_map)
|
|
if not module:
|
|
continue
|
|
|
|
cr = class_rating(module)
|
|
mods = v.get('modifications') or v.get('WorkInProgress_modifications') or {}
|
|
if mods.get('OutfittingFieldType_Mass'):
|
|
mass += (module.get('mass', 0) * mods['OutfittingFieldType_Mass']['value'])
|
|
|
|
else:
|
|
mass += module.get('mass', 0)
|
|
|
|
# Specials
|
|
if 'Fuel Tank' in module['name']:
|
|
fuel += 2**int(module['class'])
|
|
name = '{} (Capacity: {})'.format(module['name'], 2**int(module['class']))
|
|
|
|
elif 'Cargo Rack' in module['name']:
|
|
cargo += 2**int(module['class'])
|
|
name = '{} (Capacity: {})'.format(module['name'], 2**int(module['class']))
|
|
|
|
else:
|
|
name = module['name']
|
|
|
|
if name == 'Frame Shift Drive':
|
|
fsd = module # save for range calculation
|
|
|
|
if mods.get('OutfittingFieldType_FSDOptimalMass'):
|
|
fsd['optmass'] *= mods['OutfittingFieldType_FSDOptimalMass']['value']
|
|
|
|
if mods.get('OutfittingFieldType_MaxFuelPerJump'):
|
|
fsd['maxfuel'] *= mods['OutfittingFieldType_MaxFuelPerJump']['value']
|
|
|
|
jumpboost += module.get('jumpboost', 0)
|
|
|
|
for s in slot_map:
|
|
if slot.lower().startswith(s):
|
|
loadout[slot_map[s]].append(cr + name)
|
|
break
|
|
|
|
else:
|
|
if slot.lower().startswith('slot'):
|
|
loadout[slot[-1]].append(cr + name)
|
|
|
|
elif __debug__ and not slot.lower().startswith('planetaryapproachsuite'):
|
|
print('EDShipyard: Unknown slot {}'.format(slot))
|
|
|
|
except AssertionError as e:
|
|
if __debug__:
|
|
print('EDShipyard: {}'.format(e))
|
|
|
|
continue # Silently skip unrecognized modules
|
|
|
|
except Exception:
|
|
if __debug__:
|
|
raise
|
|
|
|
# Construct description
|
|
ship = ship_map.get(data['ship']['name'].lower(), data['ship']['name'])
|
|
|
|
if data['ship'].get('shipName') is not None:
|
|
_ships = '{}, {}'.format(ship, data['ship']['shipName'])
|
|
else:
|
|
_ships = ship
|
|
|
|
string = '[{}]\n'.format(_ships)
|
|
|
|
SLOT_TYPES = (
|
|
'H', 'L', 'M', 'S', 'U', None, 'BH', 'RB', 'TM', 'FH', 'EC', 'PC', 'SS', 'FS', None, 'MC', None, '9', '8',
|
|
'7', '6', '5', '4', '3', '2', '1'
|
|
)
|
|
for slot in SLOT_TYPES:
|
|
if not slot:
|
|
string += '\n'
|
|
|
|
elif slot in loadout:
|
|
for name in loadout[slot]:
|
|
string += '{}: {}\n'.format(slot, name)
|
|
|
|
string += '---\nCargo : {} T\nFuel : {} T\n'.format(cargo, fuel)
|
|
|
|
# Add mass and range
|
|
assert data['ship']['name'].lower() in companion.ship_map, data['ship']['name']
|
|
assert companion.ship_map[data['ship']['name'].lower()] in ships, companion.ship_map[data['ship']['name'].lower()]
|
|
|
|
try:
|
|
mass += ships[companion.ship_map[data['ship']['name'].lower()]]['hullMass']
|
|
string += 'Mass : {:.2f} T empty\n {:.2f} T full\n'.format(mass, mass + fuel + cargo)
|
|
|
|
multiplier = pow(min(fuel, fsd['maxfuel']) / fsd['fuelmul'], 1.0 / fsd['fuelpower']) * fsd['optmass']
|
|
|
|
string += 'Range : {:.2f} LY unladen\n {:.2f} LY laden\n'.format(
|
|
multiplier / (mass + fuel) + jumpboost,
|
|
multiplier / (mass + fuel + cargo) + jumpboost
|
|
)
|
|
|
|
except Exception:
|
|
if __debug__:
|
|
raise
|
|
|
|
if filename:
|
|
with open(filename, 'wt') as h:
|
|
h.write(string)
|
|
|
|
return
|
|
|
|
# Look for last ship of this type
|
|
ship = companion.ship_file_name(data['ship'].get('shipName'), data['ship']['name'])
|
|
regexp = re.compile(re.escape(ship) + r'\.\d{4}-\d\d-\d\dT\d\d\.\d\d\.\d\d\.txt')
|
|
oldfiles = sorted([x for x in os.listdir(config.get_str('outdir')) if regexp.match(x)])
|
|
if oldfiles:
|
|
with open(join(config.get_str('outdir'), oldfiles[-1]), 'rU') as h:
|
|
if h.read() == string:
|
|
return # same as last time - don't write
|
|
|
|
# Write
|
|
filename = join(config.get_str('outdir'), '{}.{}.txt'.format(
|
|
ship, time.strftime('%Y-%m-%dT%H.%M.%S', time.localtime(querytime)))
|
|
)
|
|
|
|
with open(filename, 'wt') as h:
|
|
h.write(string)
|