Add button to show service statistics
This commit is contained in:
@@ -2,13 +2,10 @@ import { FC, HTMLProps } from 'react'
|
||||
import { EnrichedEntity } from '../../../src/types'
|
||||
import cx from 'classnames'
|
||||
import styles from './NodeOverview.module.css'
|
||||
import Link from 'next/link'
|
||||
import { EntityIcon } from '../../home/EntityIcon/EntityIcon'
|
||||
import { GraphNode } from '../../../src/graph-untangle/types'
|
||||
import { fixedEncodeURIComponent } from '../../../src/utils'
|
||||
import { useRouter } from 'next/router'
|
||||
import { GraphIcon } from '../../icons/GraphIcon'
|
||||
import { I18n } from '../../shared/I18n/I18n'
|
||||
import { ButtonVisualize } from '../../shared/ButtonVisualize/ButtonVisualize'
|
||||
|
||||
export type OverviewGraphNode = GraphNode<{
|
||||
icons: (EnrichedEntity | string)[]
|
||||
@@ -19,20 +16,10 @@ interface Props extends HTMLProps<HTMLDivElement> {
|
||||
}
|
||||
|
||||
export const NodeOverview: FC<Props> = ({ node, className, ...props }) => {
|
||||
const { query } = useRouter()
|
||||
return (
|
||||
<div {...props} className={cx(className, styles.root)}>
|
||||
<h3>
|
||||
<span className={styles.linkOut}>
|
||||
<Link
|
||||
href={{
|
||||
pathname: `/visualize/${fixedEncodeURIComponent(node.name)}`,
|
||||
query
|
||||
}}
|
||||
>
|
||||
<GraphIcon />
|
||||
</Link>
|
||||
</span>
|
||||
<ButtonVisualize groupId={node.name} />
|
||||
{node.name}
|
||||
</h3>
|
||||
{node.icons?.length ? (
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import { useRouter } from 'next/router'
|
||||
import { useGroups } from '../contexts/GroupProvider'
|
||||
import { FC, useMemo } from 'react'
|
||||
import { FC, useMemo, useState } from 'react'
|
||||
import { calculateInputs } from '../../src/calculateInputs'
|
||||
import { DetailGraphNode, NodeDetails } from './NodeDetails/NodeDetails'
|
||||
import { groupBy, isNonNullable, uniquify } from '../../src/utils'
|
||||
@@ -11,6 +11,8 @@ 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()
|
||||
@@ -61,6 +63,91 @@ export const PageDetails: FC = () => {
|
||||
)
|
||||
}, [findFactory, group, intermediateFactories])
|
||||
|
||||
const [savingModuleText, setSavingModuleText] = useState<string | undefined>()
|
||||
// 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<string | undefined>()
|
||||
// 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, 'ee')
|
||||
// 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 (
|
||||
<>
|
||||
<Head>
|
||||
@@ -74,6 +161,9 @@ export const PageDetails: FC = () => {
|
||||
<h1>
|
||||
<I18n id={'page.visualize.details.title'} values={{ name: group?.name ?? '' }} />
|
||||
</h1>
|
||||
<Button onClick={() => window.open(statisticsUrl, '_blank')}>
|
||||
<I18n id={'page.visualize.details.statistics.button'} />
|
||||
</Button>
|
||||
<ProducingGraph
|
||||
nodes={producingNodes}
|
||||
inputs={inputFactories}
|
||||
|
||||
@@ -32,14 +32,14 @@ export const PageOverview: FC = () => {
|
||||
<>
|
||||
<Head>
|
||||
<title>
|
||||
<I18n id={'page.visualize.details.title'} />
|
||||
<I18n id={'page.visualize.overview.title'} />
|
||||
</title>
|
||||
<meta name='description' content={i18n(intl, 'page.home.head.meta.description')} />
|
||||
</Head>
|
||||
<main>
|
||||
<ScrollContainer>
|
||||
<h1>
|
||||
<I18n id={'page.visualize.details.title'} />
|
||||
<I18n id={'page.visualize.overview.title'} />
|
||||
</h1>
|
||||
<ProducingGraph
|
||||
nodes={producingNodes}
|
||||
|
||||
Reference in New Issue
Block a user