import { useRouter } from 'next/router' import { useGroups } from '../contexts/GroupProvider' import { FC, useMemo, useState } from 'react' import { calculateInputs } from '../../src/calculateInputs' import { DetailGraphNode, NodeDetails } from './NodeDetails/NodeDetails' import { groupBy, isNonNullable, uniquify } from '../../src/utils' import { EnrichedEntity } from '../../src/types' import Head from 'next/head' import { ScrollContainer } from './ScrollContainer/ScrollContainer' import { ProducingGraph } from './ProducingGraph/ProducingGraph' import { useFactories } from '../contexts/FactoryProvider' import { i18n, I18n } from '../shared/I18n/I18n' import { useIntl } from 'react-intl' import { Button } from '../shared/Button/Button' import { useAsyncEffect } from '../../src/hooks/useAsyncEffect' export const PageDetails: FC = () => { const intl = useIntl() const { query: { name } } = useRouter() const { exportedFactories, baseFactories, groups } = useGroups() const { findFactory } = useFactories() const group = typeof name === 'string' ? groups[name] : undefined const [inputFactories, intermediateFactories] = useMemo< ReturnType >(() => { if (!group) return [[], []] return calculateInputs( [...group.exports, ...group.malls], baseFactories, exportedFactories, findFactory ) }, [baseFactories, exportedFactories, findFactory, group]) const producingNodes: DetailGraphNode[] = useMemo(() => { if (!group) return [] const nodes = uniquify([...intermediateFactories, ...group.exports, ...group.malls]) .map(findFactory) .filter(isNonNullable) .map( (factory: EnrichedEntity) => ({ inputs: Object.keys(factory.recipe?.prerequisites ?? {}).sort((a, b) => a.localeCompare(b) ), outputs: Object.keys(factory.recipe?.output ?? {}).sort((a, b) => a.localeCompare(b)), name: factory.name, recipes: [factory.recipe] } as DetailGraphNode) ) return Object.values(groupBy(nodes, node => node.inputs.join())).map( nodesOfInput => ({ inputs: nodesOfInput[0].inputs, outputs: uniquify(nodesOfInput.flatMap(node => node.outputs)), name: nodesOfInput.map(node => node.name).join(', '), recipes: nodesOfInput.flatMap(node => node.recipes) } as DetailGraphNode) ) }, [findFactory, group, intermediateFactories]) const [savingModuleText, setSavingModuleText] = useState() // eslint-disable-next-line react-hooks/exhaustive-deps useAsyncEffect(async () => { const res = await fetch('/factorio/modules/energy-saving.csv') if (res.ok) setSavingModuleText(await res.text()) }, []) const [optimalModuleText, setOptimalModuleText] = useState() // eslint-disable-next-line react-hooks/exhaustive-deps useAsyncEffect(async () => { const res = await fetch('/factorio/modules/few-beacons.csv') if (res.ok) setOptimalModuleText(await res.text()) }, []) const statisticsUrl = useMemo(() => { const toDashedKey = (n: string) => n.slice(1).toLowerCase().replace(/_/g, '-') const checkIfPresent = (dashedKey: string) => { const b = !!optimalModuleText?.match(new RegExp(`${dashedKey};`)) && dashedKey !== 'rail-signal' return b } const getModuleString = (dashedKey: string, powerSaving?: boolean) => { const match = (powerSaving ? savingModuleText : optimalModuleText)?.match( new RegExp(`${dashedKey};.*;(\\d+);(\\d+);(\\d+);(\\d+)`) ) if (match) { const map = 'spe' const [beacons, ...modules] = match.slice(1).map(x => +x) let beaconModules = beacons == 1 ? 8 : beacons == 5 ? 12 : 0 const maxIdx = modules.reduce((m, c, i, arr) => (c > arr[m] ? i : m), 0) modules[maxIdx] -= beaconModules if (modules[maxIdx] < 0) { const newMaxIdx = modules.reduce((m, c, i, arr) => (c > arr[m] ? i : m), 0) modules[newMaxIdx] += modules[maxIdx] beaconModules += modules[maxIdx] modules[maxIdx] = 0 } let res = [ dashedKey, ...[0, 1, 2].flatMap(idx => Array(modules[idx]).fill(`${map[idx]}3`)) ].join(':') if (beacons + modules[0] + modules[1] === 0 && modules[2] === 2) res = res.replace(/e3/g, 'e2') else if (beacons + modules[0] + modules[1] === 0 && modules[2] >= 3) res = res.replace(/e3/g, 'e1') // console.log(beacons, modules, res, dashedKey) return res + (beaconModules ? `;${map[maxIdx]}3:${beaconModules}` : '') } return dashedKey } const params = { data: '1-1-19', rate: 's', cp: '2', min: '3', belt: 'express-transport-belt', items: [ ...(group?.malls .map(toDashedKey) .filter(checkIfPresent) .map(n => `${n}:r:1`) ?? []), ...(group?.exports .map(toDashedKey) .filter(checkIfPresent) .map(n => `${n}:r:45`) ?? []) ].join(','), ignore: inputFactories.map(toDashedKey).filter(checkIfPresent).join(','), modules: [ ...([...(group?.exports ?? []), ...intermediateFactories, ...inputFactories] .map(toDashedKey) .filter(checkIfPresent) .map(n => getModuleString(n)) ?? []), ...((group?.malls ?? []) .map(toDashedKey) .filter(checkIfPresent) .map(n => getModuleString(n, true)) ?? []) ].join(',') } const paramString = Object.entries(params) .map(keyValue => keyValue.join('=')) .join('&') // console.log('params', 'https://kirkmcdonald.github.io/calc.html#' + paramString) return 'https://kirkmcdonald.github.io/calc.html#' + paramString }, [group, inputFactories, savingModuleText, optimalModuleText, intermediateFactories]) return ( <> <I18n id={'page.visualize.details.title'} values={{ name: group?.name ?? '' }} />

) }