Skip to content

Commit

Permalink
Add version/DLC switcher
Browse files Browse the repository at this point in the history
- update signals
- make it clearer that this only works with Factorio 2.0
  • Loading branch information
mgabor3141 committed Oct 16, 2024
1 parent d5ecef7 commit 50b7dee
Show file tree
Hide file tree
Showing 12 changed files with 2,140 additions and 2,790 deletions.
105 changes: 88 additions & 17 deletions app/components/result-stage.tsx
Original file line number Diff line number Diff line change
@@ -1,34 +1,105 @@
import { Dispatch, useCallback, useState } from 'react'
import { Song } from '@/app/components/select-stage'
import { songToFactorio } from '@/app/lib/song-to-factorio'
import signals from '@/app/lib/data/signals.json'
import signalsDlc from '@/app/lib/data/signals-dlc.json'
import { usePostHog } from 'posthog-js/react'

/**
* @param text
* @returns boolean: success
*/
const copyToClipboard = async (text: string): Promise<boolean> => {
try {
const type = 'text/plain'
const blob = new Blob([text], { type })
const data = [new ClipboardItem({ [type]: blob })]
await navigator.clipboard.write(data)
return true
} catch (e: unknown) {
console.warn(`Could not copy to clipboard. Update your browser.`, e)
return false
}
}

export type ResultStageProps = {
song: Song
onBack?: Dispatch<void>
onBack: Dispatch<void>
}
export const ResultStage = ({ song, onBack }: ResultStageProps) => {
const postHog = usePostHog()

type version = '1' | '2' | '2sa'
const [targetVersion, setTargetVersion] = useState<version>('2')

const [copySuccess, setCopySuccess] = useState<boolean>(false)
const [blueprintString, setBlueprintString] = useState('')

const getBlueprint = useCallback(() => {
setBlueprintString(songToFactorio(song))
}, [song])
const getBlueprint = useCallback(async () => {
setCopySuccess(false)
const signalSet = targetVersion === '2sa' ? signalsDlc : signals

const bp = songToFactorio(song, signalSet)
const copyAttempt = await copyToClipboard(bp)
setCopySuccess(copyAttempt)
setBlueprintString(bp)
postHog?.capture('Generated blueprint', {
Blueprint: bp,
'Clipboard Success': copyAttempt,
})
}, [postHog, song, targetVersion])

const versionOptions: { value: version; title: string }[] = [
{ value: '1', title: 'Factorio 1.x' },
{ value: '2', title: 'Factorio 2.x' },
{ value: '2sa', title: 'Factorio 2.x with Space Age DLC' },
]

return (
<div className="panel">
<div className="panel-inset">
<button className="button" onClick={() => onBack && onBack()}>
<div className="panel w-[500px]">
<div className="panel-inset flex-column items-start gap-4">
<button className="button" onClick={() => onBack()}>
Back
</button>
<button className="button button-green" onClick={getBlueprint}>
Get blueprint!
</button>
<textarea
value={blueprintString}
readOnly={true}
cols={50}
rows={6}
className="text-"
/>

<div className="flex-column gap-2">
<p className="mb-2">I am going to use this blueprint in:</p>
{versionOptions.map(({ value, title }) => (
<div className="flex gap-2 ml-4" key={value}>
<label>
<input
type="radio"
name="target-version"
onChange={({ target: { value } }) => {
setCopySuccess(false)
setBlueprintString('')
setTargetVersion(value as version)
}}
value={value}
checked={value === targetVersion}
/>
{title}
</label>
</div>
))}
</div>

<p className={`${targetVersion !== '1' ? 'opacity-0' : ''}`}>
To create blueprints for Factorio 1.x, please use{' '}
<a href="v1/">miditorio v1</a>.
</p>

<div className="flex items-center gap-4">
<button
className={`button button-green box-border ${targetVersion === '1' ? 'disabled' : ''}`}
onClick={getBlueprint}
disabled={targetVersion === '1'}
>
Get blueprint!
</button>
<p>{copySuccess && 'Copied 🗸'}</p>
</div>
<textarea value={blueprintString} readOnly={true} cols={50} rows={6} />
</div>
</div>
)
Expand Down
7 changes: 6 additions & 1 deletion app/components/select-stage.tsx
Original file line number Diff line number Diff line change
Expand Up @@ -119,7 +119,7 @@ export const SelectStage = ({ setSong }: SelectStageProps) => {
accept: ['audio/midi', 'audio/x-midi'],
readAs: 'ArrayBuffer',
onFilesSuccessfullySelected: async ({ filesContent }) => {
postHog.capture('selected midi file', {
postHog.capture('Selected midi file', {
'File Name': filesContent[0].name,
})
setSong(undefined)
Expand Down Expand Up @@ -166,6 +166,11 @@ export const SelectStage = ({ setSong }: SelectStageProps) => {
</a>
.
</p>
<p>
If you would like to generate a blueprint for Factorio 1.x, the
current released version, please use{' '}
<a href="v1/">miditorio v1</a>.
</p>
</div>

<button className="button button-green mr0" onClick={openFilePicker}>
Expand Down
2 changes: 1 addition & 1 deletion app/lib/__snapshots__/song-to-factorio.test.ts.snap

Large diffs are not rendered by default.

58 changes: 32 additions & 26 deletions app/lib/blueprint.ts
Original file line number Diff line number Diff line change
@@ -1,48 +1,54 @@
import { arrayChunks, encodeBlueprint } from '@/app/lib/utils'
import signals from '@/app/lib/data/signals-dlc.json'
import { FinalInstruments } from '@/app/lib/song-to-factorio'

const qualities = signals
.filter(({ type }) => type === 'quality')
.map(({ name }) => name)

// This is a reserved signal because of the playback circuit
const RESERVED = ['signal-green']
const RESERVED_SIGNALS = ['signal-green']

const signalsWithQuality = signals
.flatMap((signal) =>
qualities.map((quality) => ({
...signal,
quality,
})),
)
.filter(
({ name, quality }) => !(quality === 'normal' && RESERVED.includes(name)),
)
const prepareSignals = (signals: Signal[]) => {
const qualities = signals
.filter(({ type }) => type === 'quality')
.map(({ name }) => name)

return signals
.flatMap((signal) =>
qualities.map((quality) => ({
...signal,
comparator: '=',
quality,
})),
)
.filter(
({ name, quality }) =>
!(quality === 'normal' && RESERVED_SIGNALS.includes(name)),
)
}

export type Signal = {
name: string
type?: string
}

export const toBlueprint = ({
tickCombinatorValues,
dataCombinatorValues,
instruments,
signals,
}: {
tickCombinatorValues: number[]
dataCombinatorValues: number[]
instruments: FinalInstruments
signals: Signal[]
}) => {
const preparedSignals = prepareSignals(signals)

console.log(
`Got ${tickCombinatorValues.length} signals. ` +
`(${signalsWithQuality.length} total signals available.)`,
`(${preparedSignals.length} total signals available.)`,
)

// TODO
tickCombinatorValues = tickCombinatorValues.slice(
0,
signalsWithQuality.length,
)
dataCombinatorValues = dataCombinatorValues.slice(
0,
signalsWithQuality.length,
)
tickCombinatorValues = tickCombinatorValues.slice(0, preparedSignals.length)
dataCombinatorValues = dataCombinatorValues.slice(0, preparedSignals.length)

const entities: {
name: string
Expand Down Expand Up @@ -415,7 +421,7 @@ export const toBlueprint = ({
index: sectionIndex + 1,
filters: section.map((value, valueIndex) => ({
index: valueIndex + 1,
...signalsWithQuality[sectionIndex * 1000 + valueIndex],
...preparedSignals[sectionIndex * 1000 + valueIndex],
count: value,
})),
})),
Expand Down
Loading

0 comments on commit 50b7dee

Please sign in to comment.