Prechádzať zdrojové kódy

buy: consider the entire empire's consumption

don't consider consuming bases' inventory for "want"
consider other bases' production for "want"
raylu 5 dní pred
rodič
commit
39df46446d
3 zmenil súbory, kde vykonal 36 pridanie a 45 odobranie
  1. 11 3
      buy.py
  2. 11 10
      supply.py
  3. 14 32
      ts/buy.ts

+ 11 - 3
buy.py

@@ -17,6 +17,7 @@ if typing.TYPE_CHECKING:
 
 
 def main() -> None:
 def main() -> None:
 	days = int(sys.argv[1])
 	days = int(sys.argv[1])
+
 	with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
 	with concurrent.futures.ThreadPoolExecutor(max_workers=2) as executor:
 		futures = [
 		futures = [
 			executor.submit(get_raw_prices),
 			executor.submit(get_raw_prices),
@@ -80,12 +81,19 @@ def get_raw_prices() -> typing.Mapping[str, market.RawPrice]:
 def get_total_buy(days: int) -> typing.Mapping[str, int]:
 def get_total_buy(days: int) -> typing.Mapping[str, int]:
 	planets = [supply.Planet(fio_burn) for fio_burn in cache.get('https://rest.fnar.net/fioweb/burn/user/' + config.username,
 	planets = [supply.Planet(fio_burn) for fio_burn in cache.get('https://rest.fnar.net/fioweb/burn/user/' + config.username,
 			headers={'Authorization': config.fio_api_key})]
 			headers={'Authorization': config.fio_api_key})]
-	buy: dict[str, int] = collections.defaultdict(int)
+
+	total_consumption: dict[str, float] = collections.defaultdict(float)
 	for planet in planets:
 	for planet in planets:
 		supply_config = config.supply_config(planet.name)
 		supply_config = config.supply_config(planet.name)
-		for mat, amount in planet.supply_for_days(days).items():
+		for mat, amount in planet.net_consumption.items():
 			if mat not in supply_config.ignore_materials:
 			if mat not in supply_config.ignore_materials:
-				buy[mat] += amount
+				total_consumption[mat] += amount
+
+	buy: dict[str, int] = collections.defaultdict(int)
+	for mat, consumption in total_consumption.items():
+		if consumption <= 0:
+			continue
+		buy[mat] = round(consumption * days)
 	return buy
 	return buy
 
 
 def get_planet_exports_and_ship_storage() -> typing.Mapping[str, int]:
 def get_planet_exports_and_ship_storage() -> typing.Mapping[str, int]:

+ 11 - 10
supply.py

@@ -105,6 +105,8 @@ def calculate_optimal(planets: typing.Sequence[Planet], materials: typing.Mappin
 	for planet in planets:
 	for planet in planets:
 		vol_per_day = weight_per_day = 0
 		vol_per_day = weight_per_day = 0
 		for ticker, consumption in planet.net_consumption.items():
 		for ticker, consumption in planet.net_consumption.items():
+			if consumption <= 0:
+				continue
 			vol_per_day += materials[ticker]['Volume'] * consumption
 			vol_per_day += materials[ticker]['Volume'] * consumption
 			weight_per_day += materials[ticker]['Weight'] * consumption
 			weight_per_day += materials[ticker]['Weight'] * consumption
 			days = planet.inventory.get(ticker, 0) / consumption
 			days = planet.inventory.get(ticker, 0) / consumption
@@ -149,6 +151,8 @@ def calculate_optimal(planets: typing.Sequence[Planet], materials: typing.Mappin
 		supply_config = config.supply_config(planet.name)
 		supply_config = config.supply_config(planet.name)
 		planet_buy = optimal[planet.name]
 		planet_buy = optimal[planet.name]
 		for ticker, consumption in planet.net_consumption.items():
 		for ticker, consumption in planet.net_consumption.items():
+			if consumption <= 0:
+				continue
 			avail = planet.inventory.get(ticker, 0)
 			avail = planet.inventory.get(ticker, 0)
 			days = avail / consumption
 			days = avail / consumption
 			print(f'{ticker:>3}: {avail:5d} ({consumption:8.2f}/d) {days:5.1f} d', end='')
 			print(f'{ticker:>3}: {avail:5d} ({consumption:8.2f}/d) {days:5.1f} d', end='')
@@ -230,18 +234,13 @@ class Planet:
 		self.name = fio_burn['PlanetName'] or fio_burn['PlanetNaturalId']
 		self.name = fio_burn['PlanetName'] or fio_burn['PlanetNaturalId']
 		self.inventory = {item['MaterialTicker']: item['MaterialAmount'] for item in fio_burn['Inventory']}
 		self.inventory = {item['MaterialTicker']: item['MaterialAmount'] for item in fio_burn['Inventory']}
 
 
-		# producing any amount (including less than consumption)
 		self.net_consumption = {}
 		self.net_consumption = {}
-		for c in fio_burn['OrderConsumption'] + fio_burn['WorkforceConsumption']:
-			ticker = c['MaterialTicker']
-			self.net_consumption[ticker] = self.net_consumption.get(ticker, 0) + c['DailyAmount']
+		for item in fio_burn['OrderConsumption'] + fio_burn['WorkforceConsumption']:
+			ticker = item['MaterialTicker']
+			self.net_consumption[ticker] = self.net_consumption.get(ticker, 0) + item['DailyAmount']
 		for item in fio_burn['OrderProduction']:
 		for item in fio_burn['OrderProduction']:
-			if consumption := self.net_consumption.get(item['MaterialTicker']):
-				consumption -= item['DailyAmount']
-				if consumption <= 0:
-					del self.net_consumption[item['MaterialTicker']]
-				else:
-					self.net_consumption[item['MaterialTicker']] = consumption
+			ticker = item['MaterialTicker']
+			self.net_consumption[ticker] = self.net_consumption.get(ticker, 0) - item['DailyAmount']
 
 
 		# producing more than consumption
 		# producing more than consumption
 		self.exporting = set()
 		self.exporting = set()
@@ -252,6 +251,8 @@ class Planet:
 	def supply_for_days(self, target_days: float) -> dict[str, int]:
 	def supply_for_days(self, target_days: float) -> dict[str, int]:
 		buy: dict[str, int] = {}
 		buy: dict[str, int] = {}
 		for ticker, consumption in self.net_consumption.items():
 		for ticker, consumption in self.net_consumption.items():
+			if consumption <= 0:
+				continue
 			avail = self.inventory.get(ticker, 0)
 			avail = self.inventory.get(ticker, 0)
 			days = avail / consumption
 			days = avail / consumption
 			to_buy = 0
 			to_buy = 0

+ 14 - 32
ts/buy.ts

@@ -65,16 +65,22 @@ async function calcForCX(username: string, apiKey: string, supplyForDays: number
 	const prices = await getPrices(cx);
 	const prices = await getPrices(cx);
 	const avail = await warehouseInventory(username, apiKey, warehouseNames[cx]);
 	const avail = await warehouseInventory(username, apiKey, warehouseNames[cx]);
 	const {bids, orders} = await getBids(username, apiKey, cx);
 	const {bids, orders} = await getBids(username, apiKey, cx);
-	const buy = new Map<string, number>();
+
+	// what do we need and have
+	const totalConsumption = new Map<string, number>();
 	for (const planet of planets) {
 	for (const planet of planets) {
-		for (const [mat, amount] of planet.supplyForDays(supplyForDays))
-			buy.set(mat, (buy.get(mat) ?? 0) + amount);
+		for (const [ticker, consumption] of planet.netConsumption)
+			totalConsumption.set(ticker, (totalConsumption.get(ticker) ?? 0) + consumption);
 		for (const mat of planet.exporting) {
 		for (const mat of planet.exporting) {
 			const planetExport = planet.inventory.get(mat);
 			const planetExport = planet.inventory.get(mat);
 			if (planetExport)
 			if (planetExport)
 				avail.set(mat, (avail.get(mat) ?? 0) + planetExport);
 				avail.set(mat, (avail.get(mat) ?? 0) + planetExport);
 		}
 		}
 	}
 	}
+	const buy = new Map<string, number>();
+	for (const [mat, amount] of totalConsumption)
+		if (amount > 0)
+			buy.set(mat, (buy.get(mat) ?? 0) + amount * supplyForDays);
 
 
 	// what's left to buy
 	// what's left to buy
 	const materials: Material[] = [];
 	const materials: Material[] = [];
@@ -215,7 +221,7 @@ class Planet {
 	id: string;
 	id: string;
 	name: string;
 	name: string;
 	inventory: Map<string, number>;
 	inventory: Map<string, number>;
-	netConsumption: Amount[];
+	netConsumption: Map<string, number>;
 	exporting: Set<string>; // producing more than consumption
 	exporting: Set<string>; // producing more than consumption
 
 
 	constructor(fioBurn: FIOBurn) {
 	constructor(fioBurn: FIOBurn) {
@@ -225,42 +231,19 @@ class Planet {
 		for (const item of fioBurn.Inventory)
 		for (const item of fioBurn.Inventory)
 			this.inventory.set(item.MaterialTicker, item.MaterialAmount);
 			this.inventory.set(item.MaterialTicker, item.MaterialAmount);
 
 
-		const producing = new Map<string, Amount>();
+		this.netConsumption = new Map<string, number>();
 		for (const item of fioBurn.OrderProduction)
 		for (const item of fioBurn.OrderProduction)
-			producing.set(item.MaterialTicker, item);
+			this.netConsumption.set(item.MaterialTicker, -item.DailyAmount);
 
 
-		this.netConsumption = [];
 		for (const c of [...fioBurn.OrderConsumption, ...fioBurn.WorkforceConsumption]) {
 		for (const c of [...fioBurn.OrderConsumption, ...fioBurn.WorkforceConsumption]) {
-			let net = c.DailyAmount;
-			const production = producing.get(c.MaterialTicker);
-			if (production) {
-				net -= production.DailyAmount;
-				if (net < 0)
-					continue;
-			}
-			c.netConsumption = net;
-			this.netConsumption.push(c);
+			this.netConsumption.set(c.MaterialTicker, (this.netConsumption.get(c.MaterialTicker) ?? 0) + c.DailyAmount);
 		}
 		}
 
 
-		const consuming = new Set(this.netConsumption.map(item => item.MaterialTicker));
 		this.exporting = new Set<string>();
 		this.exporting = new Set<string>();
 		for (const item of fioBurn.OrderProduction)
 		for (const item of fioBurn.OrderProduction)
-			if (!consuming.has(item.MaterialTicker))
+			if ((this.netConsumption.get(item.MaterialTicker) ?? 0) < 0)
 				this.exporting.add(item.MaterialTicker);
 				this.exporting.add(item.MaterialTicker);
 	}
 	}
-
-	supplyForDays(targetDays: number): Map<string, number> {
-		const buy = new Map<string, number>();
-		for (const consumption of this.netConsumption) {
-			const ticker = consumption.MaterialTicker;
-			const avail = this.inventory.get(ticker) ?? 0;
-			const dailyConsumption = consumption.netConsumption!;
-			const days = avail / dailyConsumption;
-			if (days < targetDays)
-				buy.set(ticker, Math.ceil((targetDays - days) * dailyConsumption));
-		}
-		return buy;
-	}
 }
 }
 
 
 interface Material {
 interface Material {
@@ -310,7 +293,6 @@ interface Warehouse {
 interface Amount {
 interface Amount {
 	MaterialTicker: string;
 	MaterialTicker: string;
 	DailyAmount: number;
 	DailyAmount: number;
-	netConsumption?: number;
 }
 }
 
 
 interface FIOBurn {
 interface FIOBurn {