feat: page interactive, démos Play/Step et simulateur Carnot
Ajoute le pipeline PageSpec (validation, rendu, publication /p/{slug}),
les démos TipTap /demo, et le simulateur Carnot (modes frigo/PAC/moteur,
énergie kJ vs puissance W, unités K/°C/°F) avec correctifs d’équations KaTeX.
Co-authored-by: Cursor <cursoragent@cursor.com>
This commit is contained in:
65
memento-note/lib/simulators/index.ts
Normal file
65
memento-note/lib/simulators/index.ts
Normal file
@@ -0,0 +1,65 @@
|
||||
import type { IntentId } from '@/lib/interactive-demo/types'
|
||||
import { carnotCycleSimulator } from './carnot-cycle'
|
||||
import { carnotCycleAnim } from './carnot-cycle-anim'
|
||||
import { tsDiagramAnim } from './ts-diagram'
|
||||
import type { AnimPlugin, AnyPlugin, SimulatorPlugin } from './types'
|
||||
|
||||
export const GENERIC_SIM_ID = 'generic-formula' as const
|
||||
|
||||
const REGISTRY: Record<string, AnyPlugin> = {
|
||||
[carnotCycleSimulator.id]: carnotCycleSimulator,
|
||||
[carnotCycleAnim.id]: carnotCycleAnim,
|
||||
[tsDiagramAnim.id]: tsDiagramAnim,
|
||||
}
|
||||
|
||||
export function getPlugin(id: string): AnyPlugin | null {
|
||||
return REGISTRY[id] ?? null
|
||||
}
|
||||
|
||||
export function getSimulator(id: string): SimulatorPlugin | null {
|
||||
const p = REGISTRY[id]
|
||||
return p?.family === 'sim' ? p : null
|
||||
}
|
||||
|
||||
export function getAnimPlugin(id: string): AnimPlugin | null {
|
||||
const p = REGISTRY[id]
|
||||
return p?.family === 'anim' ? p : null
|
||||
}
|
||||
|
||||
export function isCatalogSimId(id: string): boolean {
|
||||
return id !== GENERIC_SIM_ID && id in REGISTRY
|
||||
}
|
||||
|
||||
export function listSimulators(): AnyPlugin[] {
|
||||
return Object.values(REGISTRY)
|
||||
}
|
||||
|
||||
/**
|
||||
* Compact catalog injected into the section-generation prompt so the LLM
|
||||
* can pick a curated plugin (sim or anim) and bind note values into a preset.
|
||||
*/
|
||||
export function catalogForPrompt(lang: string): string {
|
||||
const fr = lang.startsWith('fr')
|
||||
const catalog = listSimulators().map((plugin) => ({
|
||||
simId: plugin.id,
|
||||
family: plugin.family,
|
||||
summary: fr ? plugin.summary.fr : plugin.summary.en,
|
||||
keywords: plugin.keywords.slice(0, 10),
|
||||
...(plugin.family === 'sim'
|
||||
? {
|
||||
params: plugin.params.map((p) => ({
|
||||
id: p.id,
|
||||
symbol: p.symbol,
|
||||
range: [p.min, p.max],
|
||||
default: p.defaultValue,
|
||||
unit: p.unit,
|
||||
})),
|
||||
outputs: plugin.outputs.map((o) => o.symbol),
|
||||
}
|
||||
: {}),
|
||||
}))
|
||||
return JSON.stringify(catalog, null, 1)
|
||||
}
|
||||
|
||||
export type { SimulatorPlugin, AnimPlugin, AnyPlugin, AnimBeat, SimI18n, SimParamDef, SimOutputDef } from './types'
|
||||
export type { IntentId }
|
||||
Reference in New Issue
Block a user