0ptr/nullptr/models/ship.py

192 lines
5.3 KiB
Python

from .base import Base
from time import time, strftime
from nullptr.util import *
from nullptr.models import Waypoint
import os
class Ship(Base):
def define(self):
self.cargo:dict = {}
self.mission_state:dict = {}
self.status:str = ''
self.cargo_capacity:int = 0
self.cargo_units:int = 0
self.location = None
self.cooldown:int = 0
self.arrival:int = 0
self.fuel_current:int = 0
self.fuel_capacity:int = 0
self.mission:str = None
self.mission_status:str = 'init'
self.role = None
self.crew = None
self.frame = ''
self.speed = "CRUISE"
self._log_file = None
self._log_level = 5
def log(self, m, l=3):
if m is None: return
if type(m) != str:
m = pretty(m)
if self._log_file is None:
fn = os.path.join(self.store.data_dir, f'{self.symbol}.{self.ext()}.log')
self._log_file = open(fn, 'a')
ts = strftime('%Y%m%d %H%M%S')
sts = strftime('%H%M%S')
m = m.strip()
self._log_file.write(f'{ts} {m}\n')
self._log_file.flush()
if l <= self._log_level:
print(f'{self} {sts} {m}')
@classmethod
def ext(self):
return 'shp'
def range(self):
if self.fuel_capacity == 0:
return 100000
return self.fuel_capacity
def update(self, d):
self.seta('status', d, 'nav.status')
self.seta('speed', d, "nav.flightMode")
self.seta('frame', d, 'frame.name')
getter = self.store.getter(Waypoint, create=True)
self.seta('location', d, 'nav.waypointSymbol', interp=getter)
self.seta('cargo_capacity', d, 'cargo.capacity')
self.seta('cargo_units', d, 'cargo.units')
self.seta('fuel_capacity', d, 'fuel.capacity')
self.seta('fuel_current', d,'fuel.current')
cargo = sg(d, 'cargo.inventory')
if cargo is not None:
self.load_cargo(cargo)
self.seta('cooldown', d, 'cooldown.expiration', parse_timestamp)
self.seta('arrival', d, 'nav.route.arrival', parse_timestamp)
def tick(self):
if self.status == 'IN_TRANSIT' and self.arrival < time():
self.status = 'IN_ORBIT'
def is_cooldown(self):
return self.cooldown > time()
def is_travelling(self):
return self.status == 'IN_TRANSIT'
def set_mission_state(self, nm, val):
self.mission_state[nm] = val
self.store.dirty(self)
def get_cargo(self, typ):
if typ not in self.cargo:
return 0
return self.cargo[typ]
def take_cargo(self, typ, amt):
if typ not in self.cargo:
return
if self.cargo[typ] <= amt:
del self.cargo[typ]
else:
self.cargo[typ] -= amt
self.cargo_units = sum(self.cargo.values())
def put_cargo(self, typ, amt):
if typ not in self.cargo:
self.cargo[typ] = amt
else:
self.cargo[typ] += amt
self.cargo_units = sum(self.cargo.values())
def load_cargo(self, cargo):
result = {}
total = 0
for i in cargo:
symbol = must_get(i, 'symbol')
units = must_get(i, 'units')
result[symbol] = units
total += units
self.cargo_units = total
self.cargo = result
def deliverable_cargo(self, contract):
result = []
if contract is None:
return result
for d in contract.deliveries:
if self.get_cargo(d['trade_symbol']) > 0:
result.append(d['trade_symbol'])
return result
def nondeliverable_cargo(self, contract):
cargo = self.cargo.keys()
deliveries = [d['trade_symbol'] for d in contract.deliveries]
garbage = [c for c in cargo if c not in deliveries]
return garbage
def cargo_space(self):
return self.cargo_capacity - self.cargo_units
def update_timers(self):
if self.status == 'IN_TRANSIT' and self.arrival < time():
self.status = 'IN_ORBIT'
def f(self, detail=1):
self.update_timers()
arrival = int(self.arrival - time())
cooldown = int(self.cooldown - time())
role = self.role
if role is None:
role = 'none'
crew = 'none'
if self.crew is not None:
crew = self.crew.symbol
mstatus = self.mission_status
if mstatus == 'error':
mstatus = mstatus.upper()
if mstatus is None:
mstatus = 'none'
status = self.status.lower()
if status.startswith('in_'):
status = status[3:]
if detail < 2:
r = self.symbol
elif detail == 2:
symbol = self.symbol.split('-')[1]
r = f'{symbol:<2} {role:7} {mstatus:8} {str(self.location):11}'
if self.is_travelling():
r += f' [A: {arrival}]'
if self.is_cooldown():
r += f' [C: {cooldown}]'
else:
r = f'== {self.symbol} {self.frame} ==\n'
r += f'Role: {crew} / {role}\n'
r += f'Mission: {self.mission} ({mstatus})\n'
for k, v in self.mission_state.items():
if type(v) == list:
v = f'[{len(v)} items]'
r += f' {k}: {v}\n'
adj = 'to' if self.status == 'IN_TRANSIT' else 'at'
r += f'Status {self.status} {adj} {self.location}\n'
r += f'Fuel: {self.fuel_current}/{self.fuel_capacity}\n'
r += f'Speed: {self.speed}\n'
r += f'Cargo: {self.cargo_units}/{self.cargo_capacity}\n'
for res, u in self.cargo.items():
r += f' {res}: {u}\n'
if self.is_travelling():
r += f'Arrival: {arrival} seconds\n'
if self.is_cooldown():
r += f'Cooldown: {cooldown} seconds \n'
return r