Skip to content

Commit

Permalink
Merged kfsone/tradedangerous into master
Browse files Browse the repository at this point in the history
  • Loading branch information
Falkery committed Dec 23, 2014
2 parents 9e8f3cf + b2255bf commit f8f9b51
Show file tree
Hide file tree
Showing 8 changed files with 216 additions and 56 deletions.
4 changes: 4 additions & 0 deletions CHANGES.txt
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,10 @@
TradeDangerous, Copyright (C) Oliver "kfsone" Smith, July 2014
==============================================================================

v6.2.5 [wip]
. (bgol) Fixed weirdness with rangeCache
. (bgol/kfsone) Fixed jump distances and performance of "nav" command

v6.2.4 Dec 21 2014
. (kfsone) Experimental "add-station" command in misc,
. (kfsone) Added "--near" to olddata command,
Expand Down
86 changes: 40 additions & 46 deletions commands/nav_cmd.py
Original file line number Diff line number Diff line change
Expand Up @@ -37,35 +37,19 @@ class NoRouteError(TradeException):
pass


class Distance(object):
def __init__(self, start, end, dist):
self.start, self.end, self.dist = start, end, dist

def __repr__(self):
return "Distance({}, {}, {})".format(
self.start, self.end, self.dist
)


def getRoute(cmdenv, tdb, srcSystem, dstSystem, maxLyPer):
openList = dict()
distances = { srcSystem: [ 0.0, None ] }

# Check for a direct route and seed the open list with the systems
# in direct-range of the origin.
for dstSys, dist in tdb.genSystemsInRange(srcSystem, maxLyPer):
distances[dstSys] = [ dist, srcSystem ]
if dstSys == dstSystem:
return [ dstSystem, srcSystem ], distances
openList[dstSys] = dist
# Is there only one system in the list?
if not openList:
raise NoRouteError(
"There are no systems within {}ly of {}.".format(
maxLyPer, srcSystem.name()
))

# Check whether the destination system has a connecting link
inRange = False
for dstSys, dist in tdb.genSystemsInRange(dstSystem, maxLyPer):
inRange = True
break
if not inRange:
raise NoRouteError(
"There are no systems within {}ly of {}.".format(
maxLyPer, dstSystem.name()
))
return None, None
openList = { srcSystem: 0 }
distances = { srcSystem: Distance(srcSystem, srcSystem, 0.0) }

avoiding = frozenset([
place.system if isinstance(place, Station) else place
Expand All @@ -74,8 +58,13 @@ def getRoute(cmdenv, tdb, srcSystem, dstSystem, maxLyPer):
if avoiding:
cmdenv.DEBUG0("Avoiding: {}", list(avoiding))

# As long as the open list is not empty, keep iterating.
while openList and dstSystem not in distances:
leastHops = False

# Once we find a path, we can curb any remaining paths that
# are longer. This allows us to search aggresively until we
# find the shortest route.
shortestDist = float("inf")
while openList:

# Expand the search domain by one jump; grab the list of
# nodes that are this many hops out and then clear the list.
Expand All @@ -87,32 +76,37 @@ def getRoute(cmdenv, tdb, srcSystem, dstSystem, maxLyPer):
if destSys in avoiding:
continue
dist = startDist + destDist
if dist >= shortestDist:
continue
# If we aready have a shorter path, do nothing
try:
distNode = distances[destSys]
if distNode[0] <= dist:
if distances[destSys].dist <= dist:
continue
distNode[0], distNode[1] = dist, node
except KeyError:
distances[destSys] = [ dist, node ]
pass
distances[destSys] = Distance(node, destSys, dist)
openList[destSys] = dist
if destSys == dstSystem:
shortestDist = dist

# Unravel the route by tracing back the vias.
route = [ dstSystem ]
while route[-1] != srcSystem:
jumpEnd = route[-1]
jumpEnd = dstSystem
while jumpEnd != srcSystem:
try:
jumpStart = distances[jumpEnd][1]
distEnt = distances[jumpEnd]
except KeyError:
raise NoRouteError(
"No route found between {} and {} "
"with {}ly jump limit.".format(
srcSystem.name(), dstSystem.name(), maxLyPer
))
return None, None
route.append(jumpStart)

return route, distances
route.append(distEnt.start)
jumpEnd = distEnt.start

return route


######################################################################
Expand All @@ -132,30 +126,30 @@ def run(results, cmdenv, tdb):
cmdenv.DEBUG0("Route from {} to {} with max {}ly per jump.",
srcSystem.name(), dstSystem.name(), maxLyPer)

route, distances = getRoute(cmdenv, tdb, srcSystem, dstSystem, maxLyPer)
route = getRoute(cmdenv, tdb, srcSystem, dstSystem, maxLyPer)

results.summary = ResultRow(
fromSys=srcSystem,
toSys=dstSystem,
maxLy=maxLyPer,
)

lastHop, totalLy, dirLy = None, 0.00, 0.00
lastSys, totalLy, dirLy = srcSystem, 0.00, 0.00
route.reverse()
for hop in route:
jumpLy = (distances[hop][0] - distances[lastHop][0]) if lastHop else 0.00
for jumpSys in route:
jumpLy = math.sqrt(lastSys.distToSq(jumpSys))
totalLy += jumpLy
if cmdenv.detail:
dirLy = math.sqrt(dstSystem.distToSq(hop))
dirLy = math.sqrt(jumpSys.distToSq(dstSystem))
row = ResultRow(
action='Via',
system=hop,
system=jumpSys,
jumpLy=jumpLy,
totalLy=totalLy,
dirLy=dirLy,
)
results.rows.append(row)
lastHop = hop
lastSys = jumpSys
results.rows[0].action='Depart'
results.rows[-1].action='Arrive'

Expand Down
85 changes: 83 additions & 2 deletions commands/update_gui.py
Original file line number Diff line number Diff line change
Expand Up @@ -132,7 +132,7 @@ class UpdateGUI(ScrollingCanvas):
def __init__(self, parent, tdb, tdenv):
super().__init__(parent)

width = tdenv.width or 600
width = tdenv.width or 640
height = tdenv.height or 640
sticky = 1 if tdenv.alwaysOnTop else 0

Expand Down Expand Up @@ -209,6 +209,50 @@ def validateRow(self, row):
row[3][1].set("?")


def checkValueAgainstStats(self, widget, stats):
cr = int(widget.val.get())
minCr, avgCr, maxCr = stats
widget.configure(bg = 'white')

if cr < int(minCr / 1.01) and cr < int(avgCr * 0.7):
widget.bell()
ok = mbox.askokcancel(
"Very low price",
"The price you entered is very low.\n"
"\n"
"Your input was: {}\n"
"Previous low..: {}\n"
"\n"
"Is it correct?".format(
cr, minCr,
))
if not ok:
widget.val.set("")
widget.focus_set()
return False
widget.configure(bg = '#ff8080')

if cr >= (maxCr * 1.01) and int(cr * 0.7) > avgCr:
widget.bell()
ok = mbox.askokcancel(
"Very high price",
"The price you entered is very high.\n"
"\n"
"Your input was..: {}\n"
"Previous highest: {}\n"
"\n"
"Is it correct?".format(
cr, maxCr,
))
if not ok:
widget.val.set("")
widget.focus_set()
return False
widget.configure(bg = '#8080ff')

return True


def validate(self, widget):
""" For checking the contents of a widget. """
item, row, pos = widget.item, widget.row, widget.pos
Expand All @@ -232,6 +276,11 @@ def validate(self, widget):
)
return False

# is it lower than the value?
payStats = self.payStats[item.ID]
if not self.checkValueAgainstStats(widget, payStats):
return False

if pos <= 1:
if not value or value == "0":
widget.val.set("")
Expand All @@ -258,11 +307,15 @@ def validate(self, widget):
)
return False

askStats = self.askStats[item.ID]
if not self.checkValueAgainstStats(widget, askStats):
return False

# https://forums.frontier.co.uk/showthread.php?t=34986&p=1162429&viewfull=1#post1162429
# It seems that stations usually pay within 25% of the
# asking price as a buy-back price. If the user gives
# us something out of those bounds, check with them.
if paying < int(asking * 0.72) or \
if paying < int(asking * 0.70) or \
paying < asking - 250:
widget.bell()
ok = mbox.askokcancel(
Expand Down Expand Up @@ -456,6 +509,8 @@ def addHeading(text):
addHeading("Asking")
addHeading("Demand")
addHeading("Stock")
addHeading("AvgPay")
addHeading("AvgAsk")
self.endRow()


Expand All @@ -467,11 +522,16 @@ def addItemRow(self, ID, catID, itemName, paying, asking, demand, stock):
self.items[itemName] = item
self.itemList.append(item)

payStats = self.payStats[item.ID]
askStats = self.askStats[item.ID]

self.addLabel(item.name.upper())
self.addInput(item, paying, row)
self.addInput(item, asking, row)
self.addInput(item, demand, row)
self.addInput(item, stock, row)
self.addLabel(payStats[1])
self.addLabel(askStats[1])

self.itemDisplays.append(row)

Expand Down Expand Up @@ -500,6 +560,27 @@ def createWidgets(self):
)
self.newStation = False if int(cur.fetchone()[0]) else True

cur.execute("""
SELECT item_id, MIN(price), AVG(price), MAX(price)
FROM StationBuying
WHERE station_id != ?
GROUP BY 1
""", [station.ID])
self.payStats = {
ID: [ minCr, int(avgCr), maxCr ]
for ID, minCr, avgCr, maxCr in cur
}
cur.execute("""
SELECT item_id, MIN(price), AVG(price), MAX(price)
FROM StationSelling
WHERE station_id != ?
GROUP BY 1
""", [station.ID])
self.askStats = {
ID: [ minCr, int(avgCr), maxCr ]
for ID, minCr, avgCr, maxCr in cur
}

if self.newStation and not tdenv.all:
def splashScreen():
mbox.showinfo(
Expand Down
1 change: 1 addition & 0 deletions corrections.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,7 @@
"ONGKAMPAN/PATTERSON STATION:274": DELETED,
"ZETA AQUILAE/OEFELIEN": DELETED,
"ZETA AQUILAE/JULIAN GATEWAY": DELETED,
"GROOMBRIDGE 1618/FRANKUN RING": "Franklin Ring",

#ADD_STATIONS_HERE
}
Expand Down
Loading

0 comments on commit f8f9b51

Please sign in to comment.