// src/main.ts async function fetchData() { const [buildingsResponse, recipesResponse, exchangesResponse] = await Promise.all([ fetch("https://api.prunplanner.org/data/buildings"), fetch("https://api.prunplanner.org/data/recipes"), fetch("https://api.prunplanner.org/data/exchanges") ]); const [buildings, recipes, prices] = await Promise.all([ buildingsResponse.json(), recipesResponse.json(), exchangesResponse.json() ]); return { buildings, recipes, prices }; } function render({ buildings, recipes, prices }) { const priceMap = new Map; for (const price of prices) if (price.ExchangeCode == "PP7D_IC1") priceMap.set(price.MaterialTicker, price); const buildingMap = new Map; for (const building of buildings) { const cost = building.BuildingCosts.reduce((sum, mat) => { const price = priceMap.get(mat.CommodityTicker); if (price === undefined) throw new Error(`missing price for ${mat.CommodityTicker}`); return sum + price.PriceAverage * mat.Amount; }, 0); buildingMap.set(building.Ticker, cost); } const profits = []; for (const recipe of recipes) { const runsPerDay = 1000 * 60 * 60 * 24 / recipe.TimeMs; if (recipe.Outputs.length !== 1) { console.warn(`${recipe.RecipeName} doesn't have 1 output`); continue; } const output = recipe.Outputs[0]; const outputPrice = priceMap.get(output.Ticker); if (outputPrice === undefined) throw new Error(`missing price for ${output.Ticker}`); const revenuePerRun = output.Amount * outputPrice.PriceAverage; const costPerRun = recipe.Inputs.reduce((sum, input) => { const price = priceMap.get(input.Ticker); if (price === undefined) throw new Error(`missing price for ${input.Ticker}`); return sum + price.PriceAverage * input.Amount; }, 0); const dailyProfit = (revenuePerRun - costPerRun) * runsPerDay; const buildingCost = buildingMap.get(recipe.BuildingTicker); if (buildingCost === undefined) throw new Error(`missing building cost for ${recipe.BuildingTicker}`); if (outputPrice.Traded === 0 || buildingCost > 1200000) continue; profits.push({ recipeName: recipe.RecipeName, dailyProfit, traded: outputPrice.Traded, priceAverage: outputPrice.PriceAverage, buildingCost }); } profits.sort((a, b) => b.dailyProfit - a.dailyProfit); const fmt = new Intl.NumberFormat(undefined, { maximumFractionDigits: 2 }); const tbody = document.querySelector("tbody"); tbody.innerHTML = ""; for (const profit of profits) { const row = document.createElement("tr"); row.innerHTML = ` ${profit.recipeName} ${fmt.format(profit.dailyProfit)} ${fmt.format(profit.traded * profit.priceAverage)} ${fmt.format(profit.traded)} ${fmt.format(profit.buildingCost)} `; tbody.appendChild(row); } } fetchData().then(render); //# debugId=5C43254EC8D8A7F364756E2164756E21