Skip to content

Commit

Permalink
Added systems and initial jumps/distance code.
Browse files Browse the repository at this point in the history
Added a separate notion of systems in preparation for supporting multiple stations per system. Partial.

Added preliminary 'getDestinations' code to Station which tells you how many stations it can reach and how many light years it takes to get there and how many jumps. This can then be used for best trade calculations at run time rather than limiting the data we load based on direct links. Thus you'll be able to find trades that require more than one jump.
  • Loading branch information
kfsone committed Aug 7, 2014
1 parent 4e5d6fd commit 1c56a80
Show file tree
Hide file tree
Showing 2 changed files with 71 additions and 19 deletions.
2 changes: 1 addition & 1 deletion tradecalc.py
Original file line number Diff line number Diff line change
Expand Up @@ -95,7 +95,7 @@ def getBestTrade(self, src, dst, startCr, capacity=None):
raise ValueError("%s does not have a link to %s" % (src, dst))

# Get a list of what we can buy
return self.tryCombinations(startCr, src.links[dst.ID], capacity)
return self.tryCombinations(startCr, src.trades[dst.ID], capacity)

def getBestHopFrom(self, src, credits, capacity=None):
""" Determine the best trade run from a given station. """
Expand Down
88 changes: 70 additions & 18 deletions tradedb.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,7 @@
# Imports

import pypyodbc
from queue import Queue

######################################################################
# Classes
Expand All @@ -26,32 +27,53 @@ def __repr__(self):
return "%s (%dcr)" % (self.item, self.costCr)


class System(object):
""" Describes a star system, which may contain one or more Station objects,
and lists which stars it has a direct connection to. """

def __init__(self, system):
self.system = system
self.links = {}
self.stations = []

def addLink(self, dest, dist):
self.links[dest] = dist

def links(self):
return list(self.links.keys())

def addStation(self, station):
if not station in self.stations:
self.stations.append(station)

def str(self):
return self.system


class Station(object):
""" Describes a station and which stations it links to, the links themselves
also describe what products can be sold to the destination and how much
profit can be earned by doing so. These are stored in gain order so that
we can easily tell if we can afford to fill up on the most expensive
item. """
""" Describes a station within a given system along with what trade
opportunities it presents. """
def __init__(self, ID, system, station):
self.ID, self.system, self.station = ID, system.replace(' ', ''), station.replace(' ', '')
self.links = {}
self.ID, self.system, self.station = ID, system, station.replace(' ', '')
self.trades = {}
self.stations = []
system.addStation(self)

def addTrade(self, dest, item, itemID, costCr, gainCr):
""" Add a Trade entry from this to a destination station. """
dstID = dest.ID
if not dstID in self.links:
self.links[dstID] = []
if not dstID in self.trades:
self.trades[dstID] = []
self.stations.append(dest)
trade = Trade(item, itemID, costCr, gainCr)
self.links[dstID].append(trade)
self.trades[dstID].append(trade)

def organizeTrades(self):
""" Process the trades-to-destination lists: If there are multiple items
with the same gain for a given link, only keep the cheapest. Then
sort the list into by-gain order. """
for dstID in self.links:
items = self.links[dstID]
for dstID in self.trades:
items = self.trades[dstID]
# Find the cheapest item
cheapest = min(items, key=lambda item: item.costCr)
cheapestGain = cheapest.gainCr
Expand All @@ -64,15 +86,37 @@ def organizeTrades(self):
gains[itemGainCr] = item
# Now sort the list in descending gain order - so the most
# profitable item is listed first.
self.links[dstID] = sorted([item for item in gains.values()], key=lambda trade: trade.gainCr, reverse=True)
self.trades[dstID] = sorted([item for item in gains.values()], key=lambda trade: trade.gainCr, reverse=True)

def getDestinations(self, maxJumps=None, maxLy=None):
openList, closedList, destStations = Queue(), dict(), []
openList.put([self.system, 0, 0])
while not openList.empty():
(sys, jumps, dist) = openList.get()
if (maxJumps and jumps > maxJumps) or (maxLy and dist > maxLy):
continue
for stn in sys.stations:
if stn != self:
destStations.append([sys, stn, jumps, dist])
jumps += 1
if (maxJumps and jumps > maxJumps):
continue
for (destSys, destDist) in sys.links.items():
if maxLy and dist + destDist > maxLy:
continue
if destSys in closedList:
continue
openList.put([destSys, jumps, dist + destDist])
closedList[destSys] = 1
return destStations

def __repr__(self):
str = self.system + " " + self.station
str = self.system.str() + " " + self.station
return str


class TradeDB(object):
def __init__(self, path="TradeDangerous.accdb"):
def __init__(self, path=r'.\TradeDangerous.accdb'):
self.path = "Driver={Microsoft Access Driver (*.mdb, *.accdb)};DBQ=" + path
self.load()

Expand All @@ -81,11 +125,19 @@ def load(self, avoiding=[], ignoreLinks=False):
conn = pypyodbc.connect(self.path)
cur = conn.cursor()

cur.execute('SELECT system FROM Stations GROUP BY system')
self.systems = { row[0]: System(row[0]) for row in cur }
cur.execute("""SELECT frmSys.system, toSys.system
FROM Stations AS frmSys, Links, Stations as toSys
WHERE frmSys.ID = Links.from AND toSys.ID = Links.to""")
for row in cur:
self.systems[row[0]].addLink(self.systems[row[1]], 1)

cur.execute('SELECT id, system, station FROM Stations')
# Station lookup by ID
self.stations = { row[0]: Station(row[0], row[1], row[2]) for row in cur}
self.stations = { row[0]: Station(row[0], self.systems[row[1]], row[2]) for row in cur }
# StationID lookup by System Name
self.systemIDs = { value.system.upper(): key for (key, value) in self.stations.items() }
self.systemIDs = { value.system.str().upper(): key for (key, value) in self.stations.items() }
# StationID lookup by Station Name
self.stationIDs = { value.station.upper(): key for (key, value) in self.stations.items() }

Expand Down Expand Up @@ -133,4 +185,4 @@ def query(self, sql):

def fetch_all(self, sql):
for row in self.query(sql):
yield row
yield row

0 comments on commit 1c56a80

Please sign in to comment.