|
@@ -29,13 +29,6 @@ const blueprint = {
|
|
|
'CQM': 1,
|
|
'CQM': 1,
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-const shipbuilders = [
|
|
|
|
|
- 'CraftsmanThirteen',
|
|
|
|
|
- 'EvoV',
|
|
|
|
|
- 'MapReduce',
|
|
|
|
|
- 'SurvivorBob',
|
|
|
|
|
- 'TRUEnterprises',
|
|
|
|
|
-];
|
|
|
|
|
|
|
|
|
|
const main = document.querySelector('main.shipbuilding')!;
|
|
const main = document.querySelector('main.shipbuilding')!;
|
|
|
(async () => {
|
|
(async () => {
|
|
@@ -48,12 +41,10 @@ const main = document.querySelector('main.shipbuilding')!;
|
|
|
}
|
|
}
|
|
|
})();
|
|
})();
|
|
|
async function render() {
|
|
async function render() {
|
|
|
- const [allPrices, recipes, buildingList, knownCompanies, companyProductionById] = await Promise.all([
|
|
|
|
|
|
|
+ const [allPrices, recipes, buildingList] = await Promise.all([
|
|
|
cachedFetchJSON('https://refined-prun.github.io/refined-prices/all.json') as Promise<RawPrice[]>,
|
|
cachedFetchJSON('https://refined-prun.github.io/refined-prices/all.json') as Promise<RawPrice[]>,
|
|
|
recipeForMats(),
|
|
recipeForMats(),
|
|
|
cachedFetchJSON('https://api.prunplanner.org/data/buildings/') as Promise<Building[]>,
|
|
cachedFetchJSON('https://api.prunplanner.org/data/buildings/') as Promise<Building[]>,
|
|
|
- cachedFetchJSON('https://pmmg-products.github.io/reports/data/knownCompanies.json') as Promise<Record<string, {Username: string}>>,
|
|
|
|
|
- pmmgMonthlyReport(),
|
|
|
|
|
]);
|
|
]);
|
|
|
const prices = Object.fromEntries(allPrices.filter((price) => price.ExchangeCode === 'IC1')
|
|
const prices = Object.fromEntries(allPrices.filter((price) => price.ExchangeCode === 'IC1')
|
|
|
.map((price) => [price.MaterialTicker, price]));
|
|
.map((price) => [price.MaterialTicker, price]));
|
|
@@ -92,7 +83,6 @@ async function render() {
|
|
|
renderProduction(expertiseGroups, production, prices, recipes, buildings),
|
|
renderProduction(expertiseGroups, production, prices, recipes, buildings),
|
|
|
renderMatList('extract', extract),
|
|
renderMatList('extract', extract),
|
|
|
renderMatList('buy', buy),
|
|
renderMatList('buy', buy),
|
|
|
- renderShipbuilders(requiredMats, knownCompanies, companyProductionById),
|
|
|
|
|
);
|
|
);
|
|
|
}
|
|
}
|
|
|
|
|
|
|
@@ -106,59 +96,6 @@ function renderMatList(header: string, mats: Record<string, number>): HTMLElemen
|
|
|
return section;
|
|
return section;
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-async function pmmgMonthlyReport(): Promise<PMMGCompanyProduction> {
|
|
|
|
|
- const constants = await fetch('https://raw.githubusercontent.com/PMMG-Products/pmmg-products.github.io/main/reports/src/staticData/constants.ts')
|
|
|
|
|
- .then((res) => res.text());
|
|
|
|
|
- const match = constants.match(/export const months = \[(.*?)\];/s);
|
|
|
|
|
- if (!match)
|
|
|
|
|
- throw new Error('failed to parse PMMG months');
|
|
|
|
|
- const months = match[1].split(',').map((m) => m.trim().replace(/^"|"$/g, ''));
|
|
|
|
|
- const latestMonth = months.at(-1);
|
|
|
|
|
- if (!latestMonth)
|
|
|
|
|
- throw new Error('missing PMMG month');
|
|
|
|
|
- const report = await cachedFetchJSON(`https://pmmg-products.github.io/reports/data/company-data-${latestMonth}.json`);
|
|
|
|
|
- return report['individual'];
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
-function renderShipbuilders(requiredMats: Record<string, number>,
|
|
|
|
|
- knownCompanies: Record<string, {Username: string}>, companyProductionById: PMMGCompanyProduction): HTMLElement {
|
|
|
|
|
- const matTickers = Object.keys(requiredMats).sort();
|
|
|
|
|
- const shipbuilderSet = new Set(shipbuilders);
|
|
|
|
|
- const shipbuildersById: Record<string, string> = {};
|
|
|
|
|
- for (const [companyId, company] of Object.entries(knownCompanies))
|
|
|
|
|
- if (shipbuilderSet.has(company.Username))
|
|
|
|
|
- shipbuildersById[companyId] = company.Username;
|
|
|
|
|
-
|
|
|
|
|
- const missingShipbuilders = shipbuilders
|
|
|
|
|
- .filter((username) => !Object.values(shipbuildersById).includes(username));
|
|
|
|
|
- if (missingShipbuilders.length > 0)
|
|
|
|
|
- return element('h3', {textContent: `missing shipbuilders in PMMG report: ${missingShipbuilders.join(', ')}`});
|
|
|
|
|
-
|
|
|
|
|
- const section = element('section');
|
|
|
|
|
- section.append(element('h2', {textContent: 'shipbuilders'}));
|
|
|
|
|
-
|
|
|
|
|
- const table = element('table');
|
|
|
|
|
- const header = element('tr');
|
|
|
|
|
- header.append(element('th', {textContent: 'mat'}));
|
|
|
|
|
- header.append(element('th', {textContent: 'amount'}));
|
|
|
|
|
- for (const username of Object.values(shipbuildersById))
|
|
|
|
|
- header.append(element('th', {textContent: username}));
|
|
|
|
|
- table.append(header);
|
|
|
|
|
-
|
|
|
|
|
- for (const mat of matTickers) {
|
|
|
|
|
- const row = element('tr');
|
|
|
|
|
- row.append(element('td', {textContent: mat}));
|
|
|
|
|
- row.append(element('td', {textContent: formatAmount(requiredMats[mat])}));
|
|
|
|
|
- for (const companyId of Object.keys(shipbuildersById)) {
|
|
|
|
|
- const makes = mat in companyProductionById[companyId];
|
|
|
|
|
- row.append(element('td', {textContent: makes ? '' : 'x'}));
|
|
|
|
|
- }
|
|
|
|
|
- table.append(row);
|
|
|
|
|
- }
|
|
|
|
|
- section.append(table);
|
|
|
|
|
- return section;
|
|
|
|
|
-}
|
|
|
|
|
-
|
|
|
|
|
async function recipeForMats(): Promise<Record<string, Recipe>> {
|
|
async function recipeForMats(): Promise<Record<string, Recipe>> {
|
|
|
const allRecipes: Recipe[] = await cachedFetchJSON('https://api.prunplanner.org/data/recipes/');
|
|
const allRecipes: Recipe[] = await cachedFetchJSON('https://api.prunplanner.org/data/recipes/');
|
|
|
const matRecipes: Record<string, Recipe[]> = {}; // all ways to make a mat
|
|
const matRecipes: Record<string, Recipe[]> = {}; // all ways to make a mat
|
|
@@ -404,5 +341,4 @@ interface Building {
|
|
|
scientists: number
|
|
scientists: number
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
-type PMMGCompanyProduction = Record<string, Record<string, {amount: number}>>;
|
|
|
|
|
type Production = Record<string, Record<string, number>>;
|
|
type Production = Record<string, Record<string, number>>;
|