main.ts 2.0 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768
  1. interface Recipe {
  2. RecipeId: string;
  3. BuildingTicker: string;
  4. RecipeName: string;
  5. TimeMs: number;
  6. Inputs: Array<{Ticker: string; Amount: number}>;
  7. Outputs: Array<{Ticker: string; Amount: number}>;
  8. }
  9. interface Price {
  10. MaterialTicker: string;
  11. ExchangeCode: string;
  12. PriceAverage: number;
  13. }
  14. async function fetchData(): Promise<{recipes: Recipe[]; prices: Price[]}> {
  15. const [recipesResponse, exchangesResponse] = await Promise.all([
  16. fetch('https://api.prunplanner.org/data/recipes'),
  17. fetch('https://api.prunplanner.org/data/exchanges'),
  18. ]);
  19. const [recipes, prices] = await Promise.all([
  20. recipesResponse.json(),
  21. exchangesResponse.json(),
  22. ]);
  23. return {recipes, prices};
  24. }
  25. function render({recipes, prices}: {recipes: Recipe[], prices: Price[]}) {
  26. const priceMap = new Map<string, number>();
  27. for (const price of prices)
  28. if (price.ExchangeCode == 'PP7D_IC1')
  29. priceMap.set(price.MaterialTicker, price.PriceAverage);
  30. const fmt = new Intl.NumberFormat(undefined, {maximumFractionDigits: 2});
  31. const tbody = document.querySelector('tbody') as HTMLTableSectionElement;
  32. tbody.innerHTML = '';
  33. for (const recipe of recipes) {
  34. if (recipe.BuildingTicker !== 'FRM')
  35. continue;
  36. const runsPerDay = 1000 * 60 * 60 * 24 / recipe.TimeMs;
  37. const revenuePerRun = recipe.Outputs.reduce((sum, output) => {
  38. const price = priceMap.get(output.Ticker);
  39. if (price === undefined)
  40. throw new Error(`missing price for ${output.Ticker}`);
  41. return sum + price * output.Amount;
  42. }, 0);
  43. const costPerRun = recipe.Inputs.reduce((sum, input) => {
  44. const price = priceMap.get(input.Ticker);
  45. if (price === undefined)
  46. throw new Error(`missing price for ${input.Ticker}`);
  47. return sum + price * input.Amount;
  48. }, 0);
  49. const row = document.createElement('tr');
  50. row.innerHTML = `
  51. <td>${recipe.RecipeName}</td>
  52. <td>${fmt.format(revenuePerRun * runsPerDay)}</td>
  53. <td>${fmt.format(costPerRun * runsPerDay)}</td>
  54. <td>${fmt.format((revenuePerRun - costPerRun) * runsPerDay)}</td>
  55. `;
  56. tbody.appendChild(row);
  57. }
  58. }
  59. fetchData().then(render);