rat.ts 2.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273
  1. import {cachedFetchJSON} from './cache';
  2. render();
  3. async function render(): Promise<void> {
  4. const loader = document.querySelector('#loader') as HTMLElement;
  5. loader.style.display = 'block';
  6. try {
  7. await _render();
  8. } catch (e) {
  9. console.error(e);
  10. }
  11. loader.style.display = 'none';
  12. }
  13. async function _render(): Promise<void> {
  14. const allRecipes: readonly RecipeFull[] = await cachedFetchJSON('https://api.prunplanner.org/data/recipes/');
  15. const cols = ratRecipes(allRecipes);
  16. document.querySelector('#cols')!.innerHTML = cols.map((col) =>
  17. `<div class="col">${Array.from(col).map((input) => `<div class="mat">${input}</div>`).join('')}</div>`
  18. ).join('');
  19. }
  20. function ratRecipes(allRecipes: readonly RecipeFull[]): Set<string>[] {
  21. const ratRecipes = allRecipes.filter((recipe) =>
  22. recipe.building_ticker === 'FP' && recipe.outputs.length === 1 && recipe.outputs[0].material_ticker === 'RAT');
  23. const recipes: Recipe[] = ratRecipes.map((recipe) => {
  24. return {
  25. inputs: recipe.inputs.map((input) => input.material_ticker),
  26. catalogued: false,
  27. };
  28. });
  29. const cols: Set<string>[] = [new Set(), new Set(), new Set()];
  30. const seenInputs = new Set<string>();
  31. recipes[0].inputs.forEach((input, index) => {
  32. cols[index].add(input);
  33. seenInputs.add(input);
  34. });
  35. recipes[0].catalogued = true;
  36. let allCatalogued;
  37. do {
  38. allCatalogued = true;
  39. for (const recipe of recipes) {
  40. if (recipe.catalogued) continue;
  41. const inputs = new Set(recipe.inputs);
  42. const newInputs = inputs.difference(seenInputs);
  43. if (newInputs.size === 1) {
  44. const newInput = newInputs.keys().next().value!;
  45. const seenCols = Array.from(inputs.difference(newInputs)).map((oldInput) =>
  46. cols.findIndex((col) => col.has(oldInput)));
  47. const newCol = new Set([0, 1, 2]).difference(new Set(seenCols)).keys().next().value!;
  48. cols[newCol].add(newInput);
  49. seenInputs.add(newInput);
  50. recipe.catalogued = true;
  51. } else if (newInputs.size === 0)
  52. recipe.catalogued = true;
  53. else
  54. allCatalogued = false;
  55. }
  56. } while (!allCatalogued);
  57. return cols;
  58. }
  59. interface RecipeFull {
  60. building_ticker: string;
  61. inputs: Array<{material_ticker: string}>
  62. outputs: Array<{material_ticker: string}>
  63. }
  64. interface Recipe {
  65. readonly inputs: Array<string>
  66. catalogued: boolean;
  67. }