Adding the lab project
This commit is contained in:
@@ -0,0 +1,93 @@
|
||||
import { numericGridSize, seededRandom } from './caRuntime.js'
|
||||
import type { CaClass, JsonObject, SceneParams } from './types.js'
|
||||
|
||||
export interface InitialConditionResult {
|
||||
type: 'cells'
|
||||
cells: number[][]
|
||||
generator: {
|
||||
kind: string
|
||||
} & JsonObject
|
||||
}
|
||||
|
||||
export interface InitialConditionRuntimeInput {
|
||||
settings: SceneParams
|
||||
caClass: CaClass
|
||||
params: JsonObject
|
||||
}
|
||||
|
||||
export interface InitialConditionRuntime {
|
||||
id: string
|
||||
label: string
|
||||
generate: (input: InitialConditionRuntimeInput) => InitialConditionResult
|
||||
}
|
||||
|
||||
const initialConditionRuntimes = new Map<string, InitialConditionRuntime>()
|
||||
|
||||
function clampDensity(value: unknown) {
|
||||
return Math.max(0, Math.min(1, typeof value === 'number' ? value : 0.28))
|
||||
}
|
||||
|
||||
function randomSoup({ settings, caClass, params }: InitialConditionRuntimeInput): InitialConditionResult {
|
||||
const density = clampDensity(params.density)
|
||||
const seed = typeof params.seed === 'string' ? params.seed : 'studio-seed'
|
||||
const random = seededRandom(seed)
|
||||
const [width, height, depth] = numericGridSize(settings.simulation?.grid, caClass.dimensions)
|
||||
const cells: number[][] = []
|
||||
|
||||
for (let z = 0; z < depth; z += 1) {
|
||||
for (let y = 0; y < height; y += 1) {
|
||||
for (let x = 0; x < width; x += 1) {
|
||||
if (random() < density) cells.push([x, y, z])
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return {
|
||||
type: 'cells',
|
||||
cells,
|
||||
generator: {
|
||||
kind: 'random-soup',
|
||||
density,
|
||||
seed
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
export function registerInitialConditionRuntime(
|
||||
runtime: InitialConditionRuntime,
|
||||
options: { replace?: boolean } = {}
|
||||
) {
|
||||
if (!runtime.id.trim()) throw new Error('Initial condition runtime id is required')
|
||||
if (initialConditionRuntimes.has(runtime.id) && !options.replace) {
|
||||
throw new Error(`Initial condition runtime already registered: ${runtime.id}`)
|
||||
}
|
||||
initialConditionRuntimes.set(runtime.id, runtime)
|
||||
}
|
||||
|
||||
export function listInitialConditionRuntimes() {
|
||||
return [...initialConditionRuntimes.values()]
|
||||
}
|
||||
|
||||
export function getInitialConditionRuntime(runtimeId: string) {
|
||||
return initialConditionRuntimes.get(runtimeId) ?? null
|
||||
}
|
||||
|
||||
export function generateInitialCondition(runtimeId: string, input: InitialConditionRuntimeInput) {
|
||||
const runtime = getInitialConditionRuntime(runtimeId)
|
||||
if (!runtime) throw new Error(`Initial condition runtime unavailable: ${runtimeId}`)
|
||||
|
||||
const result = runtime.generate(input)
|
||||
if (result.type !== 'cells' || !Array.isArray(result.cells)) {
|
||||
throw new Error(`Initial condition runtime returned an invalid result: ${runtimeId}`)
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
registerInitialConditionRuntime(
|
||||
{
|
||||
id: 'random-soup',
|
||||
label: 'Random soup',
|
||||
generate: randomSoup
|
||||
},
|
||||
{ replace: true }
|
||||
)
|
||||
Reference in New Issue
Block a user