| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596 |
- import {cachedFetchJSON} from './cache';
- render();
- async function render(): Promise<void> {
- const loader = document.querySelector('#loader') as HTMLElement;
- loader.style.display = 'block';
- try {
- await _render();
- } catch (e) {
- console.error(e);
- }
- loader.style.display = 'none';
- }
- async function _render(): Promise<void> {
- const allRecipes: readonly RecipeFull[] = await cachedFetchJSON('https://api.prunplanner.org/data/recipes/');
- const cols = ratRecipes(allRecipes);
- const frm = buildingOutputs(allRecipes, 'FRM');
- const hyf = buildingOutputs(allRecipes, 'HYF');
- document.querySelector('#cols')!.append(...cols.map((col) => {
- const colEl = document.createElement('div');
- colEl.className = 'col';
- colEl.append(...Array.from(col).map((input) => {
- const matEl = document.createElement('div');
- matEl.className = 'mat';
- if (frm.has(input))
- matEl.classList.add('frm');
- if (hyf.has(input))
- matEl.classList.add('hyf');
- matEl.textContent = input;
- return matEl;
- }));
- return colEl;
- }));
- }
- function ratRecipes(allRecipes: readonly RecipeFull[]): Set<string>[] {
- const ratRecipes = allRecipes.filter((recipe) =>
- recipe.building_ticker === 'FP' && recipe.outputs.length === 1 && recipe.outputs[0].material_ticker === 'RAT');
- const recipes: Recipe[] = ratRecipes.map((recipe) => {
- return {
- inputs: recipe.inputs.map((input) => input.material_ticker),
- catalogued: false,
- };
- });
- const cols: Set<string>[] = [new Set(), new Set(), new Set()];
- const seenInputs = new Set<string>();
- recipes[0].inputs.forEach((input, index) => {
- cols[index].add(input);
- seenInputs.add(input);
- });
- recipes[0].catalogued = true;
- let allCatalogued;
- do {
- allCatalogued = true;
- for (const recipe of recipes) {
- if (recipe.catalogued) continue;
- const inputs = new Set(recipe.inputs);
- const newInputs = inputs.difference(seenInputs);
- if (newInputs.size === 1) {
- const newInput = newInputs.keys().next().value!;
- const seenCols = Array.from(inputs.difference(newInputs)).map((oldInput) =>
- cols.findIndex((col) => col.has(oldInput)));
- const newCol = new Set([0, 1, 2]).difference(new Set(seenCols)).keys().next().value!;
- cols[newCol].add(newInput);
- seenInputs.add(newInput);
- recipe.catalogued = true;
- } else if (newInputs.size === 0)
- recipe.catalogued = true;
- else
- allCatalogued = false;
- }
- } while (!allCatalogued);
- return cols;
- }
- function buildingOutputs(allRecipes: readonly RecipeFull[], building: string): Set<string> {
- const outputs = new Set<string>();
- for (const recipe of allRecipes)
- if (recipe.building_ticker === building)
- for (const output of recipe.outputs)
- outputs.add(output.material_ticker);
- return outputs;
- }
- interface RecipeFull {
- building_ticker: string;
- inputs: Array<{material_ticker: string}>
- outputs: Array<{material_ticker: string}>
- }
- interface Recipe {
- readonly inputs: Array<string>
- catalogued: boolean;
- }
|