Explorar o código

production: identify extractable resources, hardcode recipes

raylu hai 1 mes
pai
achega
2c5c7759b5
Modificáronse 1 ficheiros con 39 adicións e 10 borrados
  1. 39 10
      ts/production.ts

+ 39 - 10
ts/production.ts

@@ -38,7 +38,7 @@ async function render() {
 }
 
 async function _render() {
-	const [allPrices, recipes, buildingList, storage] = await Promise.all([
+	const [allPrices, {recipes, extractables}, buildingList, storage] = await Promise.all([
 		cachedFetchJSON('https://refined-prun.github.io/refined-prices/all.json') as Promise<RawPrice[]>,
 		recipeForMats(),
 		cachedFetchJSON('https://api.prunplanner.org/data/buildings/') as Promise<Building[]>,
@@ -54,7 +54,7 @@ async function _render() {
 	const analysisNodes: AnalysisNode[] = [];
 	let cost = 0;
 	for (const [mat, amount] of Object.entries(blueprint)) {
-		const node = analyzeMat(mat, amount, production, extract, buy, prices, recipes, storage);
+		const node = analyzeMat(mat, amount, production, extract, buy, prices, recipes, extractables, storage);
 		cost += node.cost;
 		analysisNodes.push(node);
 	}
@@ -99,11 +99,33 @@ function renderMatList(header: string, mats: Record<string, number>, storage: Re
 	return section;
 }
 
-async function recipeForMats(): Promise<Record<string, Recipe>> {
-	const allRecipes: Recipe[] = await cachedFetchJSON('https://api.prunplanner.org/data/recipes/');
+async function recipeForMats(): Promise<{recipes: Record<string, Recipe>, extractables: Set<string>}> {
+	const [allRecipes, materials]: [Recipe[], Material[]] = await Promise.all([
+		cachedFetchJSON('https://api.prunplanner.org/data/recipes/'),
+		cachedFetchJSON('https://api.prunplanner.org/data/materials/'),
+	]);
+
+	const extractables = new Set(materials.filter(
+		(m) => ['ores', 'minerals', 'liquids', 'gases'].includes(m.category_name)).map((m) => m.ticker));
+
+	const chosenRecipes: Record<string, string> = {
+		'AL': '6xALO 1xO 1xC 1xFLX=>4xAL',
+		'C': '4xHCP=>4xC',
+		'FE': '6xFEO 1xC 1xO 1xFLX=>4xFE',
+		'GL': '2xSIO 1xNA 1xSEN=>10xGL',
+		'HCP': '14xH2O 1xNS=>8xHCP',
+		'RE': '8xREO 1xC 1xO 1xFLX=>5xRE',
+		'RG': '10xGL 15xPG 1xSEN=>10xRG',
+		'SI': '3xSIO 1xC 1xO 1xFLX=>1xSI',
+	}
+
 	const matRecipes: Record<string, Recipe[]> = {}; // all ways to make a mat
 	for (const recipe of allRecipes)
 		for (const output of recipe.outputs) {
+			if (extractables.has(output.material_ticker))
+				continue;
+			if (chosenRecipes[output.material_ticker] && recipe.recipe_name != chosenRecipes[output.material_ticker])
+				continue;
 			const recipes = matRecipes[output.material_ticker];
 			if (recipes)
 				recipes.push(recipe);
@@ -111,15 +133,15 @@ async function recipeForMats(): Promise<Record<string, Recipe>> {
 				matRecipes[output.material_ticker] = [recipe];
 		}
 
-	const matRecipe: Record<string, Recipe> = {}; // mats for which there's only one recipe to make
+	const matRecipe: Record<string, Recipe> = {};
 	for (const [mat, recipes] of Object.entries(matRecipes))
 		if (recipes.length === 1)
 			matRecipe[mat] = recipes[0];
-	return matRecipe;
+	return {recipes: matRecipe, extractables};
 }
 
 function analyzeMat(mat: string, amount: number, production: Production, extract: Record<string, number>, buy: Record<string, number>,
-		prices: Record<string, RawPrice>, recipes: Record<string, Recipe>, storage: Record<string, number>): AnalysisNode {
+		prices: Record<string, RawPrice>, recipes: Record<string, Recipe>, extractables: Set<string>, storage: Record<string, number>): AnalysisNode {
 	const price = prices[mat];
 	if (!price)
 		throw new Error(`missing price for ${mat}`);
@@ -141,11 +163,13 @@ function analyzeMat(mat: string, amount: number, production: Production, extract
 		};
 	}
 
-	const recipe = recipes[mat];
-	if (!recipe) {
+	if (extractables.has(mat)) {
 		extract[mat] = (extract[mat] ?? 0) + amount;
 		return {ticker: mat, amount, inStorage, acquisition: `extract`, children: [], cost: 0};
 	}
+	const recipe = recipes[mat];
+	if (!recipe)
+		throw new Error(`no recipe for ${mat}`);
 
 	const building = recipe.building_ticker;
 	if (!production[building])
@@ -158,7 +182,7 @@ function analyzeMat(mat: string, amount: number, production: Production, extract
 	const children: AnalysisNode[] = [];
 	for (const inputMat of recipe.inputs) {
 		const inputAmount = inputMat.material_amount * amount / recipe.outputs[0].material_amount;
-		const node = analyzeMat(inputMat.material_ticker, inputAmount, production, extract, buy, prices, recipes, storage);
+		const node = analyzeMat(inputMat.material_ticker, inputAmount, production, extract, buy, prices, recipes, extractables, storage);
 		totalCost += node.cost;
 		children.push(node);
 	}
@@ -395,6 +419,11 @@ interface RecipeMat {
 	material_amount: number
 }
 
+interface Material {
+	ticker: string
+	category_name: string
+}
+
 interface RawPrice {
 	MaterialTicker: string
 	ExchangeCode: string