-
Notifications
You must be signed in to change notification settings - Fork 32
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Oliver Smith
committed
Dec 11, 2014
1 parent
02dc9be
commit bd73e5e
Showing
1 changed file
with
186 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,186 @@ | ||
#! /usr/bin/env python | ||
|
||
# Experimental module to generate a JSON version of the .prices file. | ||
|
||
# Set to True to allow export of systems that don't have any station data | ||
emptySystems = True | ||
# Set to True to allow export of stations that don't have prices | ||
emptyStations = True | ||
# Positions should be xferred as whole multiples of this | ||
posMultiplier = 32 | ||
|
||
import sqlite3 | ||
import json | ||
import time | ||
import collections | ||
import os | ||
|
||
conn = sqlite3.connect("data/TradeDangerous.db") | ||
|
||
def collectItemData(db): | ||
""" | ||
Builds a flat, array of item names that serves as a table of items. | ||
Station Price Data refers to this table by position in the array. | ||
As a result, we also need a mapping for itemID -> tableID | ||
""" | ||
|
||
items = [] # table of items | ||
itemIdx = {} # mapping from itemID -> position in items | ||
for ID, name in db.execute("SELECT i.item_id, i.name FROM Item AS i"): | ||
itemIdx[ID] = len(items) | ||
items.append(name) | ||
|
||
return items, itemIdx | ||
|
||
|
||
def collectSystems( | ||
db, | ||
itemIdx, | ||
posMult=None, | ||
withEmptySystems=False, | ||
withStations=True, | ||
withEmptyStations=False, | ||
withPrices=True | ||
): | ||
""" | ||
Build the System -> Station -> Price data from the supplied DB. | ||
withEmptySystems: | ||
True: include systems with no station data. | ||
withStations: | ||
False: (implies withEmptySystems=True) don't include station data. | ||
withEmptyStations: | ||
True: include stations with no price data. | ||
withPrices: | ||
False: (implies withEmptyStations=True) don't include price data. | ||
""" | ||
|
||
systems = collections.defaultdict(dict) | ||
if not withStations: | ||
withEmptySystems = True | ||
|
||
for sysID, sys, posX, posY, posZ in db.execute(""" | ||
SELECT sys.system_id, sys.name, | ||
sys.pos_x, sys.pos_y, sys.pos_z | ||
FROM System AS sys | ||
LEFT OUTER JOIN Station | ||
USING (system_id) | ||
GROUP BY 1 | ||
"""): | ||
if posMult: | ||
posX = int(posX * posMult) | ||
posY = int(posY * posMult) | ||
posZ = int(posZ * posMult) | ||
systemData = { | ||
'pos': [ posX, posY, posZ ], | ||
} | ||
if withStations: | ||
stations = collectStations( | ||
db, itemIdx, | ||
sysID, | ||
withEmptyStations=withEmptyStations, | ||
withPrices=withPrices, | ||
) | ||
if not stations and not withEmptySystems: | ||
continue | ||
if stations: | ||
systemData['stn'] = stations | ||
systems[sys] = systemData | ||
|
||
return systems | ||
|
||
|
||
def collectStations( | ||
db, | ||
itemIdx, | ||
sysID, | ||
withEmptyStations=False, | ||
withPrices=True | ||
): | ||
""" | ||
Populate a station list for a given system, including price data. | ||
""" | ||
stations = {} | ||
if not withPrices: | ||
withEmptyStations = True | ||
for stnID, name, lsFromStar, lastMod in db.execute(""" | ||
SELECT stn.station_id, stn.name, stn.ls_from_star, | ||
MAX(si.modified) | ||
FROM Station AS stn | ||
LEFT OUTER JOIN StationItem si | ||
USING (station_id) | ||
WHERE stn.system_id = ? | ||
GROUP BY 1 | ||
""", [sysID]): | ||
if not lastMod and not withEmptyStations: | ||
continue | ||
stationData = { | ||
'ls': int(lsFromStar), | ||
} | ||
if lastMod: | ||
stationData['ts'] = lastMod | ||
if withPrices: | ||
buy, sell = collectPriceData( | ||
db, itemIdx, | ||
stnID, | ||
) | ||
stationData['buy'] = buy | ||
stationData['sell'] = sell | ||
|
||
stations[name] = stationData | ||
|
||
return stations | ||
|
||
|
||
def collectPriceData(db, itemIdx, stnID): | ||
""" | ||
Collect buying and selling data for a given station. Items reference the | ||
position in the itemData array. | ||
""" | ||
|
||
buying, selling = [], [] | ||
|
||
for itmID, cr in db.execute(""" | ||
SELECT sb.item_id, sb.price | ||
FROM StationBuying AS sb | ||
WHERE station_id = ? | ||
""", [stnID]): | ||
buying.append([ itemIdx[itmID], cr ]) | ||
|
||
for itmID, cr, units, level in db.execute(""" | ||
SELECT ss.item_id, ss.price, ss.units, ss.level | ||
FROM StationSelling AS ss | ||
WHERE station_id = ? | ||
""", [stnID]): | ||
selling.append([ itemIdx[itmID], cr, units, level ]) | ||
|
||
return buying, selling | ||
|
||
|
||
itemData, itemIdx = collectItemData(conn) | ||
sysData = collectSystems( | ||
conn, itemIdx, | ||
posMult=posMultiplier, | ||
withEmptySystems=emptySystems, withEmptyStations=emptyStations | ||
) | ||
jsonData = { | ||
'src': 'td/json-exp', | ||
'posMult': posMultiplier, | ||
'time': int(time.time()), | ||
'items': itemData, | ||
'emptySys': emptySystems, | ||
'emptyStn': emptyStations, | ||
'sys': sysData, | ||
} | ||
|
||
try: | ||
cmdrName = os.environ['CMDR'] | ||
jsonData['cmdr'] = cmdrName | ||
except KeyError: | ||
pass | ||
|
||
print(json.dumps(jsonData, separators=(',',':'))) | ||
|