historical marketprices

api.py
This commit is contained in:
Richard 2024-01-13 11:27:32 +01:00
parent 08ab3f0999
commit 188ef320cc
6 changed files with 72 additions and 18 deletions

View File

@ -3,6 +3,7 @@ from nullptr.models.jumpgate import Jumpgate
from nullptr.models.system import System from nullptr.models.system import System
from nullptr.models.waypoint import Waypoint from nullptr.models.waypoint import Waypoint
from dataclasses import dataclass from dataclasses import dataclass
from nullptr.util import pprint
from copy import copy from copy import copy
class AnalyzerException(Exception): class AnalyzerException(Exception):
@ -109,6 +110,7 @@ class Analyzer:
mkts = [m.waypoint for m in self.store.all_members(orig.system, Marketplace)] mkts = [m.waypoint for m in self.store.all_members(orig.system, Marketplace)]
cur = orig cur = orig
if orig == to: if orig == to:
return [] return []
while cur != to: while cur != to:
best = cur best = cur
@ -157,8 +159,8 @@ class Analyzer:
prices[r] = [] prices[r] = []
prices[r].append({ prices[r].append({
'wp': m.waypoint, 'wp': m.waypoint,
'buy': p['buy'], 'buy': p.buy,
'sell': p['sell'] 'sell': p.sell
}) })
return prices return prices

View File

@ -121,6 +121,7 @@ class Api:
units = min(units, fuel_avail) units = min(units, fuel_avail)
data = {'fromCargo': from_cargo, 'units': units } data = {'fromCargo': from_cargo, 'units': units }
data = self.request('post', f'my/ships/{ship}/refuel', data) data = self.request('post', f'my/ships/{ship}/refuel', data)
self.log_transaction(data)
if from_cargo: if from_cargo:
boxes = ceil(float(units) / 100) boxes = ceil(float(units) / 100)
ship.take_cargo('FUEL', boxes) ship.take_cargo('FUEL', boxes)
@ -236,7 +237,18 @@ class Api:
result = self.store.update_list('Survey', mg(data, 'surveys')) result = self.store.update_list('Survey', mg(data, 'surveys'))
return result return result
######## Commerce ######### ######## Commerce #########
def log_transaction(self, data):
if not 'transaction' in data: return
typ = mg(data, 'transaction.tradeSymbol')
ppu = mg(data, 'transaction.pricePerUnit')
shipsym = mg(data, 'transaction.shipSymbol')
ship = self.store.get('Ship', shipsym)
units = mg(data, 'transaction.units')
act = mg(data,'transaction.type')
ship.log(f'{act} {units} of {typ} for {ppu} at {ship.location}')
def sell(self, ship, typ,units=None): def sell(self, ship, typ,units=None):
if units is None: if units is None:
units = ship.get_cargo(typ) units = ship.get_cargo(typ)
@ -245,7 +257,7 @@ class Api:
'units': units 'units': units
} }
data = self.request('post', f'my/ships/{ship}/sell', data) data = self.request('post', f'my/ships/{ship}/sell', data)
ship.log(f'sell {units} of {typ}') self.log_transaction(data)
if 'cargo' in data: if 'cargo' in data:
ship.update(data) ship.update(data)
if 'agent' in data: if 'agent' in data:
@ -258,7 +270,7 @@ class Api:
'units': amt 'units': amt
} }
data = self.request('post', f'my/ships/{ship}/purchase', data) data = self.request('post', f'my/ships/{ship}/purchase', data)
ship.log(f'buy {amt} of {typ} at {ship.location}') self.log_transaction(data)
if 'cargo' in data: if 'cargo' in data:
ship.update(data) ship.update(data)
if 'agent' in data: if 'agent' in data:

View File

@ -184,7 +184,7 @@ class Commander(CommandLine):
for w in r: for w in r:
wname = w.symbol.split('-')[2] wname = w.symbol.split('-')[2]
traits = ", ".join(w.traits()) traits = ", ".join(w.itraits())
typ = w.type[0] typ = w.type[0]
if typ not in ['F','J'] and len(traits) == 0: if typ not in ['F','J'] and len(traits) == 0:
continue continue
@ -542,3 +542,9 @@ class Commander(CommandLine):
pprint(prices[resource.upper()]) pprint(prices[resource.upper()])
else: else:
pprint(prices) pprint(prices)
def do_path(self, waypoint_str):
if not self.has_ship(): return
w = self.resolve('Waypoint', waypoint_str)
p = self.analyzer.find_nav_path(self.ship.location, w, self.ship.fuel_capacity)
pprint(p)

View File

@ -36,6 +36,9 @@ class Base:
def __getstate__(self): def __getstate__(self):
return {k:v for k,v in self.__dict__.items() if not k.startswith('_')} return {k:v for k,v in self.__dict__.items() if not k.startswith('_')}
def dirty(self):
self.store.dirty(self)
@classmethod @classmethod
def ext(cls): def ext(cls):
raise NotImplementedError('no ext') raise NotImplementedError('no ext')

View File

@ -2,9 +2,29 @@
from .base import Base from .base import Base
from time import time from time import time
from nullptr.util import * from nullptr.util import *
from dataclasses import field from dataclasses import field, dataclass
from nullptr.models import Waypoint from nullptr.models import Waypoint
from typing import List, Tuple
SUPPLY = ['SCARCE','LIMITED','MODERATE','HIGH','ABUNDANT']
ACTIVITY =['RESTRICTED','WEAK','GROWING','STRONG']
class MarketEntry:
buy: int
sell: int
volume: int
supply: int
activity: int
history: List[Tuple[int, int, int, int, int, int]] = []
def add(self, buy, sell, volume, supply, activity):
self.buy = buy
self.sell = sell
self.volume = volume
self.supply = supply
self.activity = activity
self.history.append((int(time()), buy, sell, volume, supply, activity))
class Marketplace(Base): class Marketplace(Base):
def define(self): def define(self):
self.imports:list = [] self.imports:list = []
@ -21,6 +41,21 @@ class Marketplace(Base):
def is_fuel(self): def is_fuel(self):
return self.imports + self.exports + self.exchange == ['FUEL'] return self.imports + self.exports + self.exchange == ['FUEL']
def record_prices(self, data):
for g in data:
symbol= mg(g, 'symbol')
if symbol in self.prices:
e = self.prices[symbol]
else:
e = self.prices[symbol] = MarketEntry()
buy = mg(g, 'purchasePrice')
sell = mg(g, 'sellPrice')
volume = mg(g, 'tradeVolumes')
supply = SUPPLY.index(mg(g, 'supply'))
activity = ACTIVITY.index(sg(g, 'activity','STRONG'))
e.add(buy, sell, volume, supply, activity)
self.dirty()
def update(self, d): def update(self, d):
self.setlst('imports', d, 'imports', 'symbol') self.setlst('imports', d, 'imports', 'symbol')
@ -28,16 +63,7 @@ class Marketplace(Base):
self.setlst('exchange', d, 'exchange', 'symbol') self.setlst('exchange', d, 'exchange', 'symbol')
if 'tradeGoods' in d: if 'tradeGoods' in d:
self.last_prices = time() self.last_prices = time()
prices = {} self.record_prices(mg(d, 'tradeGoods'))
for g in mg(d, 'tradeGoods'):
price = {}
symbol= mg(g, 'symbol')
price['symbol'] = symbol
price['buy'] = mg(g, 'purchasePrice')
price['sell'] = mg(g, 'sellPrice')
price['volume'] = mg(g, 'tradeVolume')
prices[symbol] = price
self.prices = prices
def buy_price(self, resource): def buy_price(self, resource):
if resource not in self.prices: if resource not in self.prices:

View File

@ -32,7 +32,7 @@ class Waypoint(Base):
def ext(self): def ext(self):
return 'way' return 'way'
def traits(self): def itraits(self):
traits = [] traits = []
if self.type == 'JUMP_GATE': if self.type == 'JUMP_GATE':
traits.append('JUMP') traits.append('JUMP')
@ -54,4 +54,9 @@ class Waypoint(Base):
if 'STRIPPED' in self.traits: if 'STRIPPED' in self.traits:
traits.append('STRIPPED') traits.append('STRIPPED')
return traits return traits
def f(self, detail=1):
r = self.symbol
if detail > 3:
r += f'\n{self.x} {self.y}'
return r