diff --git a/.changeset/ad-hoc-value-errors.md b/.changeset/ad-hoc-value-errors.md new file mode 100644 index 00000000000..589e2532f8e --- /dev/null +++ b/.changeset/ad-hoc-value-errors.md @@ -0,0 +1,5 @@ +--- +"@hashintel/petrinaut": patch +--- + +Improve scenario and experiment forms with keyboard navigation, stacked section headers, overlay scrollbars, default starting-place filtering with a compact toggle beside the section title, and source expressions over selected computed values. Align the Time Step label and info icon, align token totals with place headers, keep select chevrons inside spreadsheet cells, and keep validation errors visible while editing ad-hoc values. diff --git a/.changeset/editable-example-scenarios.md b/.changeset/editable-example-scenarios.md new file mode 100644 index 00000000000..cdbb73e7189 --- /dev/null +++ b/.changeset/editable-example-scenarios.md @@ -0,0 +1,5 @@ +--- +"@hashintel/petrinaut-core": patch +--- + +Make bundled example scenarios editable in the ad-hoc scenario form while preserving their parameters and initial states. diff --git a/apps/petrinaut-website/scripts/generate-example-artifacts.ts b/apps/petrinaut-website/scripts/generate-example-artifacts.ts index d0674b8ced6..22d7b50d0b4 100644 --- a/apps/petrinaut-website/scripts/generate-example-artifacts.ts +++ b/apps/petrinaut-website/scripts/generate-example-artifacts.ts @@ -65,9 +65,12 @@ const generateRuntime = async (entry: ExampleCatalogEntry) => { null, ) as Record; for (const scenario of definition.scenarios ?? []) { - const hir = lowerScenarioToHir({ - parameterOverrides: scenario.parameterOverrides, - initialState: scenario.initialState, + const hir = lowerScenarioToHir(scenario, { + adHocContext: { + places: definition.places, + types: definition.types, + netParameters: definition.parameters, + }, }); const outcome = compileScenario( scenario, diff --git a/apps/petrinaut-website/src/examples/catalog.test.ts b/apps/petrinaut-website/src/examples/catalog.test.ts index 32828584771..5097d5e926e 100644 --- a/apps/petrinaut-website/src/examples/catalog.test.ts +++ b/apps/petrinaut-website/src/examples/catalog.test.ts @@ -1,5 +1,7 @@ import { describe, expect, it } from "vitest"; +import { compileScenario } from "@hashintel/petrinaut-core"; + import { exampleCatalog, exampleSlugs, @@ -34,7 +36,16 @@ describe("example catalog", () => { expect(example.catalog).toBe(entry); for (const scenario of example.definition.scenarios ?? []) { + expect(scenario.initialState.type).toBe("adhoc"); expect(runtime.scenarioHirById).toHaveProperty(scenario.id); + const compiled = compileScenario( + scenario, + runtime.scenarioHirById[scenario.id]!, + example.definition.parameters, + example.definition.places, + example.definition.types, + ); + expect(compiled.ok, JSON.stringify(compiled)).toBe(true); for (const parameter of scenario.scenarioParameters) { const bounds = entry.parameterBounds[parameter.identifier]; diff --git a/apps/petrinaut-website/src/examples/models/gases-1-pn-consumption-trigger.json b/apps/petrinaut-website/src/examples/models/gases-1-pn-consumption-trigger.json index 938d4918e66..788e93c1a59 100644 --- a/apps/petrinaut-website/src/examples/models/gases-1-pn-consumption-trigger.json +++ b/apps/petrinaut-website/src/examples/models/gases-1-pn-consumption-trigger.json @@ -430,8 +430,125 @@ "param__draw_enabled": "scenario.draw_enabled" }, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: 1,\n LoadsDelivered: 0,\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: 0,\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenConsumed: 0,\n SteadyNitrogenEvaporated: 0,\n SteadyNitrogenContents: 42,\n SteadyNitrogenUllage: 12,\n SteadyNitrogenUnitsDrawnSinceOrder: 0,\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "draw_enabled", + "type": "real", + "expression": "1", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__draw_enabled", + "expression": "scenario.draw_enabled", + "optimize": null + } + ], + "places": { + "place__idle_tankers": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_contents": { + "kind": "uncoloured", + "count": { + "expression": "42", + "optimize": null + } + }, + "place__s1_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + }, + "place__s1_units_drawn_since_order": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } }, { @@ -449,8 +566,125 @@ "param__draw_enabled": "scenario.draw_enabled" }, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: 1,\n LoadsDelivered: 0,\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: 0,\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenConsumed: 0,\n SteadyNitrogenEvaporated: 0,\n SteadyNitrogenContents: 42,\n SteadyNitrogenUllage: 12,\n SteadyNitrogenUnitsDrawnSinceOrder: 0,\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "draw_enabled", + "type": "real", + "expression": "0", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__draw_enabled", + "expression": "scenario.draw_enabled", + "optimize": null + } + ], + "places": { + "place__idle_tankers": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_contents": { + "kind": "uncoloured", + "count": { + "expression": "42", + "optimize": null + } + }, + "place__s1_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + }, + "place__s1_units_drawn_since_order": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } } ], diff --git a/apps/petrinaut-website/src/examples/models/gases-1-pn.json b/apps/petrinaut-website/src/examples/models/gases-1-pn.json index 24b6a80ed4b..e6e2a794557 100644 --- a/apps/petrinaut-website/src/examples/models/gases-1-pn.json +++ b/apps/petrinaut-website/src/examples/models/gases-1-pn.json @@ -415,8 +415,118 @@ "param__draw_enabled": "scenario.draw_enabled" }, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: 1,\n LoadsDelivered: 0,\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: 0,\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenConsumed: 0,\n SteadyNitrogenEvaporated: 0,\n SteadyNitrogenContents: 42,\n SteadyNitrogenUllage: 12,\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "draw_enabled", + "type": "real", + "expression": "1", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__draw_enabled", + "expression": "scenario.draw_enabled", + "optimize": null + } + ], + "places": { + "place__idle_tankers": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_contents": { + "kind": "uncoloured", + "count": { + "expression": "42", + "optimize": null + } + }, + "place__s1_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + } + } + } } }, { @@ -434,8 +544,118 @@ "param__draw_enabled": "scenario.draw_enabled" }, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: 1,\n LoadsDelivered: 0,\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: 0,\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenConsumed: 0,\n SteadyNitrogenEvaporated: 0,\n SteadyNitrogenContents: 42,\n SteadyNitrogenUllage: 12,\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "draw_enabled", + "type": "real", + "expression": "0", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__draw_enabled", + "expression": "scenario.draw_enabled", + "optimize": null + } + ], + "places": { + "place__idle_tankers": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_contents": { + "kind": "uncoloured", + "count": { + "expression": "42", + "optimize": null + } + }, + "place__s1_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + } + } + } } } ], diff --git a/apps/petrinaut-website/src/examples/models/gases-2-spn.json b/apps/petrinaut-website/src/examples/models/gases-2-spn.json index b5ab5430ce0..c149a0d0617 100644 --- a/apps/petrinaut-website/src/examples/models/gases-2-spn.json +++ b/apps/petrinaut-website/src/examples/models/gases-2-spn.json @@ -868,8 +868,202 @@ "param__draw_enabled": "scenario.draw_enabled" }, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: 1,\n LoadsDelivered: 0,\n Returning: 0,\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: 0,\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenConsumed: 0,\n SteadyNitrogenEvaporated: 0,\n SteadyNitrogenContents: 42,\n SteadyNitrogenUllage: 12,\n SlowNitrogenOrderPlaced: 0,\n SlowNitrogenOrderPermits: 1,\n SlowNitrogenOnRoute: 0,\n SlowNitrogenVented: 0,\n SlowNitrogenLineRunning: 1,\n SlowNitrogenLineStopped: 0,\n SlowNitrogenStockouts: 0,\n SlowNitrogenConsumed: 0,\n SlowNitrogenEvaporated: 0,\n SlowNitrogenContents: 18,\n SlowNitrogenUllage: 12,\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "draw_enabled", + "type": "real", + "expression": "1", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__draw_enabled", + "expression": "scenario.draw_enabled", + "optimize": null + } + ], + "places": { + "place__idle_tankers": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__returning": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_contents": { + "kind": "uncoloured", + "count": { + "expression": "42", + "optimize": null + } + }, + "place__s1_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + }, + "place__s2_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_on_route": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_contents": { + "kind": "uncoloured", + "count": { + "expression": "18", + "optimize": null + } + }, + "place__s2_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + } + } + } } }, { @@ -887,8 +1081,202 @@ "param__draw_enabled": "scenario.draw_enabled" }, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: 1,\n LoadsDelivered: 0,\n Returning: 0,\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: 0,\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenConsumed: 0,\n SteadyNitrogenEvaporated: 0,\n SteadyNitrogenContents: 42,\n SteadyNitrogenUllage: 12,\n SlowNitrogenOrderPlaced: 0,\n SlowNitrogenOrderPermits: 1,\n SlowNitrogenOnRoute: 0,\n SlowNitrogenVented: 0,\n SlowNitrogenLineRunning: 1,\n SlowNitrogenLineStopped: 0,\n SlowNitrogenStockouts: 0,\n SlowNitrogenConsumed: 0,\n SlowNitrogenEvaporated: 0,\n SlowNitrogenContents: 18,\n SlowNitrogenUllage: 12,\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "draw_enabled", + "type": "real", + "expression": "0", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__draw_enabled", + "expression": "scenario.draw_enabled", + "optimize": null + } + ], + "places": { + "place__idle_tankers": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__returning": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_contents": { + "kind": "uncoloured", + "count": { + "expression": "42", + "optimize": null + } + }, + "place__s1_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + }, + "place__s2_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_on_route": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_contents": { + "kind": "uncoloured", + "count": { + "expression": "18", + "optimize": null + } + }, + "place__s2_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + } + } + } } }, { @@ -906,8 +1294,202 @@ "param__draw_enabled": "scenario.draw_enabled" }, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: 2,\n LoadsDelivered: 0,\n Returning: 0,\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: 0,\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenConsumed: 0,\n SteadyNitrogenEvaporated: 0,\n SteadyNitrogenContents: 42,\n SteadyNitrogenUllage: 12,\n SlowNitrogenOrderPlaced: 0,\n SlowNitrogenOrderPermits: 1,\n SlowNitrogenOnRoute: 0,\n SlowNitrogenVented: 0,\n SlowNitrogenLineRunning: 1,\n SlowNitrogenLineStopped: 0,\n SlowNitrogenStockouts: 0,\n SlowNitrogenConsumed: 0,\n SlowNitrogenEvaporated: 0,\n SlowNitrogenContents: 18,\n SlowNitrogenUllage: 12,\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "draw_enabled", + "type": "real", + "expression": "1", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__draw_enabled", + "expression": "scenario.draw_enabled", + "optimize": null + } + ], + "places": { + "place__idle_tankers": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__returning": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_contents": { + "kind": "uncoloured", + "count": { + "expression": "42", + "optimize": null + } + }, + "place__s1_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + }, + "place__s2_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_on_route": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_contents": { + "kind": "uncoloured", + "count": { + "expression": "18", + "optimize": null + } + }, + "place__s2_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + } + } + } } }, { @@ -931,8 +1513,214 @@ "param__route_scale": "scenario.route_scale" }, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: 1,\n LoadsDelivered: 0,\n Returning: 0,\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: 0,\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenConsumed: 0,\n SteadyNitrogenEvaporated: 0,\n SteadyNitrogenContents: 42,\n SteadyNitrogenUllage: 12,\n SlowNitrogenOrderPlaced: 0,\n SlowNitrogenOrderPermits: 1,\n SlowNitrogenOnRoute: 0,\n SlowNitrogenVented: 0,\n SlowNitrogenLineRunning: 1,\n SlowNitrogenLineStopped: 0,\n SlowNitrogenStockouts: 0,\n SlowNitrogenConsumed: 0,\n SlowNitrogenEvaporated: 0,\n SlowNitrogenContents: 18,\n SlowNitrogenUllage: 12,\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "draw_enabled", + "type": "real", + "expression": "1", + "exposed": true, + "optimize": null + }, + { + "name": "route_scale", + "type": "real", + "expression": "1.5", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__draw_enabled", + "expression": "scenario.draw_enabled", + "optimize": null + }, + { + "parameterId": "param__route_scale", + "expression": "scenario.route_scale", + "optimize": null + } + ], + "places": { + "place__idle_tankers": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__returning": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_contents": { + "kind": "uncoloured", + "count": { + "expression": "42", + "optimize": null + } + }, + "place__s1_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + }, + "place__s2_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_on_route": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_contents": { + "kind": "uncoloured", + "count": { + "expression": "18", + "optimize": null + } + }, + "place__s2_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + } + } + } } } ], diff --git a/apps/petrinaut-website/src/examples/models/gases-3-cpn.json b/apps/petrinaut-website/src/examples/models/gases-3-cpn.json index 2f230237f8c..7b95a2aa1a8 100644 --- a/apps/petrinaut-website/src/examples/models/gases-3-cpn.json +++ b/apps/petrinaut-website/src/examples/models/gases-3-cpn.json @@ -1238,8 +1238,288 @@ "scenarioParameters": [], "parameterOverrides": {}, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: [{ product: \"nitrogen\" }, { product: \"nitrogen\" }, { product: \"oxygen\" }],\n LoadsDelivered: 0,\n Returning: [],\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: [],\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenConsumed: 0,\n SteadyNitrogenEvaporated: 0,\n SteadyNitrogenContents: 42,\n SteadyNitrogenUllage: 12,\n SlowNitrogenOrderPlaced: 0,\n SlowNitrogenOrderPermits: 1,\n SlowNitrogenOnRoute: [],\n SlowNitrogenVented: 0,\n SlowNitrogenLineRunning: 1,\n SlowNitrogenLineStopped: 0,\n SlowNitrogenStockouts: 0,\n SlowNitrogenConsumed: 0,\n SlowNitrogenEvaporated: 0,\n SlowNitrogenContents: 18,\n SlowNitrogenUllage: 12,\n CriticalOxygenOrderPlaced: 0,\n CriticalOxygenOrderPermits: 2,\n CriticalOxygenOnRoute: [],\n CriticalOxygenVented: 0,\n CriticalOxygenLineRunning: 1,\n CriticalOxygenLineStopped: 0,\n CriticalOxygenStockouts: 0,\n CriticalOxygenConsumed: 0,\n CriticalOxygenEvaporated: 0,\n CriticalOxygenContents: 46,\n CriticalOxygenUllage: 12,\n};" + "type": "adhoc", + "content": { + "variables": [], + "netParameters": [], + "places": { + "place__idle_tankers": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "\"nitrogen\"", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "\"nitrogen\"", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "\"oxygen\"", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__returning": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_contents": { + "kind": "uncoloured", + "count": { + "expression": "42", + "optimize": null + } + }, + "place__s1_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + }, + "place__s2_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s2_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_contents": { + "kind": "uncoloured", + "count": { + "expression": "18", + "optimize": null + } + }, + "place__s2_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + }, + "place__s3_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s3_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s3_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s3_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_contents": { + "kind": "uncoloured", + "count": { + "expression": "46", + "optimize": null + } + }, + "place__s3_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + } + } + } } }, { @@ -1257,8 +1537,302 @@ "param__route_scale": "scenario.route_scale" }, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: [{ product: \"nitrogen\" }, { product: \"nitrogen\" }, { product: \"oxygen\" }],\n LoadsDelivered: 0,\n Returning: [],\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: [],\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenConsumed: 0,\n SteadyNitrogenEvaporated: 0,\n SteadyNitrogenContents: 42,\n SteadyNitrogenUllage: 12,\n SlowNitrogenOrderPlaced: 0,\n SlowNitrogenOrderPermits: 1,\n SlowNitrogenOnRoute: [],\n SlowNitrogenVented: 0,\n SlowNitrogenLineRunning: 1,\n SlowNitrogenLineStopped: 0,\n SlowNitrogenStockouts: 0,\n SlowNitrogenConsumed: 0,\n SlowNitrogenEvaporated: 0,\n SlowNitrogenContents: 18,\n SlowNitrogenUllage: 12,\n CriticalOxygenOrderPlaced: 0,\n CriticalOxygenOrderPermits: 2,\n CriticalOxygenOnRoute: [],\n CriticalOxygenVented: 0,\n CriticalOxygenLineRunning: 1,\n CriticalOxygenLineStopped: 0,\n CriticalOxygenStockouts: 0,\n CriticalOxygenConsumed: 0,\n CriticalOxygenEvaporated: 0,\n CriticalOxygenContents: 46,\n CriticalOxygenUllage: 12,\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "route_scale", + "type": "real", + "expression": "1.5", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__route_scale", + "expression": "scenario.route_scale", + "optimize": null + } + ], + "places": { + "place__idle_tankers": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "\"nitrogen\"", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "\"nitrogen\"", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "\"oxygen\"", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__returning": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_contents": { + "kind": "uncoloured", + "count": { + "expression": "42", + "optimize": null + } + }, + "place__s1_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + }, + "place__s2_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s2_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_contents": { + "kind": "uncoloured", + "count": { + "expression": "18", + "optimize": null + } + }, + "place__s2_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + }, + "place__s3_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s3_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s3_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s3_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_contents": { + "kind": "uncoloured", + "count": { + "expression": "46", + "optimize": null + } + }, + "place__s3_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + } + } + } } }, { @@ -1268,8 +1842,279 @@ "scenarioParameters": [], "parameterOverrides": {}, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: [{ product: \"nitrogen\" }, { product: \"oxygen\" }],\n LoadsDelivered: 0,\n Returning: [],\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: [],\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenConsumed: 0,\n SteadyNitrogenEvaporated: 0,\n SteadyNitrogenContents: 42,\n SteadyNitrogenUllage: 12,\n SlowNitrogenOrderPlaced: 0,\n SlowNitrogenOrderPermits: 1,\n SlowNitrogenOnRoute: [],\n SlowNitrogenVented: 0,\n SlowNitrogenLineRunning: 1,\n SlowNitrogenLineStopped: 0,\n SlowNitrogenStockouts: 0,\n SlowNitrogenConsumed: 0,\n SlowNitrogenEvaporated: 0,\n SlowNitrogenContents: 18,\n SlowNitrogenUllage: 12,\n CriticalOxygenOrderPlaced: 0,\n CriticalOxygenOrderPermits: 2,\n CriticalOxygenOnRoute: [],\n CriticalOxygenVented: 0,\n CriticalOxygenLineRunning: 1,\n CriticalOxygenLineStopped: 0,\n CriticalOxygenStockouts: 0,\n CriticalOxygenConsumed: 0,\n CriticalOxygenEvaporated: 0,\n CriticalOxygenContents: 46,\n CriticalOxygenUllage: 12,\n};" + "type": "adhoc", + "content": { + "variables": [], + "netParameters": [], + "places": { + "place__idle_tankers": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "\"nitrogen\"", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "\"oxygen\"", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__returning": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_contents": { + "kind": "uncoloured", + "count": { + "expression": "42", + "optimize": null + } + }, + "place__s1_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + }, + "place__s2_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s2_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_contents": { + "kind": "uncoloured", + "count": { + "expression": "18", + "optimize": null + } + }, + "place__s2_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + }, + "place__s3_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s3_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s3_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s3_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_contents": { + "kind": "uncoloured", + "count": { + "expression": "46", + "optimize": null + } + }, + "place__s3_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + } + } + } } }, { @@ -1279,8 +2124,288 @@ "scenarioParameters": [], "parameterOverrides": {}, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: [{ product: \"nitrogen\" }, { product: \"oxygen\" }, { product: \"oxygen\" }],\n LoadsDelivered: 0,\n Returning: [],\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: [],\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenConsumed: 0,\n SteadyNitrogenEvaporated: 0,\n SteadyNitrogenContents: 42,\n SteadyNitrogenUllage: 12,\n SlowNitrogenOrderPlaced: 0,\n SlowNitrogenOrderPermits: 1,\n SlowNitrogenOnRoute: [],\n SlowNitrogenVented: 0,\n SlowNitrogenLineRunning: 1,\n SlowNitrogenLineStopped: 0,\n SlowNitrogenStockouts: 0,\n SlowNitrogenConsumed: 0,\n SlowNitrogenEvaporated: 0,\n SlowNitrogenContents: 18,\n SlowNitrogenUllage: 12,\n CriticalOxygenOrderPlaced: 0,\n CriticalOxygenOrderPermits: 2,\n CriticalOxygenOnRoute: [],\n CriticalOxygenVented: 0,\n CriticalOxygenLineRunning: 1,\n CriticalOxygenLineStopped: 0,\n CriticalOxygenStockouts: 0,\n CriticalOxygenConsumed: 0,\n CriticalOxygenEvaporated: 0,\n CriticalOxygenContents: 46,\n CriticalOxygenUllage: 12,\n};" + "type": "adhoc", + "content": { + "variables": [], + "netParameters": [], + "places": { + "place__idle_tankers": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "\"nitrogen\"", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "\"oxygen\"", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "\"oxygen\"", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__returning": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_contents": { + "kind": "uncoloured", + "count": { + "expression": "42", + "optimize": null + } + }, + "place__s1_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + }, + "place__s2_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s2_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_contents": { + "kind": "uncoloured", + "count": { + "expression": "18", + "optimize": null + } + }, + "place__s2_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + }, + "place__s3_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s3_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s3_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s3_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_consumed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_evaporated": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_contents": { + "kind": "uncoloured", + "count": { + "expression": "46", + "optimize": null + } + }, + "place__s3_ullage": { + "kind": "uncoloured", + "count": { + "expression": "12", + "optimize": null + } + } + } + } } } ], diff --git a/apps/petrinaut-website/src/examples/models/gases-4-dcpn.json b/apps/petrinaut-website/src/examples/models/gases-4-dcpn.json index ce46d796856..8cb57bea868 100644 --- a/apps/petrinaut-website/src/examples/models/gases-4-dcpn.json +++ b/apps/petrinaut-website/src/examples/models/gases-4-dcpn.json @@ -1498,8 +1498,421 @@ "scenarioParameters": [], "parameterOverrides": {}, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: [{ remaining: 0, product: \"nitrogen\", payload: 12, hired: 0 }, { remaining: 0, product: \"nitrogen\", payload: 12, hired: 0 }, { remaining: 0, product: \"oxygen\", payload: 12, hired: 0 }],\n LoadsDelivered: 0,\n Returning: [],\n OpenOrders: 0,\n Hires: 0,\n Plant: [{ up: 1 }],\n Outages: 0,\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: [],\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenTank: [{ level: 42, pressure: 2, drawn: 0, boiled: 0, capacity: 54, draw: parameters.draw_1, criticality: 2, product: \"nitrogen\", spilled: 0 }],\n SlowNitrogenOrderPlaced: 0,\n SlowNitrogenOrderPermits: 1,\n SlowNitrogenOnRoute: [],\n SlowNitrogenVented: 0,\n SlowNitrogenLineRunning: 1,\n SlowNitrogenLineStopped: 0,\n SlowNitrogenStockouts: 0,\n SlowNitrogenTank: [{ level: 18, pressure: 2, drawn: 0, boiled: 0, capacity: 30, draw: parameters.draw_2, criticality: 1, product: \"nitrogen\", spilled: 0 }],\n CriticalOxygenOrderPlaced: 0,\n CriticalOxygenOrderPermits: 2,\n CriticalOxygenOnRoute: [],\n CriticalOxygenVented: 0,\n CriticalOxygenLineRunning: 1,\n CriticalOxygenLineStopped: 0,\n CriticalOxygenStockouts: 0,\n CriticalOxygenTank: [{ level: 46, pressure: 2, drawn: 0, boiled: 0, capacity: 58, draw: parameters.draw_3, criticality: 3, product: \"oxygen\", spilled: 0 }],\n};" + "type": "adhoc", + "content": { + "variables": [], + "netParameters": [], + "places": { + "place__idle_tankers": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "\"oxygen\"", + "optimize": null + }, + { + "expression": "12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__returning": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__open_orders": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__hires": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__plant": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__outages": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "42", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "54", + "optimize": null + }, + { + "expression": "parameters.draw_1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__s2_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s2_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "18", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "30", + "optimize": null + }, + { + "expression": "parameters.draw_2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__s3_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s3_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s3_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s3_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "46", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "58", + "optimize": null + }, + { + "expression": "parameters.draw_3", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "3", + "optimize": null + }, + { + "expression": "\"oxygen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + } + } + } } }, { @@ -1517,8 +1930,435 @@ "param__route_scale": "scenario.route_scale" }, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: [{ remaining: 0, product: \"nitrogen\", payload: 12, hired: 0 }, { remaining: 0, product: \"nitrogen\", payload: 12, hired: 0 }, { remaining: 0, product: \"oxygen\", payload: 12, hired: 0 }],\n LoadsDelivered: 0,\n Returning: [],\n OpenOrders: 0,\n Hires: 0,\n Plant: [{ up: 1 }],\n Outages: 0,\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: [],\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenTank: [{ level: 42, pressure: 2, drawn: 0, boiled: 0, capacity: 54, draw: parameters.draw_1, criticality: 2, product: \"nitrogen\", spilled: 0 }],\n SlowNitrogenOrderPlaced: 0,\n SlowNitrogenOrderPermits: 1,\n SlowNitrogenOnRoute: [],\n SlowNitrogenVented: 0,\n SlowNitrogenLineRunning: 1,\n SlowNitrogenLineStopped: 0,\n SlowNitrogenStockouts: 0,\n SlowNitrogenTank: [{ level: 18, pressure: 2, drawn: 0, boiled: 0, capacity: 30, draw: parameters.draw_2, criticality: 1, product: \"nitrogen\", spilled: 0 }],\n CriticalOxygenOrderPlaced: 0,\n CriticalOxygenOrderPermits: 2,\n CriticalOxygenOnRoute: [],\n CriticalOxygenVented: 0,\n CriticalOxygenLineRunning: 1,\n CriticalOxygenLineStopped: 0,\n CriticalOxygenStockouts: 0,\n CriticalOxygenTank: [{ level: 46, pressure: 2, drawn: 0, boiled: 0, capacity: 58, draw: parameters.draw_3, criticality: 3, product: \"oxygen\", spilled: 0 }],\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "route_scale", + "type": "real", + "expression": "1.5", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__route_scale", + "expression": "scenario.route_scale", + "optimize": null + } + ], + "places": { + "place__idle_tankers": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "\"oxygen\"", + "optimize": null + }, + { + "expression": "12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__returning": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__open_orders": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__hires": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__plant": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__outages": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "42", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "54", + "optimize": null + }, + { + "expression": "parameters.draw_1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__s2_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s2_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "18", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "30", + "optimize": null + }, + { + "expression": "parameters.draw_2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__s3_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s3_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s3_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s3_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "46", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "58", + "optimize": null + }, + { + "expression": "parameters.draw_3", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "3", + "optimize": null + }, + { + "expression": "\"oxygen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + } + } + } } }, { @@ -1528,8 +2368,400 @@ "scenarioParameters": [], "parameterOverrides": {}, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: [{ remaining: 0, product: \"nitrogen\", payload: 12, hired: 0 }, { remaining: 0, product: \"oxygen\", payload: 12, hired: 0 }],\n LoadsDelivered: 0,\n Returning: [],\n OpenOrders: 0,\n Hires: 0,\n Plant: [{ up: 1 }],\n Outages: 0,\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: [],\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenTank: [{ level: 42, pressure: 2, drawn: 0, boiled: 0, capacity: 54, draw: parameters.draw_1, criticality: 2, product: \"nitrogen\", spilled: 0 }],\n SlowNitrogenOrderPlaced: 0,\n SlowNitrogenOrderPermits: 1,\n SlowNitrogenOnRoute: [],\n SlowNitrogenVented: 0,\n SlowNitrogenLineRunning: 1,\n SlowNitrogenLineStopped: 0,\n SlowNitrogenStockouts: 0,\n SlowNitrogenTank: [{ level: 18, pressure: 2, drawn: 0, boiled: 0, capacity: 30, draw: parameters.draw_2, criticality: 1, product: \"nitrogen\", spilled: 0 }],\n CriticalOxygenOrderPlaced: 0,\n CriticalOxygenOrderPermits: 2,\n CriticalOxygenOnRoute: [],\n CriticalOxygenVented: 0,\n CriticalOxygenLineRunning: 1,\n CriticalOxygenLineStopped: 0,\n CriticalOxygenStockouts: 0,\n CriticalOxygenTank: [{ level: 46, pressure: 2, drawn: 0, boiled: 0, capacity: 58, draw: parameters.draw_3, criticality: 3, product: \"oxygen\", spilled: 0 }],\n};" + "type": "adhoc", + "content": { + "variables": [], + "netParameters": [], + "places": { + "place__idle_tankers": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "\"oxygen\"", + "optimize": null + }, + { + "expression": "12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__returning": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__open_orders": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__hires": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__plant": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__outages": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "42", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "54", + "optimize": null + }, + { + "expression": "parameters.draw_1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__s2_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s2_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "18", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "30", + "optimize": null + }, + { + "expression": "parameters.draw_2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__s3_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s3_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s3_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s3_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "46", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "58", + "optimize": null + }, + { + "expression": "parameters.draw_3", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "3", + "optimize": null + }, + { + "expression": "\"oxygen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + } + } + } } }, { @@ -1547,8 +2779,435 @@ "param__draw_2": "scenario.slow_draw" }, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: [{ remaining: 0, product: \"nitrogen\", payload: 12, hired: 0 }, { remaining: 0, product: \"nitrogen\", payload: 12, hired: 0 }, { remaining: 0, product: \"oxygen\", payload: 12, hired: 0 }],\n LoadsDelivered: 0,\n Returning: [],\n OpenOrders: 0,\n Hires: 0,\n Plant: [{ up: 1 }],\n Outages: 0,\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: [],\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenTank: [{ level: 42, pressure: 2, drawn: 0, boiled: 0, capacity: 54, draw: parameters.draw_1, criticality: 2, product: \"nitrogen\", spilled: 0 }],\n SlowNitrogenOrderPlaced: 0,\n SlowNitrogenOrderPermits: 1,\n SlowNitrogenOnRoute: [],\n SlowNitrogenVented: 0,\n SlowNitrogenLineRunning: 1,\n SlowNitrogenLineStopped: 0,\n SlowNitrogenStockouts: 0,\n SlowNitrogenTank: [{ level: 18, pressure: 2, drawn: 0, boiled: 0, capacity: 30, draw: parameters.draw_2, criticality: 1, product: \"nitrogen\", spilled: 0 }],\n CriticalOxygenOrderPlaced: 0,\n CriticalOxygenOrderPermits: 2,\n CriticalOxygenOnRoute: [],\n CriticalOxygenVented: 0,\n CriticalOxygenLineRunning: 1,\n CriticalOxygenLineStopped: 0,\n CriticalOxygenStockouts: 0,\n CriticalOxygenTank: [{ level: 46, pressure: 2, drawn: 0, boiled: 0, capacity: 58, draw: parameters.draw_3, criticality: 3, product: \"oxygen\", spilled: 0 }],\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "slow_draw", + "type": "real", + "expression": "0.01", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__draw_2", + "expression": "scenario.slow_draw", + "optimize": null + } + ], + "places": { + "place__idle_tankers": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "\"oxygen\"", + "optimize": null + }, + { + "expression": "12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__returning": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__open_orders": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__hires": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__plant": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__outages": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "42", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "54", + "optimize": null + }, + { + "expression": "parameters.draw_1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__s2_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s2_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "18", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "30", + "optimize": null + }, + { + "expression": "parameters.draw_2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__s3_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s3_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s3_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s3_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "46", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "58", + "optimize": null + }, + { + "expression": "parameters.draw_3", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "3", + "optimize": null + }, + { + "expression": "\"oxygen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + } + } + } } }, { @@ -1566,8 +3225,435 @@ "param__hire_enabled": "scenario.hire_enabled" }, "initialState": { - "type": "code", - "content": "return {\n IdleTankers: [{ remaining: 0, product: \"nitrogen\", payload: 12, hired: 0 }, { remaining: 0, product: \"nitrogen\", payload: 12, hired: 0 }, { remaining: 0, product: \"oxygen\", payload: 12, hired: 0 }],\n LoadsDelivered: 0,\n Returning: [],\n OpenOrders: 0,\n Hires: 0,\n Plant: [{ up: 1 }],\n Outages: 0,\n SteadyNitrogenOrderPlaced: 0,\n SteadyNitrogenOrderPermits: 2,\n SteadyNitrogenOnRoute: [],\n SteadyNitrogenVented: 0,\n SteadyNitrogenLineRunning: 1,\n SteadyNitrogenLineStopped: 0,\n SteadyNitrogenStockouts: 0,\n SteadyNitrogenTank: [{ level: 42, pressure: 2, drawn: 0, boiled: 0, capacity: 54, draw: parameters.draw_1, criticality: 2, product: \"nitrogen\", spilled: 0 }],\n SlowNitrogenOrderPlaced: 0,\n SlowNitrogenOrderPermits: 1,\n SlowNitrogenOnRoute: [],\n SlowNitrogenVented: 0,\n SlowNitrogenLineRunning: 1,\n SlowNitrogenLineStopped: 0,\n SlowNitrogenStockouts: 0,\n SlowNitrogenTank: [{ level: 18, pressure: 2, drawn: 0, boiled: 0, capacity: 30, draw: parameters.draw_2, criticality: 1, product: \"nitrogen\", spilled: 0 }],\n CriticalOxygenOrderPlaced: 0,\n CriticalOxygenOrderPermits: 2,\n CriticalOxygenOnRoute: [],\n CriticalOxygenVented: 0,\n CriticalOxygenLineRunning: 1,\n CriticalOxygenLineStopped: 0,\n CriticalOxygenStockouts: 0,\n CriticalOxygenTank: [{ level: 46, pressure: 2, drawn: 0, boiled: 0, capacity: 58, draw: parameters.draw_3, criticality: 3, product: \"oxygen\", spilled: 0 }],\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "hire_enabled", + "type": "real", + "expression": "0", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__hire_enabled", + "expression": "scenario.hire_enabled", + "optimize": null + } + ], + "places": { + "place__idle_tankers": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "\"oxygen\"", + "optimize": null + }, + { + "expression": "12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__loads_delivered": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__returning": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__open_orders": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__hires": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__plant": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__outages": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s1_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s1_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s1_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s1_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "42", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "54", + "optimize": null + }, + { + "expression": "parameters.draw_1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__s2_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s2_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s2_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s2_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "18", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "30", + "optimize": null + }, + { + "expression": "parameters.draw_2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "\"nitrogen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__s3_order_placed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_order_permits": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__s3_on_route": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__s3_vented": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_line_running": { + "kind": "uncoloured", + "count": { + "expression": "1", + "optimize": null + } + }, + "place__s3_line_stopped": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_stockouts": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__s3_tank": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "46", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "58", + "optimize": null + }, + { + "expression": "parameters.draw_3", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "3", + "optimize": null + }, + { + "expression": "\"oxygen\"", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + } + } + } } } ], diff --git a/apps/petrinaut-website/src/examples/models/semiconductor-fab-drift.json b/apps/petrinaut-website/src/examples/models/semiconductor-fab-drift.json index d8a63a269e0..150226a7310 100644 --- a/apps/petrinaut-website/src/examples/models/semiconductor-fab-drift.json +++ b/apps/petrinaut-website/src/examples/models/semiconductor-fab-drift.json @@ -1409,8 +1409,2737 @@ "param__maintenance_threshold": "scenario.maintenance_threshold" }, "initialState": { - "type": "code", - "content": "return {\n FabEntrance: [],\n WIPQueue: [\n { product_type: 0, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 7, priority: 1.11, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 14, priority: 1.0, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 21, priority: 1.22, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 14, priority: 1.09, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 21, priority: 1.41, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 14, priority: 1.24, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 21, priority: 1.0, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 7, priority: 1.11, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 14, priority: 1.0, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 21, priority: 1.22, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 14, priority: 1.09, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 21, priority: 1.41, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 14, priority: 1.24, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 21, priority: 1.0, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 7, priority: 1.11, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 14, priority: 1.0, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 21, priority: 1.22, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 14, priority: 1.09, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 21, priority: 1.41, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 14, priority: 1.24, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 }\n ],\n BatchQueue: [],\n InProcess: [],\n PostProcess: [],\n InInspection: [],\n Finished: [],\n Scrapped: [],\n WIPPermits: Math.max(0, parameters.wip_cap - 35),\n ChambersAvailable: [\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.01, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 0, chamber_idx: 1, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.16, particle_count: 0.22, hours_since_maintenance: 40.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 1, chamber_idx: 0, qualification: 1, process_drift: 0.0, batch_count: 0 },\n { condition: 0.24, particle_count: 0.28, hours_since_maintenance: 60.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 1, chamber_idx: 1, qualification: 2, process_drift: 0.005, batch_count: 0 },\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.015, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 0, chamber_idx: 1, qualification: 0, process_drift: -0.01, batch_count: 0 },\n { condition: 0.16, particle_count: 0.22, hours_since_maintenance: 40.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 1, chamber_idx: 0, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.24, particle_count: 0.28, hours_since_maintenance: 60.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 1, chamber_idx: 1, qualification: 0, process_drift: 0.0, batch_count: 0 },\n { condition: 0.32, particle_count: 0.34, hours_since_maintenance: 80.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 2, chamber_idx: 0, qualification: 1, process_drift: 0.005, batch_count: 0 },\n { condition: 0.4, particle_count: 0.4, hours_since_maintenance: 100.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 2, chamber_idx: 1, qualification: 2, process_drift: 0.01, batch_count: 0 },\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.01, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 0, chamber_idx: 1, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.16, particle_count: 0.22, hours_since_maintenance: 40.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 1, chamber_idx: 0, qualification: 1, process_drift: 0.0, batch_count: 0 },\n { condition: 0.24, particle_count: 0.28, hours_since_maintenance: 60.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 1, chamber_idx: 1, qualification: 2, process_drift: 0.005, batch_count: 0 },\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 3, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 3, tool_id: 1, chamber_idx: 0, qualification: 0, process_drift: 0.0, batch_count: 0 }\n ],\n ChambersProcessing: [],\n ChambersInMaintenance: [],\n ChambersBroken: [],\n MaintenanceCrew: 3,\n MaintenanceEvents: 0,\n BreakdownEvents: 0,\n LotsReleased: 0,\n LotsCompleted: 0,\n Calibrations: 0,\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "wip_cap", + "type": "integer", + "expression": "50", + "exposed": true, + "optimize": null + }, + { + "name": "demand_rate", + "type": "real", + "expression": "0.12", + "exposed": true, + "optimize": null + }, + { + "name": "maintenance_threshold", + "type": "real", + "expression": "0.85", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__wip_cap", + "expression": "scenario.wip_cap", + "optimize": null + }, + { + "parameterId": "param__demand_rate", + "expression": "scenario.demand_rate", + "optimize": null + }, + { + "parameterId": "param__maintenance_threshold", + "expression": "scenario.maintenance_threshold", + "optimize": null + } + ], + "places": { + "place__fab_entrance": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__wip_queue": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.11", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.22", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.09", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.41", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.24", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.11", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.22", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.09", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.41", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.24", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.11", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.22", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.09", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.41", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.24", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__batch_queue": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__in_process": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__post_process": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__in_inspection": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__finished": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__scrapped": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__wip_permits": { + "kind": "uncoloured", + "count": { + "expression": "Math.max(0, parameters.wip_cap - 35)", + "optimize": null + } + }, + "place__chambers_available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "0.22", + "optimize": null + }, + { + "expression": "40.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.24", + "optimize": null + }, + { + "expression": "0.28", + "optimize": null + }, + { + "expression": "60.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.015", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "0.22", + "optimize": null + }, + { + "expression": "40.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.24", + "optimize": null + }, + { + "expression": "0.28", + "optimize": null + }, + { + "expression": "60.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.32", + "optimize": null + }, + { + "expression": "0.34", + "optimize": null + }, + { + "expression": "80.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.4", + "optimize": null + }, + { + "expression": "0.4", + "optimize": null + }, + { + "expression": "100.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "0.22", + "optimize": null + }, + { + "expression": "40.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.24", + "optimize": null + }, + { + "expression": "0.28", + "optimize": null + }, + { + "expression": "60.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "3", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "3", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__chambers_processing": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__chambers_in_maintenance": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__chambers_broken": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__maintenance_crew": { + "kind": "uncoloured", + "count": { + "expression": "3", + "optimize": null + } + }, + "place__maintenance_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__breakdown_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__lots_released": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__lots_completed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__calibrations": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } }, { @@ -1441,8 +4170,2742 @@ "param__drift_volatility": "0.04" }, "initialState": { - "type": "code", - "content": "return {\n FabEntrance: [],\n WIPQueue: [\n { product_type: 0, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 7, priority: 1.11, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 14, priority: 1.0, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 21, priority: 1.22, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 14, priority: 1.09, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 21, priority: 1.41, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 14, priority: 1.24, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 21, priority: 1.0, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 7, priority: 1.11, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 14, priority: 1.0, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 21, priority: 1.22, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 14, priority: 1.09, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 21, priority: 1.41, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 14, priority: 1.24, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 21, priority: 1.0, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 7, priority: 1.11, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 14, priority: 1.0, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 21, priority: 1.22, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 14, priority: 1.09, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 21, priority: 1.41, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 14, priority: 1.24, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 }\n ],\n BatchQueue: [],\n InProcess: [],\n PostProcess: [],\n InInspection: [],\n Finished: [],\n Scrapped: [],\n WIPPermits: Math.max(0, parameters.wip_cap - 35),\n ChambersAvailable: [\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.01, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 0, chamber_idx: 1, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.16, particle_count: 0.22, hours_since_maintenance: 40.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 1, chamber_idx: 0, qualification: 1, process_drift: 0.0, batch_count: 0 },\n { condition: 0.24, particle_count: 0.28, hours_since_maintenance: 60.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 1, chamber_idx: 1, qualification: 2, process_drift: 0.005, batch_count: 0 },\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.015, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 0, chamber_idx: 1, qualification: 0, process_drift: -0.01, batch_count: 0 },\n { condition: 0.16, particle_count: 0.22, hours_since_maintenance: 40.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 1, chamber_idx: 0, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.24, particle_count: 0.28, hours_since_maintenance: 60.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 1, chamber_idx: 1, qualification: 0, process_drift: 0.0, batch_count: 0 },\n { condition: 0.32, particle_count: 0.34, hours_since_maintenance: 80.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 2, chamber_idx: 0, qualification: 1, process_drift: 0.005, batch_count: 0 },\n { condition: 0.4, particle_count: 0.4, hours_since_maintenance: 100.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 2, chamber_idx: 1, qualification: 2, process_drift: 0.01, batch_count: 0 },\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.01, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 0, chamber_idx: 1, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.16, particle_count: 0.22, hours_since_maintenance: 40.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 1, chamber_idx: 0, qualification: 1, process_drift: 0.0, batch_count: 0 },\n { condition: 0.24, particle_count: 0.28, hours_since_maintenance: 60.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 1, chamber_idx: 1, qualification: 2, process_drift: 0.005, batch_count: 0 },\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 3, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 3, tool_id: 1, chamber_idx: 0, qualification: 0, process_drift: 0.0, batch_count: 0 }\n ],\n ChambersProcessing: [],\n ChambersInMaintenance: [],\n ChambersBroken: [],\n MaintenanceCrew: 3,\n MaintenanceEvents: 0,\n BreakdownEvents: 0,\n LotsReleased: 0,\n LotsCompleted: 0,\n Calibrations: 0,\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "wip_cap", + "type": "integer", + "expression": "50", + "exposed": true, + "optimize": null + }, + { + "name": "demand_rate", + "type": "real", + "expression": "0.12", + "exposed": true, + "optimize": null + }, + { + "name": "maintenance_threshold", + "type": "real", + "expression": "0.85", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__wip_cap", + "expression": "scenario.wip_cap", + "optimize": null + }, + { + "parameterId": "param__demand_rate", + "expression": "scenario.demand_rate", + "optimize": null + }, + { + "parameterId": "param__maintenance_threshold", + "expression": "scenario.maintenance_threshold", + "optimize": null + }, + { + "parameterId": "param__drift_volatility", + "expression": "0.04", + "optimize": null + } + ], + "places": { + "place__fab_entrance": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__wip_queue": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.11", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.22", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.09", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.41", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.24", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.11", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.22", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.09", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.41", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.24", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.11", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.22", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.09", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.41", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.24", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__batch_queue": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__in_process": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__post_process": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__in_inspection": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__finished": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__scrapped": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__wip_permits": { + "kind": "uncoloured", + "count": { + "expression": "Math.max(0, parameters.wip_cap - 35)", + "optimize": null + } + }, + "place__chambers_available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "0.22", + "optimize": null + }, + { + "expression": "40.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.24", + "optimize": null + }, + { + "expression": "0.28", + "optimize": null + }, + { + "expression": "60.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.015", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "0.22", + "optimize": null + }, + { + "expression": "40.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.24", + "optimize": null + }, + { + "expression": "0.28", + "optimize": null + }, + { + "expression": "60.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.32", + "optimize": null + }, + { + "expression": "0.34", + "optimize": null + }, + { + "expression": "80.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.4", + "optimize": null + }, + { + "expression": "0.4", + "optimize": null + }, + { + "expression": "100.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "0.22", + "optimize": null + }, + { + "expression": "40.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.24", + "optimize": null + }, + { + "expression": "0.28", + "optimize": null + }, + { + "expression": "60.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "3", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "3", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__chambers_processing": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__chambers_in_maintenance": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__chambers_broken": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__maintenance_crew": { + "kind": "uncoloured", + "count": { + "expression": "3", + "optimize": null + } + }, + "place__maintenance_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__breakdown_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__lots_released": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__lots_completed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__calibrations": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } }, { @@ -1472,8 +6935,2737 @@ "param__maintenance_threshold": "scenario.maintenance_threshold" }, "initialState": { - "type": "code", - "content": "return {\n FabEntrance: [],\n WIPQueue: [\n { product_type: 0, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 7, priority: 1.11, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 14, priority: 1.0, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 21, priority: 1.22, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 14, priority: 1.09, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 21, priority: 1.41, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 14, priority: 1.24, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 21, priority: 1.0, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 7, priority: 1.11, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 14, priority: 1.0, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 21, priority: 1.22, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 14, priority: 1.09, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 21, priority: 1.41, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 14, priority: 1.24, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 21, priority: 1.0, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 7, priority: 1.11, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 14, priority: 1.0, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 21, priority: 1.22, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 14, priority: 1.09, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 21, priority: 1.41, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 14, priority: 1.24, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 }\n ],\n BatchQueue: [],\n InProcess: [],\n PostProcess: [],\n InInspection: [],\n Finished: [],\n Scrapped: [],\n WIPPermits: Math.max(0, parameters.wip_cap - 35),\n ChambersAvailable: [\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.01, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 0, chamber_idx: 1, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.16, particle_count: 0.22, hours_since_maintenance: 40.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 1, chamber_idx: 0, qualification: 1, process_drift: 0.0, batch_count: 0 },\n { condition: 0.24, particle_count: 0.28, hours_since_maintenance: 60.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 1, chamber_idx: 1, qualification: 2, process_drift: 0.005, batch_count: 0 },\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.015, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 0, chamber_idx: 1, qualification: 0, process_drift: -0.01, batch_count: 0 },\n { condition: 0.16, particle_count: 0.22, hours_since_maintenance: 40.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 1, chamber_idx: 0, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.24, particle_count: 0.28, hours_since_maintenance: 60.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 1, chamber_idx: 1, qualification: 0, process_drift: 0.0, batch_count: 0 },\n { condition: 0.32, particle_count: 0.34, hours_since_maintenance: 80.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 2, chamber_idx: 0, qualification: 1, process_drift: 0.005, batch_count: 0 },\n { condition: 0.4, particle_count: 0.4, hours_since_maintenance: 100.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 2, chamber_idx: 1, qualification: 2, process_drift: 0.01, batch_count: 0 },\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.01, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 0, chamber_idx: 1, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.16, particle_count: 0.22, hours_since_maintenance: 40.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 1, chamber_idx: 0, qualification: 1, process_drift: 0.0, batch_count: 0 },\n { condition: 0.24, particle_count: 0.28, hours_since_maintenance: 60.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 1, chamber_idx: 1, qualification: 2, process_drift: 0.005, batch_count: 0 },\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 3, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 3, tool_id: 1, chamber_idx: 0, qualification: 0, process_drift: 0.0, batch_count: 0 }\n ],\n ChambersProcessing: [],\n ChambersInMaintenance: [],\n ChambersBroken: [],\n MaintenanceCrew: 3,\n MaintenanceEvents: 0,\n BreakdownEvents: 0,\n LotsReleased: 0,\n LotsCompleted: 0,\n Calibrations: 0,\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "wip_cap", + "type": "integer", + "expression": "50", + "exposed": true, + "optimize": null + }, + { + "name": "demand_rate", + "type": "real", + "expression": "0.12", + "exposed": true, + "optimize": null + }, + { + "name": "maintenance_threshold", + "type": "real", + "expression": "0.6", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__wip_cap", + "expression": "scenario.wip_cap", + "optimize": null + }, + { + "parameterId": "param__demand_rate", + "expression": "scenario.demand_rate", + "optimize": null + }, + { + "parameterId": "param__maintenance_threshold", + "expression": "scenario.maintenance_threshold", + "optimize": null + } + ], + "places": { + "place__fab_entrance": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__wip_queue": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.11", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.22", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.09", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.41", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.24", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.11", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.22", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.09", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.41", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.24", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.11", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.22", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.09", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.41", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.24", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__batch_queue": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__in_process": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__post_process": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__in_inspection": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__finished": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__scrapped": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__wip_permits": { + "kind": "uncoloured", + "count": { + "expression": "Math.max(0, parameters.wip_cap - 35)", + "optimize": null + } + }, + "place__chambers_available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "0.22", + "optimize": null + }, + { + "expression": "40.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.24", + "optimize": null + }, + { + "expression": "0.28", + "optimize": null + }, + { + "expression": "60.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.015", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "0.22", + "optimize": null + }, + { + "expression": "40.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.24", + "optimize": null + }, + { + "expression": "0.28", + "optimize": null + }, + { + "expression": "60.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.32", + "optimize": null + }, + { + "expression": "0.34", + "optimize": null + }, + { + "expression": "80.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.4", + "optimize": null + }, + { + "expression": "0.4", + "optimize": null + }, + { + "expression": "100.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "0.22", + "optimize": null + }, + { + "expression": "40.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.24", + "optimize": null + }, + { + "expression": "0.28", + "optimize": null + }, + { + "expression": "60.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "3", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "3", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__chambers_processing": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__chambers_in_maintenance": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__chambers_broken": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__maintenance_crew": { + "kind": "uncoloured", + "count": { + "expression": "3", + "optimize": null + } + }, + "place__maintenance_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__breakdown_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__lots_released": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__lots_completed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__calibrations": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } }, { @@ -1503,8 +9695,2737 @@ "param__maintenance_threshold": "scenario.maintenance_threshold" }, "initialState": { - "type": "code", - "content": "return {\n FabEntrance: [],\n WIPQueue: [\n { product_type: 0, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 7, priority: 1.11, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 14, priority: 1.0, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 21, priority: 1.22, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 14, priority: 1.09, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 21, priority: 1.41, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 14, priority: 1.24, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 21, priority: 1.0, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 7, priority: 1.11, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 14, priority: 1.0, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 21, priority: 1.22, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 14, priority: 1.09, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 21, priority: 1.41, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 14, priority: 1.24, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 21, priority: 1.0, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 7, priority: 1.11, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 14, priority: 1.0, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 21, priority: 1.22, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 14, priority: 1.09, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 21, priority: 1.41, age: 52.5, defect_count: 0.378, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.063, processing_chamber: -1, batch_wait: 0 },\n { product_type: 2, layer: 0, priority: 1.0, age: 0.0, defect_count: 0.0, process_remaining: 0, wait_time: 0, due_date: 250, process_bias: 0.0, processing_chamber: -1, batch_wait: 0 },\n { product_type: 0, layer: 7, priority: 1.0, age: 17.5, defect_count: 0.126, process_remaining: 0, wait_time: 0, due_date: 200, process_bias: 0.021, processing_chamber: -1, batch_wait: 0 },\n { product_type: 1, layer: 14, priority: 1.24, age: 35.0, defect_count: 0.252, process_remaining: 0, wait_time: 0, due_date: 180, process_bias: 0.042, processing_chamber: -1, batch_wait: 0 }\n ],\n BatchQueue: [],\n InProcess: [],\n PostProcess: [],\n InInspection: [],\n Finished: [],\n Scrapped: [],\n WIPPermits: Math.max(0, parameters.wip_cap - 35),\n ChambersAvailable: [\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.01, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 0, chamber_idx: 1, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.16, particle_count: 0.22, hours_since_maintenance: 40.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 1, chamber_idx: 0, qualification: 1, process_drift: 0.0, batch_count: 0 },\n { condition: 0.24, particle_count: 0.28, hours_since_maintenance: 60.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 0, tool_id: 1, chamber_idx: 1, qualification: 2, process_drift: 0.005, batch_count: 0 },\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.015, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 0, chamber_idx: 1, qualification: 0, process_drift: -0.01, batch_count: 0 },\n { condition: 0.16, particle_count: 0.22, hours_since_maintenance: 40.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 1, chamber_idx: 0, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.24, particle_count: 0.28, hours_since_maintenance: 60.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 1, chamber_idx: 1, qualification: 0, process_drift: 0.0, batch_count: 0 },\n { condition: 0.32, particle_count: 0.34, hours_since_maintenance: 80.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 2, chamber_idx: 0, qualification: 1, process_drift: 0.005, batch_count: 0 },\n { condition: 0.4, particle_count: 0.4, hours_since_maintenance: 100.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 1, tool_id: 2, chamber_idx: 1, qualification: 2, process_drift: 0.01, batch_count: 0 },\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.01, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 0, chamber_idx: 1, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.16, particle_count: 0.22, hours_since_maintenance: 40.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 1, chamber_idx: 0, qualification: 1, process_drift: 0.0, batch_count: 0 },\n { condition: 0.24, particle_count: 0.28, hours_since_maintenance: 60.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 2, tool_id: 1, chamber_idx: 1, qualification: 2, process_drift: 0.005, batch_count: 0 },\n { condition: 0.0, particle_count: 0.1, hours_since_maintenance: 0.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 3, tool_id: 0, chamber_idx: 0, qualification: 0, process_drift: -0.005, batch_count: 0 },\n { condition: 0.08, particle_count: 0.16, hours_since_maintenance: 20.0, maintenance_remaining: 0, diffusion_clock: 0, lots_processed: 0, machine_group: 3, tool_id: 1, chamber_idx: 0, qualification: 0, process_drift: 0.0, batch_count: 0 }\n ],\n ChambersProcessing: [],\n ChambersInMaintenance: [],\n ChambersBroken: [],\n MaintenanceCrew: 2,\n MaintenanceEvents: 0,\n BreakdownEvents: 0,\n LotsReleased: 0,\n LotsCompleted: 0,\n Calibrations: 0,\n};" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "wip_cap", + "type": "integer", + "expression": "50", + "exposed": true, + "optimize": null + }, + { + "name": "demand_rate", + "type": "real", + "expression": "0.12", + "exposed": true, + "optimize": null + }, + { + "name": "maintenance_threshold", + "type": "real", + "expression": "0.85", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__wip_cap", + "expression": "scenario.wip_cap", + "optimize": null + }, + { + "parameterId": "param__demand_rate", + "expression": "scenario.demand_rate", + "optimize": null + }, + { + "parameterId": "param__maintenance_threshold", + "expression": "scenario.maintenance_threshold", + "optimize": null + } + ], + "places": { + "place__fab_entrance": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__wip_queue": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.11", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.22", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.09", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.41", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.24", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.11", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.22", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.09", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.41", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.24", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.11", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.22", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.09", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "21", + "optimize": null + }, + { + "expression": "1.41", + "optimize": null + }, + { + "expression": "52.5", + "optimize": null + }, + { + "expression": "0.378", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.063", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "250", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0", + "optimize": null + }, + { + "expression": "7", + "optimize": null + }, + { + "expression": "1.0", + "optimize": null + }, + { + "expression": "17.5", + "optimize": null + }, + { + "expression": "0.126", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "200", + "optimize": null + }, + { + "expression": "0.021", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "1", + "optimize": null + }, + { + "expression": "14", + "optimize": null + }, + { + "expression": "1.24", + "optimize": null + }, + { + "expression": "35.0", + "optimize": null + }, + { + "expression": "0.252", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "180", + "optimize": null + }, + { + "expression": "0.042", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-1", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__batch_queue": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__in_process": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__post_process": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__in_inspection": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__finished": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__scrapped": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__wip_permits": { + "kind": "uncoloured", + "count": { + "expression": "Math.max(0, parameters.wip_cap - 35)", + "optimize": null + } + }, + "place__chambers_available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "0.22", + "optimize": null + }, + { + "expression": "40.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.24", + "optimize": null + }, + { + "expression": "0.28", + "optimize": null + }, + { + "expression": "60.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.015", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "0.22", + "optimize": null + }, + { + "expression": "40.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.24", + "optimize": null + }, + { + "expression": "0.28", + "optimize": null + }, + { + "expression": "60.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.32", + "optimize": null + }, + { + "expression": "0.34", + "optimize": null + }, + { + "expression": "80.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.4", + "optimize": null + }, + { + "expression": "0.4", + "optimize": null + }, + { + "expression": "100.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.01", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "0.22", + "optimize": null + }, + { + "expression": "40.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.24", + "optimize": null + }, + { + "expression": "0.28", + "optimize": null + }, + { + "expression": "60.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "2", + "optimize": null + }, + { + "expression": "0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0.1", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "3", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "-0.005", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + }, + { + "kind": "fixed", + "cells": [ + { + "expression": "0.08", + "optimize": null + }, + { + "expression": "0.16", + "optimize": null + }, + { + "expression": "20.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "3", + "optimize": null + }, + { + "expression": "1", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0.0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__chambers_processing": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__chambers_in_maintenance": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__chambers_broken": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__maintenance_crew": { + "kind": "uncoloured", + "count": { + "expression": "2", + "optimize": null + } + }, + "place__maintenance_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__breakdown_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__lots_released": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__lots_completed": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + }, + "place__calibrations": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } } ], diff --git a/apps/petrinaut-website/src/examples/models/truck-fleet-predictive-maintenance.json b/apps/petrinaut-website/src/examples/models/truck-fleet-predictive-maintenance.json index 00cecb15179..12f0901207a 100644 --- a/apps/petrinaut-website/src/examples/models/truck-fleet-predictive-maintenance.json +++ b/apps/petrinaut-website/src/examples/models/truck-fleet-predictive-maintenance.json @@ -1598,8 +1598,239 @@ "param__service_wear_limit": "scenario.service_wear_limit" }, "initialState": { - "type": "code", - "content": "const fleet = range(scenario.trucks).map((index) => ({\n brake_wear: (index / scenario.trucks) * 0.1,\n engine_wear: (index / scenario.trucks) * 0.08,\n tyre_wear: (index / scenario.trucks) * 0.12,\n km_remaining: 0,\n route_distance: 0,\n service_remaining: 0,\n route_class: 0,\n load_due: 0,\n load_revenue: 0,\n age: 0,\n loads_done: 0,\n unplanned: 0,\n road_severity: parameters.base_severity_mean,\n speed_factor: parameters.base_speed_mean,\n conditions_clock: 0,\n fuel_burned: 0,\n hours_driven: 0,\n rest_remaining: 0,\n fuel_rate: 0,\n }));\n return {\n Available: fleet,\n LoadBoard: [],\n Drivers: scenario.drivers,\n Bays: scenario.bays,\n Technicians: scenario.technicians,\n Spares: scenario.spares,\n RecoveryUnits: scenario.recovery_units,\n Conditions: [{ severity_mean: parameters.base_severity_mean, speed_mean: parameters.base_speed_mean, clock: 0 }],\n Rest: [],\n RestEvents: 0,\n };" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "trucks", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "drivers", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "bays", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "technicians", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "spares", + "type": "integer", + "expression": "10", + "exposed": true, + "optimize": null + }, + { + "name": "recovery_units", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "service_wear_limit", + "type": "real", + "expression": "9", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__service_wear_limit", + "expression": "scenario.service_wear_limit", + "optimize": null + } + ], + "places": { + "place__available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "template", + "count": { + "expression": "scenario.trucks", + "optimize": null + }, + "cells": [ + { + "expression": "(i / scenario.trucks) * 0.1", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.08", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "parameters.base_severity_mean", + "optimize": null + }, + { + "expression": "parameters.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__load_board": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__drivers": { + "kind": "uncoloured", + "count": { + "expression": "scenario.drivers", + "optimize": null + } + }, + "place__bays": { + "kind": "uncoloured", + "count": { + "expression": "scenario.bays", + "optimize": null + } + }, + "place__technicians": { + "kind": "uncoloured", + "count": { + "expression": "scenario.technicians", + "optimize": null + } + }, + "place__spares": { + "kind": "uncoloured", + "count": { + "expression": "scenario.spares", + "optimize": null + } + }, + "place__recovery": { + "kind": "uncoloured", + "count": { + "expression": "scenario.recovery_units", + "optimize": null + } + }, + "place__conditions": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "parameters.base_severity_mean", + "optimize": null + }, + { + "expression": "parameters.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__rest": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__rest_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } }, { @@ -1647,8 +1878,239 @@ "param__service_wear_limit": "scenario.service_wear_limit" }, "initialState": { - "type": "code", - "content": "const fleet = range(scenario.trucks).map((index) => ({\n brake_wear: (index / scenario.trucks) * 0.1,\n engine_wear: (index / scenario.trucks) * 0.08,\n tyre_wear: (index / scenario.trucks) * 0.12,\n km_remaining: 0,\n route_distance: 0,\n service_remaining: 0,\n route_class: 0,\n load_due: 0,\n load_revenue: 0,\n age: 0,\n loads_done: 0,\n unplanned: 0,\n road_severity: parameters.base_severity_mean,\n speed_factor: parameters.base_speed_mean,\n conditions_clock: 0,\n fuel_burned: 0,\n hours_driven: 0,\n rest_remaining: 0,\n fuel_rate: 0,\n }));\n return {\n Available: fleet,\n LoadBoard: [],\n Drivers: scenario.drivers,\n Bays: scenario.bays,\n Technicians: scenario.technicians,\n Spares: scenario.spares,\n RecoveryUnits: scenario.recovery_units,\n Conditions: [{ severity_mean: parameters.base_severity_mean, speed_mean: parameters.base_speed_mean, clock: 0 }],\n Rest: [],\n RestEvents: 0,\n };" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "trucks", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "drivers", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "bays", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "technicians", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "spares", + "type": "integer", + "expression": "10", + "exposed": true, + "optimize": null + }, + { + "name": "recovery_units", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "service_wear_limit", + "type": "real", + "expression": "0.5", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__service_wear_limit", + "expression": "scenario.service_wear_limit", + "optimize": null + } + ], + "places": { + "place__available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "template", + "count": { + "expression": "scenario.trucks", + "optimize": null + }, + "cells": [ + { + "expression": "(i / scenario.trucks) * 0.1", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.08", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "parameters.base_severity_mean", + "optimize": null + }, + { + "expression": "parameters.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__load_board": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__drivers": { + "kind": "uncoloured", + "count": { + "expression": "scenario.drivers", + "optimize": null + } + }, + "place__bays": { + "kind": "uncoloured", + "count": { + "expression": "scenario.bays", + "optimize": null + } + }, + "place__technicians": { + "kind": "uncoloured", + "count": { + "expression": "scenario.technicians", + "optimize": null + } + }, + "place__spares": { + "kind": "uncoloured", + "count": { + "expression": "scenario.spares", + "optimize": null + } + }, + "place__recovery": { + "kind": "uncoloured", + "count": { + "expression": "scenario.recovery_units", + "optimize": null + } + }, + "place__conditions": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "parameters.base_severity_mean", + "optimize": null + }, + { + "expression": "parameters.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__rest": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__rest_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } }, { @@ -1696,8 +2158,239 @@ "param__service_wear_limit": "scenario.service_wear_limit" }, "initialState": { - "type": "code", - "content": "const fleet = range(scenario.trucks).map((index) => ({\n brake_wear: (index / scenario.trucks) * 0.1,\n engine_wear: (index / scenario.trucks) * 0.08,\n tyre_wear: (index / scenario.trucks) * 0.12,\n km_remaining: 0,\n route_distance: 0,\n service_remaining: 0,\n route_class: 0,\n load_due: 0,\n load_revenue: 0,\n age: 0,\n loads_done: 0,\n unplanned: 0,\n road_severity: parameters.base_severity_mean,\n speed_factor: parameters.base_speed_mean,\n conditions_clock: 0,\n fuel_burned: 0,\n hours_driven: 0,\n rest_remaining: 0,\n fuel_rate: 0,\n }));\n return {\n Available: fleet,\n LoadBoard: [],\n Drivers: scenario.drivers,\n Bays: scenario.bays,\n Technicians: scenario.technicians,\n Spares: scenario.spares,\n RecoveryUnits: scenario.recovery_units,\n Conditions: [{ severity_mean: parameters.base_severity_mean, speed_mean: parameters.base_speed_mean, clock: 0 }],\n Rest: [],\n RestEvents: 0,\n };" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "trucks", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "drivers", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "bays", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "technicians", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "spares", + "type": "integer", + "expression": "10", + "exposed": true, + "optimize": null + }, + { + "name": "recovery_units", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "service_wear_limit", + "type": "real", + "expression": "0.25", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__service_wear_limit", + "expression": "scenario.service_wear_limit", + "optimize": null + } + ], + "places": { + "place__available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "template", + "count": { + "expression": "scenario.trucks", + "optimize": null + }, + "cells": [ + { + "expression": "(i / scenario.trucks) * 0.1", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.08", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "parameters.base_severity_mean", + "optimize": null + }, + { + "expression": "parameters.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__load_board": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__drivers": { + "kind": "uncoloured", + "count": { + "expression": "scenario.drivers", + "optimize": null + } + }, + "place__bays": { + "kind": "uncoloured", + "count": { + "expression": "scenario.bays", + "optimize": null + } + }, + "place__technicians": { + "kind": "uncoloured", + "count": { + "expression": "scenario.technicians", + "optimize": null + } + }, + "place__spares": { + "kind": "uncoloured", + "count": { + "expression": "scenario.spares", + "optimize": null + } + }, + "place__recovery": { + "kind": "uncoloured", + "count": { + "expression": "scenario.recovery_units", + "optimize": null + } + }, + "place__conditions": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "parameters.base_severity_mean", + "optimize": null + }, + { + "expression": "parameters.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__rest": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__rest_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } }, { @@ -1751,8 +2444,251 @@ "param__severe_route_wear_limit": "scenario.severe_route_wear_limit" }, "initialState": { - "type": "code", - "content": "const fleet = range(scenario.trucks).map((index) => ({\n brake_wear: (index / scenario.trucks) * 0.1,\n engine_wear: (index / scenario.trucks) * 0.08,\n tyre_wear: (index / scenario.trucks) * 0.12,\n km_remaining: 0,\n route_distance: 0,\n service_remaining: 0,\n route_class: 0,\n load_due: 0,\n load_revenue: 0,\n age: 0,\n loads_done: 0,\n unplanned: 0,\n road_severity: parameters.base_severity_mean,\n speed_factor: parameters.base_speed_mean,\n conditions_clock: 0,\n fuel_burned: 0,\n hours_driven: 0,\n rest_remaining: 0,\n fuel_rate: 0,\n }));\n return {\n Available: fleet,\n LoadBoard: [],\n Drivers: scenario.drivers,\n Bays: scenario.bays,\n Technicians: scenario.technicians,\n Spares: scenario.spares,\n RecoveryUnits: scenario.recovery_units,\n Conditions: [{ severity_mean: parameters.base_severity_mean, speed_mean: parameters.base_speed_mean, clock: 0 }],\n Rest: [],\n RestEvents: 0,\n };" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "trucks", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "drivers", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "bays", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "technicians", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "spares", + "type": "integer", + "expression": "10", + "exposed": true, + "optimize": null + }, + { + "name": "recovery_units", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "service_wear_limit", + "type": "real", + "expression": "0.5", + "exposed": true, + "optimize": null + }, + { + "name": "severe_route_wear_limit", + "type": "real", + "expression": "0.35", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__service_wear_limit", + "expression": "scenario.service_wear_limit", + "optimize": null + }, + { + "parameterId": "param__severe_route_wear_limit", + "expression": "scenario.severe_route_wear_limit", + "optimize": null + } + ], + "places": { + "place__available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "template", + "count": { + "expression": "scenario.trucks", + "optimize": null + }, + "cells": [ + { + "expression": "(i / scenario.trucks) * 0.1", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.08", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "parameters.base_severity_mean", + "optimize": null + }, + { + "expression": "parameters.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__load_board": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__drivers": { + "kind": "uncoloured", + "count": { + "expression": "scenario.drivers", + "optimize": null + } + }, + "place__bays": { + "kind": "uncoloured", + "count": { + "expression": "scenario.bays", + "optimize": null + } + }, + "place__technicians": { + "kind": "uncoloured", + "count": { + "expression": "scenario.technicians", + "optimize": null + } + }, + "place__spares": { + "kind": "uncoloured", + "count": { + "expression": "scenario.spares", + "optimize": null + } + }, + "place__recovery": { + "kind": "uncoloured", + "count": { + "expression": "scenario.recovery_units", + "optimize": null + } + }, + "place__conditions": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "parameters.base_severity_mean", + "optimize": null + }, + { + "expression": "parameters.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__rest": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__rest_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } }, { @@ -1800,8 +2736,239 @@ "param__service_wear_limit": "scenario.service_wear_limit" }, "initialState": { - "type": "code", - "content": "const fleet = range(scenario.trucks).map((index) => ({\n brake_wear: (index / scenario.trucks) * 0.1,\n engine_wear: (index / scenario.trucks) * 0.08,\n tyre_wear: (index / scenario.trucks) * 0.12,\n km_remaining: 0,\n route_distance: 0,\n service_remaining: 0,\n route_class: 0,\n load_due: 0,\n load_revenue: 0,\n age: 0,\n loads_done: 0,\n unplanned: 0,\n road_severity: parameters.base_severity_mean,\n speed_factor: parameters.base_speed_mean,\n conditions_clock: 0,\n fuel_burned: 0,\n hours_driven: 0,\n rest_remaining: 0,\n fuel_rate: 0,\n }));\n return {\n Available: fleet,\n LoadBoard: [],\n Drivers: scenario.drivers,\n Bays: scenario.bays,\n Technicians: scenario.technicians,\n Spares: scenario.spares,\n RecoveryUnits: scenario.recovery_units,\n Conditions: [{ severity_mean: parameters.base_severity_mean, speed_mean: parameters.base_speed_mean, clock: 0 }],\n Rest: [],\n RestEvents: 0,\n };" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "trucks", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "drivers", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "bays", + "type": "integer", + "expression": "1", + "exposed": true, + "optimize": null + }, + { + "name": "technicians", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "spares", + "type": "integer", + "expression": "10", + "exposed": true, + "optimize": null + }, + { + "name": "recovery_units", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "service_wear_limit", + "type": "real", + "expression": "0.5", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__service_wear_limit", + "expression": "scenario.service_wear_limit", + "optimize": null + } + ], + "places": { + "place__available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "template", + "count": { + "expression": "scenario.trucks", + "optimize": null + }, + "cells": [ + { + "expression": "(i / scenario.trucks) * 0.1", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.08", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "parameters.base_severity_mean", + "optimize": null + }, + { + "expression": "parameters.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__load_board": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__drivers": { + "kind": "uncoloured", + "count": { + "expression": "scenario.drivers", + "optimize": null + } + }, + "place__bays": { + "kind": "uncoloured", + "count": { + "expression": "scenario.bays", + "optimize": null + } + }, + "place__technicians": { + "kind": "uncoloured", + "count": { + "expression": "scenario.technicians", + "optimize": null + } + }, + "place__spares": { + "kind": "uncoloured", + "count": { + "expression": "scenario.spares", + "optimize": null + } + }, + "place__recovery": { + "kind": "uncoloured", + "count": { + "expression": "scenario.recovery_units", + "optimize": null + } + }, + "place__conditions": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "parameters.base_severity_mean", + "optimize": null + }, + { + "expression": "parameters.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__rest": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__rest_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } }, { @@ -1855,8 +3022,251 @@ "param__parts_lead_time": "scenario.parts_lead_time" }, "initialState": { - "type": "code", - "content": "const fleet = range(scenario.trucks).map((index) => ({\n brake_wear: (index / scenario.trucks) * 0.1,\n engine_wear: (index / scenario.trucks) * 0.08,\n tyre_wear: (index / scenario.trucks) * 0.12,\n km_remaining: 0,\n route_distance: 0,\n service_remaining: 0,\n route_class: 0,\n load_due: 0,\n load_revenue: 0,\n age: 0,\n loads_done: 0,\n unplanned: 0,\n road_severity: parameters.base_severity_mean,\n speed_factor: parameters.base_speed_mean,\n conditions_clock: 0,\n fuel_burned: 0,\n hours_driven: 0,\n rest_remaining: 0,\n fuel_rate: 0,\n }));\n return {\n Available: fleet,\n LoadBoard: [],\n Drivers: scenario.drivers,\n Bays: scenario.bays,\n Technicians: scenario.technicians,\n Spares: scenario.spares,\n RecoveryUnits: scenario.recovery_units,\n Conditions: [{ severity_mean: parameters.base_severity_mean, speed_mean: parameters.base_speed_mean, clock: 0 }],\n Rest: [],\n RestEvents: 0,\n };" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "trucks", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "drivers", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "bays", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "technicians", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "spares", + "type": "integer", + "expression": "1", + "exposed": true, + "optimize": null + }, + { + "name": "recovery_units", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "service_wear_limit", + "type": "real", + "expression": "0.5", + "exposed": true, + "optimize": null + }, + { + "name": "parts_lead_time", + "type": "real", + "expression": "72", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__service_wear_limit", + "expression": "scenario.service_wear_limit", + "optimize": null + }, + { + "parameterId": "param__parts_lead_time", + "expression": "scenario.parts_lead_time", + "optimize": null + } + ], + "places": { + "place__available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "template", + "count": { + "expression": "scenario.trucks", + "optimize": null + }, + "cells": [ + { + "expression": "(i / scenario.trucks) * 0.1", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.08", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "parameters.base_severity_mean", + "optimize": null + }, + { + "expression": "parameters.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__load_board": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__drivers": { + "kind": "uncoloured", + "count": { + "expression": "scenario.drivers", + "optimize": null + } + }, + "place__bays": { + "kind": "uncoloured", + "count": { + "expression": "scenario.bays", + "optimize": null + } + }, + "place__technicians": { + "kind": "uncoloured", + "count": { + "expression": "scenario.technicians", + "optimize": null + } + }, + "place__spares": { + "kind": "uncoloured", + "count": { + "expression": "scenario.spares", + "optimize": null + } + }, + "place__recovery": { + "kind": "uncoloured", + "count": { + "expression": "scenario.recovery_units", + "optimize": null + } + }, + "place__conditions": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "parameters.base_severity_mean", + "optimize": null + }, + { + "expression": "parameters.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__rest": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__rest_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } }, { @@ -1916,8 +3326,263 @@ "param__base_speed_mean": "scenario.base_speed_mean" }, "initialState": { - "type": "code", - "content": "const fleet = range(scenario.trucks).map((index) => ({\n brake_wear: (index / scenario.trucks) * 0.1,\n engine_wear: (index / scenario.trucks) * 0.08,\n tyre_wear: (index / scenario.trucks) * 0.12,\n km_remaining: 0,\n route_distance: 0,\n service_remaining: 0,\n route_class: 0,\n load_due: 0,\n load_revenue: 0,\n age: 0,\n loads_done: 0,\n unplanned: 0,\n road_severity: scenario.base_severity_mean,\n speed_factor: scenario.base_speed_mean,\n conditions_clock: 0,\n fuel_burned: 0,\n hours_driven: 0,\n rest_remaining: 0,\n fuel_rate: 0,\n }));\n return {\n Available: fleet,\n LoadBoard: [],\n Drivers: scenario.drivers,\n Bays: scenario.bays,\n Technicians: scenario.technicians,\n Spares: scenario.spares,\n RecoveryUnits: scenario.recovery_units,\n Conditions: [{ severity_mean: scenario.base_severity_mean, speed_mean: scenario.base_speed_mean, clock: 0 }],\n Rest: [],\n RestEvents: 0,\n };" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "trucks", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "drivers", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "bays", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "technicians", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "spares", + "type": "integer", + "expression": "10", + "exposed": true, + "optimize": null + }, + { + "name": "recovery_units", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "service_wear_limit", + "type": "real", + "expression": "0.5", + "exposed": true, + "optimize": null + }, + { + "name": "base_severity_mean", + "type": "real", + "expression": "1.4", + "exposed": true, + "optimize": null + }, + { + "name": "base_speed_mean", + "type": "real", + "expression": "0.8", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__service_wear_limit", + "expression": "scenario.service_wear_limit", + "optimize": null + }, + { + "parameterId": "param__base_severity_mean", + "expression": "scenario.base_severity_mean", + "optimize": null + }, + { + "parameterId": "param__base_speed_mean", + "expression": "scenario.base_speed_mean", + "optimize": null + } + ], + "places": { + "place__available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "template", + "count": { + "expression": "scenario.trucks", + "optimize": null + }, + "cells": [ + { + "expression": "(i / scenario.trucks) * 0.1", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.08", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "scenario.base_severity_mean", + "optimize": null + }, + { + "expression": "scenario.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__load_board": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__drivers": { + "kind": "uncoloured", + "count": { + "expression": "scenario.drivers", + "optimize": null + } + }, + "place__bays": { + "kind": "uncoloured", + "count": { + "expression": "scenario.bays", + "optimize": null + } + }, + "place__technicians": { + "kind": "uncoloured", + "count": { + "expression": "scenario.technicians", + "optimize": null + } + }, + "place__spares": { + "kind": "uncoloured", + "count": { + "expression": "scenario.spares", + "optimize": null + } + }, + "place__recovery": { + "kind": "uncoloured", + "count": { + "expression": "scenario.recovery_units", + "optimize": null + } + }, + "place__conditions": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "scenario.base_severity_mean", + "optimize": null + }, + { + "expression": "scenario.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__rest": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__rest_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } }, { @@ -1977,8 +3642,263 @@ "param__base_speed_mean": "scenario.base_speed_mean" }, "initialState": { - "type": "code", - "content": "const fleet = range(scenario.trucks).map((index) => ({\n brake_wear: (index / scenario.trucks) * 0.1,\n engine_wear: (index / scenario.trucks) * 0.08,\n tyre_wear: (index / scenario.trucks) * 0.12,\n km_remaining: 0,\n route_distance: 0,\n service_remaining: 0,\n route_class: 0,\n load_due: 0,\n load_revenue: 0,\n age: 0,\n loads_done: 0,\n unplanned: 0,\n road_severity: scenario.base_severity_mean,\n speed_factor: scenario.base_speed_mean,\n conditions_clock: 0,\n fuel_burned: 0,\n hours_driven: 0,\n rest_remaining: 0,\n fuel_rate: 0,\n }));\n return {\n Available: fleet,\n LoadBoard: [],\n Drivers: scenario.drivers,\n Bays: scenario.bays,\n Technicians: scenario.technicians,\n Spares: scenario.spares,\n RecoveryUnits: scenario.recovery_units,\n Conditions: [{ severity_mean: scenario.base_severity_mean, speed_mean: scenario.base_speed_mean, clock: 0 }],\n Rest: [],\n RestEvents: 0,\n };" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "trucks", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "drivers", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "bays", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "technicians", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "spares", + "type": "integer", + "expression": "10", + "exposed": true, + "optimize": null + }, + { + "name": "recovery_units", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "service_wear_limit", + "type": "real", + "expression": "0.5", + "exposed": true, + "optimize": null + }, + { + "name": "base_severity_mean", + "type": "real", + "expression": "0.9", + "exposed": true, + "optimize": null + }, + { + "name": "base_speed_mean", + "type": "real", + "expression": "1.1", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__service_wear_limit", + "expression": "scenario.service_wear_limit", + "optimize": null + }, + { + "parameterId": "param__base_severity_mean", + "expression": "scenario.base_severity_mean", + "optimize": null + }, + { + "parameterId": "param__base_speed_mean", + "expression": "scenario.base_speed_mean", + "optimize": null + } + ], + "places": { + "place__available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "template", + "count": { + "expression": "scenario.trucks", + "optimize": null + }, + "cells": [ + { + "expression": "(i / scenario.trucks) * 0.1", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.08", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "scenario.base_severity_mean", + "optimize": null + }, + { + "expression": "scenario.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__load_board": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__drivers": { + "kind": "uncoloured", + "count": { + "expression": "scenario.drivers", + "optimize": null + } + }, + "place__bays": { + "kind": "uncoloured", + "count": { + "expression": "scenario.bays", + "optimize": null + } + }, + "place__technicians": { + "kind": "uncoloured", + "count": { + "expression": "scenario.technicians", + "optimize": null + } + }, + "place__spares": { + "kind": "uncoloured", + "count": { + "expression": "scenario.spares", + "optimize": null + } + }, + "place__recovery": { + "kind": "uncoloured", + "count": { + "expression": "scenario.recovery_units", + "optimize": null + } + }, + "place__conditions": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "scenario.base_severity_mean", + "optimize": null + }, + { + "expression": "scenario.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__rest": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__rest_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } }, { @@ -2044,8 +3964,275 @@ "param__mountain_rate": "scenario.mountain_rate" }, "initialState": { - "type": "code", - "content": "const fleet = range(scenario.trucks).map((index) => ({\n brake_wear: (index / scenario.trucks) * 0.1,\n engine_wear: (index / scenario.trucks) * 0.08,\n tyre_wear: (index / scenario.trucks) * 0.12,\n km_remaining: 0,\n route_distance: 0,\n service_remaining: 0,\n route_class: 0,\n load_due: 0,\n load_revenue: 0,\n age: 0,\n loads_done: 0,\n unplanned: 0,\n road_severity: parameters.base_severity_mean,\n speed_factor: parameters.base_speed_mean,\n conditions_clock: 0,\n fuel_burned: 0,\n hours_driven: 0,\n rest_remaining: 0,\n fuel_rate: 0,\n }));\n return {\n Available: fleet,\n LoadBoard: [],\n Drivers: scenario.drivers,\n Bays: scenario.bays,\n Technicians: scenario.technicians,\n Spares: scenario.spares,\n RecoveryUnits: scenario.recovery_units,\n Conditions: [{ severity_mean: parameters.base_severity_mean, speed_mean: parameters.base_speed_mean, clock: 0 }],\n Rest: [],\n RestEvents: 0,\n };" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "trucks", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "drivers", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "bays", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "technicians", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "spares", + "type": "integer", + "expression": "10", + "exposed": true, + "optimize": null + }, + { + "name": "recovery_units", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "service_wear_limit", + "type": "real", + "expression": "0.5", + "exposed": true, + "optimize": null + }, + { + "name": "motorway_rate", + "type": "real", + "expression": "0.105", + "exposed": true, + "optimize": null + }, + { + "name": "urban_rate", + "type": "real", + "expression": "0.1425", + "exposed": true, + "optimize": null + }, + { + "name": "mountain_rate", + "type": "real", + "expression": "0.072", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__service_wear_limit", + "expression": "scenario.service_wear_limit", + "optimize": null + }, + { + "parameterId": "param__motorway_rate", + "expression": "scenario.motorway_rate", + "optimize": null + }, + { + "parameterId": "param__urban_rate", + "expression": "scenario.urban_rate", + "optimize": null + }, + { + "parameterId": "param__mountain_rate", + "expression": "scenario.mountain_rate", + "optimize": null + } + ], + "places": { + "place__available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "template", + "count": { + "expression": "scenario.trucks", + "optimize": null + }, + "cells": [ + { + "expression": "(i / scenario.trucks) * 0.1", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.08", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "parameters.base_severity_mean", + "optimize": null + }, + { + "expression": "parameters.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__load_board": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__drivers": { + "kind": "uncoloured", + "count": { + "expression": "scenario.drivers", + "optimize": null + } + }, + "place__bays": { + "kind": "uncoloured", + "count": { + "expression": "scenario.bays", + "optimize": null + } + }, + "place__technicians": { + "kind": "uncoloured", + "count": { + "expression": "scenario.technicians", + "optimize": null + } + }, + "place__spares": { + "kind": "uncoloured", + "count": { + "expression": "scenario.spares", + "optimize": null + } + }, + "place__recovery": { + "kind": "uncoloured", + "count": { + "expression": "scenario.recovery_units", + "optimize": null + } + }, + "place__conditions": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "parameters.base_severity_mean", + "optimize": null + }, + { + "expression": "parameters.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__rest": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__rest_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } }, { @@ -2123,8 +4310,299 @@ "param__mountain_rate": "scenario.mountain_rate" }, "initialState": { - "type": "code", - "content": "const fleet = range(scenario.trucks).map((index) => ({\n brake_wear: (index / scenario.trucks) * 0.1,\n engine_wear: (index / scenario.trucks) * 0.08,\n tyre_wear: (index / scenario.trucks) * 0.12,\n km_remaining: 0,\n route_distance: 0,\n service_remaining: 0,\n route_class: 0,\n load_due: 0,\n load_revenue: 0,\n age: 0,\n loads_done: 0,\n unplanned: 0,\n road_severity: scenario.base_severity_mean,\n speed_factor: scenario.base_speed_mean,\n conditions_clock: 0,\n fuel_burned: 0,\n hours_driven: 0,\n rest_remaining: 0,\n fuel_rate: 0,\n }));\n return {\n Available: fleet,\n LoadBoard: [],\n Drivers: scenario.drivers,\n Bays: scenario.bays,\n Technicians: scenario.technicians,\n Spares: scenario.spares,\n RecoveryUnits: scenario.recovery_units,\n Conditions: [{ severity_mean: scenario.base_severity_mean, speed_mean: scenario.base_speed_mean, clock: 0 }],\n Rest: [],\n RestEvents: 0,\n };" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "trucks", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "drivers", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "bays", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "technicians", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "spares", + "type": "integer", + "expression": "10", + "exposed": true, + "optimize": null + }, + { + "name": "recovery_units", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "service_wear_limit", + "type": "real", + "expression": "0.5", + "exposed": true, + "optimize": null + }, + { + "name": "base_severity_mean", + "type": "real", + "expression": "1.4", + "exposed": true, + "optimize": null + }, + { + "name": "base_speed_mean", + "type": "real", + "expression": "0.8", + "exposed": true, + "optimize": null + }, + { + "name": "motorway_rate", + "type": "real", + "expression": "0.105", + "exposed": true, + "optimize": null + }, + { + "name": "urban_rate", + "type": "real", + "expression": "0.1425", + "exposed": true, + "optimize": null + }, + { + "name": "mountain_rate", + "type": "real", + "expression": "0.072", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__service_wear_limit", + "expression": "scenario.service_wear_limit", + "optimize": null + }, + { + "parameterId": "param__base_severity_mean", + "expression": "scenario.base_severity_mean", + "optimize": null + }, + { + "parameterId": "param__base_speed_mean", + "expression": "scenario.base_speed_mean", + "optimize": null + }, + { + "parameterId": "param__motorway_rate", + "expression": "scenario.motorway_rate", + "optimize": null + }, + { + "parameterId": "param__urban_rate", + "expression": "scenario.urban_rate", + "optimize": null + }, + { + "parameterId": "param__mountain_rate", + "expression": "scenario.mountain_rate", + "optimize": null + } + ], + "places": { + "place__available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "template", + "count": { + "expression": "scenario.trucks", + "optimize": null + }, + "cells": [ + { + "expression": "(i / scenario.trucks) * 0.1", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.08", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "scenario.base_severity_mean", + "optimize": null + }, + { + "expression": "scenario.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__load_board": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__drivers": { + "kind": "uncoloured", + "count": { + "expression": "scenario.drivers", + "optimize": null + } + }, + "place__bays": { + "kind": "uncoloured", + "count": { + "expression": "scenario.bays", + "optimize": null + } + }, + "place__technicians": { + "kind": "uncoloured", + "count": { + "expression": "scenario.technicians", + "optimize": null + } + }, + "place__spares": { + "kind": "uncoloured", + "count": { + "expression": "scenario.spares", + "optimize": null + } + }, + "place__recovery": { + "kind": "uncoloured", + "count": { + "expression": "scenario.recovery_units", + "optimize": null + } + }, + "place__conditions": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "scenario.base_severity_mean", + "optimize": null + }, + { + "expression": "scenario.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__rest": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__rest_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } }, { @@ -2190,8 +4668,275 @@ "param__base_speed_mean": "scenario.base_speed_mean" }, "initialState": { - "type": "code", - "content": "const fleet = range(scenario.trucks).map((index) => ({\n brake_wear: (index / scenario.trucks) * 0.1,\n engine_wear: (index / scenario.trucks) * 0.08,\n tyre_wear: (index / scenario.trucks) * 0.12,\n km_remaining: 0,\n route_distance: 0,\n service_remaining: 0,\n route_class: 0,\n load_due: 0,\n load_revenue: 0,\n age: 0,\n loads_done: 0,\n unplanned: 0,\n road_severity: scenario.base_severity_mean,\n speed_factor: scenario.base_speed_mean,\n conditions_clock: 0,\n fuel_burned: 0,\n hours_driven: 0,\n rest_remaining: 0,\n fuel_rate: 0,\n }));\n return {\n Available: fleet,\n LoadBoard: [],\n Drivers: scenario.drivers,\n Bays: scenario.bays,\n Technicians: scenario.technicians,\n Spares: scenario.spares,\n RecoveryUnits: scenario.recovery_units,\n Conditions: [{ severity_mean: scenario.base_severity_mean, speed_mean: scenario.base_speed_mean, clock: 0 }],\n Rest: [],\n RestEvents: 0,\n };" + "type": "adhoc", + "content": { + "variables": [ + { + "name": "trucks", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "drivers", + "type": "integer", + "expression": "8", + "exposed": true, + "optimize": null + }, + { + "name": "bays", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "technicians", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "spares", + "type": "integer", + "expression": "10", + "exposed": true, + "optimize": null + }, + { + "name": "recovery_units", + "type": "integer", + "expression": "2", + "exposed": true, + "optimize": null + }, + { + "name": "service_wear_limit", + "type": "real", + "expression": "0.5", + "exposed": true, + "optimize": null + }, + { + "name": "severe_route_wear_limit", + "type": "real", + "expression": "0.35", + "exposed": true, + "optimize": null + }, + { + "name": "base_severity_mean", + "type": "real", + "expression": "1.4", + "exposed": true, + "optimize": null + }, + { + "name": "base_speed_mean", + "type": "real", + "expression": "0.8", + "exposed": true, + "optimize": null + } + ], + "netParameters": [ + { + "parameterId": "param__service_wear_limit", + "expression": "scenario.service_wear_limit", + "optimize": null + }, + { + "parameterId": "param__severe_route_wear_limit", + "expression": "scenario.severe_route_wear_limit", + "optimize": null + }, + { + "parameterId": "param__base_severity_mean", + "expression": "scenario.base_severity_mean", + "optimize": null + }, + { + "parameterId": "param__base_speed_mean", + "expression": "scenario.base_speed_mean", + "optimize": null + } + ], + "places": { + "place__available": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "template", + "count": { + "expression": "scenario.trucks", + "optimize": null + }, + "cells": [ + { + "expression": "(i / scenario.trucks) * 0.1", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.08", + "optimize": null + }, + { + "expression": "(i / scenario.trucks) * 0.12", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "scenario.base_severity_mean", + "optimize": null + }, + { + "expression": "scenario.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__load_board": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__drivers": { + "kind": "uncoloured", + "count": { + "expression": "scenario.drivers", + "optimize": null + } + }, + "place__bays": { + "kind": "uncoloured", + "count": { + "expression": "scenario.bays", + "optimize": null + } + }, + "place__technicians": { + "kind": "uncoloured", + "count": { + "expression": "scenario.technicians", + "optimize": null + } + }, + "place__spares": { + "kind": "uncoloured", + "count": { + "expression": "scenario.spares", + "optimize": null + } + }, + "place__recovery": { + "kind": "uncoloured", + "count": { + "expression": "scenario.recovery_units", + "optimize": null + } + }, + "place__conditions": { + "kind": "coloured", + "variables": [], + "rows": [ + { + "kind": "fixed", + "cells": [ + { + "expression": "scenario.base_severity_mean", + "optimize": null + }, + { + "expression": "scenario.base_speed_mean", + "optimize": null + }, + { + "expression": "0", + "optimize": null + } + ] + } + ], + "sharedColumns": {} + }, + "place__rest": { + "kind": "coloured", + "variables": [], + "rows": [], + "sharedColumns": {} + }, + "place__rest_events": { + "kind": "uncoloured", + "count": { + "expression": "0", + "optimize": null + } + } + } + } } } ], diff --git a/libs/@hashintel/petrinaut-core/src/examples/cafe-queue.ts b/libs/@hashintel/petrinaut-core/src/examples/cafe-queue.ts index 2f2e1cfd1e6..bbd2fd8aee1 100644 --- a/libs/@hashintel/petrinaut-core/src/examples/cafe-queue.ts +++ b/libs/@hashintel/petrinaut-core/src/examples/cafe-queue.ts @@ -219,12 +219,66 @@ export default TransitionKernel(() => { param__service_rate: "scenario.service_rate", }, initialState: { - type: "per_place", + type: "adhoc", content: { - place__waiting: "12", - place__free_staff: "3", - place__serving: "0", - place__served: "0", + variables: [ + { + name: "arrival_rate", + type: "real", + expression: "1.2", + exposed: true, + optimize: null, + }, + { + name: "service_rate", + type: "real", + expression: "0.5", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param__arrival_rate", + expression: "scenario.arrival_rate", + optimize: null, + }, + { + parameterId: "param__service_rate", + expression: "scenario.service_rate", + optimize: null, + }, + ], + places: { + place__waiting: { + kind: "uncoloured", + count: { + expression: "12", + optimize: null, + }, + }, + place__free_staff: { + kind: "uncoloured", + count: { + expression: "3", + optimize: null, + }, + }, + place__serving: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place__served: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + }, }, }, }, diff --git a/libs/@hashintel/petrinaut-core/src/examples/deployment-pipeline.ts b/libs/@hashintel/petrinaut-core/src/examples/deployment-pipeline.ts index cb6f1245bc3..af8def71e2a 100644 --- a/libs/@hashintel/petrinaut-core/src/examples/deployment-pipeline.ts +++ b/libs/@hashintel/petrinaut-core/src/examples/deployment-pipeline.ts @@ -791,8 +791,74 @@ return total === 0 ? 0 : failed / total;`, param__incident_resolution_rate: "scenario.resolution_rate", }, initialState: { - type: "per_place", - content: {}, + type: "adhoc", + content: { + variables: [ + { + name: "deployment_rate", + type: "real", + expression: "0.5", + exposed: true, + optimize: null, + }, + { + name: "incident_rate", + type: "real", + expression: "0.1", + exposed: true, + optimize: null, + }, + { + name: "risk_multiplier", + type: "real", + expression: "1", + exposed: true, + optimize: null, + }, + { + name: "mean_size", + type: "real", + expression: "1", + exposed: true, + optimize: null, + }, + { + name: "resolution_rate", + type: "real", + expression: "0.3", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param__deployment_creation_rate", + expression: "scenario.deployment_rate", + optimize: null, + }, + { + parameterId: "param__incident_rate", + expression: "scenario.incident_rate", + optimize: null, + }, + { + parameterId: "param__deployment_risk_multiplier", + expression: "scenario.risk_multiplier", + optimize: null, + }, + { + parameterId: "param__mean_deployment_size", + expression: "scenario.mean_size", + optimize: null, + }, + { + parameterId: "param__incident_resolution_rate", + expression: "scenario.resolution_rate", + optimize: null, + }, + ], + places: {}, + }, }, }, { @@ -829,8 +895,62 @@ return total === 0 ? 0 : failed / total;`, param__incident_resolution_rate: "scenario.resolution_rate", }, initialState: { - type: "per_place", - content: {}, + type: "adhoc", + content: { + variables: [ + { + name: "deployment_rate", + type: "real", + expression: "0.5", + exposed: true, + optimize: null, + }, + { + name: "incident_rate", + type: "real", + expression: "0.35", + exposed: true, + optimize: null, + }, + { + name: "severity_multiplier", + type: "real", + expression: "1.25", + exposed: true, + optimize: null, + }, + { + name: "resolution_rate", + type: "real", + expression: "0.22", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param__deployment_creation_rate", + expression: "scenario.deployment_rate", + optimize: null, + }, + { + parameterId: "param__incident_rate", + expression: "scenario.incident_rate", + optimize: null, + }, + { + parameterId: "param__incident_severity_multiplier", + expression: "scenario.severity_multiplier", + optimize: null, + }, + { + parameterId: "param__incident_resolution_rate", + expression: "scenario.resolution_rate", + optimize: null, + }, + ], + places: {}, + }, }, }, { @@ -867,8 +987,62 @@ return total === 0 ? 0 : failed / total;`, param__incident_rate: "scenario.incident_rate", }, initialState: { - type: "per_place", - content: {}, + type: "adhoc", + content: { + variables: [ + { + name: "deployment_rate", + type: "real", + expression: "1.2", + exposed: true, + optimize: null, + }, + { + name: "finish_rate", + type: "real", + expression: "0.45", + exposed: true, + optimize: null, + }, + { + name: "risk_multiplier", + type: "real", + expression: "1", + exposed: true, + optimize: null, + }, + { + name: "incident_rate", + type: "real", + expression: "0.08", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param__deployment_creation_rate", + expression: "scenario.deployment_rate", + optimize: null, + }, + { + parameterId: "param__deployment_finish_base_rate", + expression: "scenario.finish_rate", + optimize: null, + }, + { + parameterId: "param__deployment_risk_multiplier", + expression: "scenario.risk_multiplier", + optimize: null, + }, + { + parameterId: "param__incident_rate", + expression: "scenario.incident_rate", + optimize: null, + }, + ], + places: {}, + }, }, }, { @@ -911,8 +1085,74 @@ return total === 0 ? 0 : failed / total;`, param__incident_severity_multiplier: "scenario.severity_multiplier", }, initialState: { - type: "per_place", - content: {}, + type: "adhoc", + content: { + variables: [ + { + name: "deployment_rate", + type: "real", + expression: "0.45", + exposed: true, + optimize: null, + }, + { + name: "mean_size", + type: "real", + expression: "1.8", + exposed: true, + optimize: null, + }, + { + name: "risk_multiplier", + type: "real", + expression: "1.75", + exposed: true, + optimize: null, + }, + { + name: "failure_base_rate", + type: "real", + expression: "0.07", + exposed: true, + optimize: null, + }, + { + name: "severity_multiplier", + type: "real", + expression: "1.4", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param__deployment_creation_rate", + expression: "scenario.deployment_rate", + optimize: null, + }, + { + parameterId: "param__mean_deployment_size", + expression: "scenario.mean_size", + optimize: null, + }, + { + parameterId: "param__deployment_risk_multiplier", + expression: "scenario.risk_multiplier", + optimize: null, + }, + { + parameterId: "param__deployment_failure_base_rate", + expression: "scenario.failure_base_rate", + optimize: null, + }, + { + parameterId: "param__incident_severity_multiplier", + expression: "scenario.severity_multiplier", + optimize: null, + }, + ], + places: {}, + }, }, }, ], diff --git a/libs/@hashintel/petrinaut-core/src/examples/drone-patrol.ts b/libs/@hashintel/petrinaut-core/src/examples/drone-patrol.ts index 28863063467..33f47e4c12b 100644 --- a/libs/@hashintel/petrinaut-core/src/examples/drone-patrol.ts +++ b/libs/@hashintel/petrinaut-core/src/examples/drone-patrol.ts @@ -203,22 +203,181 @@ export default Dynamics((tokens, parameters) => { param__drain_rate: "scenario.drain_rate", }, initialState: { - type: "per_place", + type: "adhoc", content: { - // battery, altitude — one row per drone. - place__hangar: [ - [100, 0], - [100, 0], - [100, 0], - [100, 0], - [100, 0], - [100, 0], - [100, 0], - [100, 0], - [100, 0], - [100, 0], + variables: [ + { + name: "launch_rate", + type: "real", + expression: "0.6", + exposed: true, + optimize: null, + }, + { + name: "drain_rate", + type: "real", + expression: "2.5", + exposed: true, + optimize: null, + }, ], - place__airborne: [], + netParameters: [ + { + parameterId: "param__launch_rate", + expression: "scenario.launch_rate", + optimize: null, + }, + { + parameterId: "param__drain_rate", + expression: "scenario.drain_rate", + optimize: null, + }, + ], + places: { + place__hangar: { + kind: "coloured", + variables: [], + rows: [ + { + kind: "fixed", + cells: [ + { + expression: "100", + optimize: null, + }, + { + expression: "0", + optimize: null, + }, + ], + }, + { + kind: "fixed", + cells: [ + { + expression: "100", + optimize: null, + }, + { + expression: "0", + optimize: null, + }, + ], + }, + { + kind: "fixed", + cells: [ + { + expression: "100", + optimize: null, + }, + { + expression: "0", + optimize: null, + }, + ], + }, + { + kind: "fixed", + cells: [ + { + expression: "100", + optimize: null, + }, + { + expression: "0", + optimize: null, + }, + ], + }, + { + kind: "fixed", + cells: [ + { + expression: "100", + optimize: null, + }, + { + expression: "0", + optimize: null, + }, + ], + }, + { + kind: "fixed", + cells: [ + { + expression: "100", + optimize: null, + }, + { + expression: "0", + optimize: null, + }, + ], + }, + { + kind: "fixed", + cells: [ + { + expression: "100", + optimize: null, + }, + { + expression: "0", + optimize: null, + }, + ], + }, + { + kind: "fixed", + cells: [ + { + expression: "100", + optimize: null, + }, + { + expression: "0", + optimize: null, + }, + ], + }, + { + kind: "fixed", + cells: [ + { + expression: "100", + optimize: null, + }, + { + expression: "0", + optimize: null, + }, + ], + }, + { + kind: "fixed", + cells: [ + { + expression: "100", + optimize: null, + }, + { + expression: "0", + optimize: null, + }, + ], + }, + ], + sharedColumns: {}, + }, + place__airborne: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + }, }, }, }, diff --git a/libs/@hashintel/petrinaut-core/src/examples/examples.test.ts b/libs/@hashintel/petrinaut-core/src/examples/examples.test.ts index 327ba705c0a..9382167c005 100644 --- a/libs/@hashintel/petrinaut-core/src/examples/examples.test.ts +++ b/libs/@hashintel/petrinaut-core/src/examples/examples.test.ts @@ -4,7 +4,9 @@ import { compileHirArtifacts } from "../hir"; import { checkSDCPN } from "../lsp/lib/checker"; import { SDCPNLanguageServer } from "../lsp/lib/create-sdcpn-language-service"; import { + cafeQueue, deploymentPipelineSDCPN, + dronePatrol, probabilisticSatellitesSDCPN, productionMachines, sirModel, @@ -14,7 +16,9 @@ import { } from "./index"; const EXAMPLES = [ + cafeQueue, deploymentPipelineSDCPN, + dronePatrol, probabilisticSatellitesSDCPN, productionMachines, sirModel, diff --git a/libs/@hashintel/petrinaut-core/src/examples/production-with-machine-failure.ts b/libs/@hashintel/petrinaut-core/src/examples/production-with-machine-failure.ts index feee304583d..95c43d1252c 100644 --- a/libs/@hashintel/petrinaut-core/src/examples/production-with-machine-failure.ts +++ b/libs/@hashintel/petrinaut-core/src/examples/production-with-machine-failure.ts @@ -565,14 +565,62 @@ return fleet.reduce((sum, m) => sum + m.machine_damage_ratio, 0) / fleet.length; ], parameterOverrides: {}, initialState: { - type: "code", - content: `return { - RawMaterial: scenario.raw_material, - AvailableMachines: Array.from( - { length: scenario.machines_count }, - () => ({ machine_damage_ratio: scenario.initial_machine_damage }), - ), -};`, + type: "adhoc", + content: { + variables: [ + { + name: "raw_material", + type: "integer", + expression: "10", + exposed: true, + optimize: null, + }, + { + name: "machines_count", + type: "integer", + expression: "3", + exposed: true, + optimize: null, + }, + { + name: "initial_machine_damage", + type: "ratio", + expression: "0", + exposed: true, + optimize: null, + }, + ], + netParameters: [], + places: { + "place__d662407f-c56d-4a96-bcbb-ead785a9c594": { + kind: "uncoloured", + count: { + expression: "scenario.raw_material", + optimize: null, + }, + }, + "place__2bdd959f-a5bc-404a-bd03-34fafcef66b8": { + kind: "coloured", + variables: [], + rows: [ + { + kind: "template", + count: { + expression: "scenario.machines_count", + optimize: null, + }, + cells: [ + { + expression: "scenario.initial_machine_damage", + optimize: null, + }, + ], + }, + ], + sharedColumns: {}, + }, + }, + }, }, }, ], diff --git a/libs/@hashintel/petrinaut-core/src/examples/satellites-launcher.test.ts b/libs/@hashintel/petrinaut-core/src/examples/satellites-launcher.test.ts index 9bfe5ae5292..ff0aad83f59 100644 --- a/libs/@hashintel/petrinaut-core/src/examples/satellites-launcher.test.ts +++ b/libs/@hashintel/petrinaut-core/src/examples/satellites-launcher.test.ts @@ -33,7 +33,13 @@ function compile( ): CompiledScenarioResult { const outcome = compileScenario( constellationScenario!, - lowerScenarioToHir(constellationScenario!), + lowerScenarioToHir(constellationScenario!, { + adHocContext: { + places: petriNetDefinition.places, + types: petriNetDefinition.types, + netParameters: petriNetDefinition.parameters, + }, + }), petriNetDefinition.parameters, petriNetDefinition.places, petriNetDefinition.types, diff --git a/libs/@hashintel/petrinaut-core/src/examples/satellites-launcher.ts b/libs/@hashintel/petrinaut-core/src/examples/satellites-launcher.ts index 5ef65b0164a..6bc288f6ad4 100644 --- a/libs/@hashintel/petrinaut-core/src/examples/satellites-launcher.ts +++ b/libs/@hashintel/petrinaut-core/src/examples/satellites-launcher.ts @@ -448,7 +448,62 @@ return sats.reduce((sum, s) => sum + s.velocity, 0) / sats.length;`, "3a4b5c6d-7e8f-9a0b-1c2d-3e4f5a6b7c8d": "scenario.satellite_initial_velocity", }, - initialState: { type: "per_place", content: {} }, + initialState: { + type: "adhoc", + content: { + variables: [ + { + name: "launch_rate", + type: "real", + expression: "0.3", + exposed: true, + optimize: null, + }, + { + name: "satellite_initial_altitude", + type: "real", + expression: "20", + exposed: true, + optimize: null, + }, + { + name: "satellite_initial_velocity", + type: "real", + expression: "11", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "0d1e2f3a-4b5c-6d7e-8f9a-0b1c2d3e4f5a", + expression: "5000", + optimize: null, + }, + { + parameterId: "6f7a8b9c-0d1e-2f3a-4b5c-6d7e8f9a0b1c", + expression: "14", + optimize: null, + }, + { + parameterId: "2f3a4b5c-6d7e-8f9a-0b1c-2d3e4f5a6b7c", + expression: "scenario.launch_rate", + optimize: null, + }, + { + parameterId: "1e2f3a4b-5c6d-7e8f-9a0b-1c2d3e4f5a6b", + expression: "scenario.satellite_initial_altitude", + optimize: null, + }, + { + parameterId: "3a4b5c6d-7e8f-9a0b-1c2d-3e4f5a6b7c8d", + expression: "scenario.satellite_initial_velocity", + optimize: null, + }, + ], + places: {}, + }, + }, }, { id: "scenario__earth_orbit", @@ -477,7 +532,62 @@ return sats.reduce((sum, s) => sum + s.velocity, 0) / sats.length;`, "3a4b5c6d-7e8f-9a0b-1c2d-3e4f5a6b7c8d": "scenario.satellite_initial_velocity", }, - initialState: { type: "per_place", content: {} }, + initialState: { + type: "adhoc", + content: { + variables: [ + { + name: "launch_rate", + type: "real", + expression: "0.5", + exposed: true, + optimize: null, + }, + { + name: "satellite_initial_altitude", + type: "real", + expression: "40", + exposed: true, + optimize: null, + }, + { + name: "satellite_initial_velocity", + type: "real", + expression: "67", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "0d1e2f3a-4b5c-6d7e-8f9a-0b1c2d3e4f5a", + expression: "400000", + optimize: null, + }, + { + parameterId: "6f7a8b9c-0d1e-2f3a-4b5c-6d7e8f9a0b1c", + expression: "50", + optimize: null, + }, + { + parameterId: "2f3a4b5c-6d7e-8f9a-0b1c-2d3e4f5a6b7c", + expression: "scenario.launch_rate", + optimize: null, + }, + { + parameterId: "1e2f3a4b-5c6d-7e8f-9a0b-1c2d3e4f5a6b", + expression: "scenario.satellite_initial_altitude", + optimize: null, + }, + { + parameterId: "3a4b5c6d-7e8f-9a0b-1c2d-3e4f5a6b7c8d", + expression: "scenario.satellite_initial_velocity", + optimize: null, + }, + ], + places: {}, + }, + }, }, { id: "scenario__mars_orbit", @@ -506,7 +616,62 @@ return sats.reduce((sum, s) => sum + s.velocity, 0) / sats.length;`, "3a4b5c6d-7e8f-9a0b-1c2d-3e4f5a6b7c8d": "scenario.satellite_initial_velocity", }, - initialState: { type: "per_place", content: {} }, + initialState: { + type: "adhoc", + content: { + variables: [ + { + name: "launch_rate", + type: "real", + expression: "0.4", + exposed: true, + optimize: null, + }, + { + name: "satellite_initial_altitude", + type: "real", + expression: "25", + exposed: true, + optimize: null, + }, + { + name: "satellite_initial_velocity", + type: "real", + expression: "29", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "0d1e2f3a-4b5c-6d7e-8f9a-0b1c2d3e4f5a", + expression: "43000", + optimize: null, + }, + { + parameterId: "6f7a8b9c-0d1e-2f3a-4b5c-6d7e8f9a0b1c", + expression: "27", + optimize: null, + }, + { + parameterId: "2f3a4b5c-6d7e-8f9a-0b1c-2d3e4f5a6b7c", + expression: "scenario.launch_rate", + optimize: null, + }, + { + parameterId: "1e2f3a4b-5c6d-7e8f-9a0b-1c2d3e4f5a6b", + expression: "scenario.satellite_initial_altitude", + optimize: null, + }, + { + parameterId: "3a4b5c6d-7e8f-9a0b-1c2d-3e4f5a6b7c8d", + expression: "scenario.satellite_initial_velocity", + optimize: null, + }, + ], + places: {}, + }, + }, }, { id: "scenario__solar_orbit", @@ -535,42 +700,150 @@ return sats.reduce((sum, s) => sum + s.velocity, 0) / sats.length;`, "3a4b5c6d-7e8f-9a0b-1c2d-3e4f5a6b7c8d": "scenario.satellite_initial_velocity", }, - initialState: { type: "per_place", content: {} }, + initialState: { + type: "adhoc", + content: { + variables: [ + { + name: "launch_rate", + type: "real", + expression: "0.6", + exposed: true, + optimize: null, + }, + { + name: "satellite_initial_altitude", + type: "real", + expression: "50", + exposed: true, + optimize: null, + }, + { + name: "satellite_initial_velocity", + type: "real", + expression: "196", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "0d1e2f3a-4b5c-6d7e-8f9a-0b1c2d3e4f5a", + expression: "5000000", + optimize: null, + }, + { + parameterId: "6f7a8b9c-0d1e-2f3a-4b5c-6d7e8f9a0b1c", + expression: "80", + optimize: null, + }, + { + parameterId: "2f3a4b5c-6d7e-8f9a-0b1c-2d3e4f5a6b7c", + expression: "scenario.launch_rate", + optimize: null, + }, + { + parameterId: "1e2f3a4b-5c6d-7e8f-9a0b-1c2d3e4f5a6b", + expression: "scenario.satellite_initial_altitude", + optimize: null, + }, + { + parameterId: "3a4b5c6d-7e8f-9a0b-1c2d-3e4f5a6b7c8d", + expression: "scenario.satellite_initial_velocity", + optimize: null, + }, + ], + places: {}, + }, + }, }, { id: "scenario__pre_deployed_constellation", name: "Pre-deployed Constellation", description: - "Starts with a configurable number of satellites already in orbit, evenly spaced in a ring around the planet. The initial state is defined as code from the scenario parameters.", + "Starts with a configurable number of satellites already in orbit, evenly spaced in a ring around the planet. A dynamic row in the ad-hoc scenario form generates the initial state from the scenario parameters.", scenarioParameters: [ { type: "integer", identifier: "number_of_satellites", default: 8 }, { type: "real", identifier: "initial_altitude", default: 40 }, ], parameterOverrides: {}, initialState: { - type: "code", - content: `const distanceToCenter = - parameters.planet_radius + scenario.initial_altitude; - -// Speed of a circular orbit at this radius. The orbit dynamics divide by -// velocity, so a satellite must start moving — a stationary token would make -// the direction derivative 0/0 on the very first step. -const orbitalSpeed = Math.sqrt( - parameters.gravitational_constant / distanceToCenter, -); - -return { - Space: range(scenario.number_of_satellites).map((i) => { - const angle = Math.PI * 2 * (i / scenario.number_of_satellites); - return { - x: Math.cos(angle) * distanceToCenter, - y: Math.sin(angle) * distanceToCenter, - // Tangential heading: a quarter turn ahead of the outward radius. - direction: angle + Math.PI / 2, - velocity: orbitalSpeed, - }; - }), -};`, + type: "adhoc", + content: { + variables: [ + { + name: "number_of_satellites", + type: "integer", + expression: "8", + exposed: true, + optimize: null, + }, + { + name: "initial_altitude", + type: "real", + expression: "40", + exposed: true, + optimize: null, + }, + ], + netParameters: [], + places: { + "3cbc7944-34cb-4eeb-b779-4e392a171fe1": { + kind: "coloured", + variables: [ + { + name: "distanceToCenter", + type: "real", + expression: + "parameters.planet_radius + scenario.initial_altitude", + optimize: null, + }, + { + name: "orbitalSpeed", + type: "real", + expression: + "Math.sqrt(\n parameters.gravitational_constant / distanceToCenter,\n)", + optimize: null, + }, + { + name: "angle", + type: "real", + expression: + "Math.PI * 2 * (i / scenario.number_of_satellites)", + optimize: null, + }, + ], + rows: [ + { + kind: "template", + count: { + expression: "scenario.number_of_satellites", + optimize: null, + }, + cells: [ + { + expression: "Math.cos(angle) * distanceToCenter", + optimize: null, + }, + { + expression: "Math.sin(angle) * distanceToCenter", + optimize: null, + }, + { + expression: "angle + Math.PI / 2", + optimize: null, + }, + { + expression: "orbitalSpeed", + optimize: null, + }, + ], + }, + ], + sharedColumns: {}, + }, + }, + }, }, }, ], diff --git a/libs/@hashintel/petrinaut-core/src/examples/sir-model.ts b/libs/@hashintel/petrinaut-core/src/examples/sir-model.ts index 386557bb519..71d6ac0ad0b 100644 --- a/libs/@hashintel/petrinaut-core/src/examples/sir-model.ts +++ b/libs/@hashintel/petrinaut-core/src/examples/sir-model.ts @@ -159,12 +159,60 @@ return { param__recovery_rate: "0.8", }, initialState: { - type: "per_place", + type: "adhoc", content: { - place__susceptible: - "scenario.population * (1 - scenario.infected_ratio)", - place__infected: "scenario.population * scenario.infected_ratio", - place__recovered: "0", + variables: [ + { + name: "population", + type: "integer", + expression: "1000", + exposed: true, + optimize: null, + }, + { + name: "infected_ratio", + type: "ratio", + expression: "0.01", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param__infection_rate", + expression: "1.5", + optimize: null, + }, + { + parameterId: "param__recovery_rate", + expression: "0.8", + optimize: null, + }, + ], + places: { + place__susceptible: { + kind: "uncoloured", + count: { + expression: + "scenario.population * (1 - scenario.infected_ratio)", + optimize: null, + }, + }, + place__infected: { + kind: "uncoloured", + count: { + expression: "scenario.population * scenario.infected_ratio", + optimize: null, + }, + }, + place__recovered: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + }, }, }, }, @@ -182,12 +230,60 @@ return { param__recovery_rate: "0.5", }, initialState: { - type: "per_place", + type: "adhoc", content: { - place__susceptible: - "scenario.population * (1 - scenario.infected_ratio)", - place__infected: "scenario.population * scenario.infected_ratio", - place__recovered: "0", + variables: [ + { + name: "population", + type: "integer", + expression: "10000", + exposed: true, + optimize: null, + }, + { + name: "infected_ratio", + type: "ratio", + expression: "0.0001", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param__infection_rate", + expression: "6", + optimize: null, + }, + { + parameterId: "param__recovery_rate", + expression: "0.5", + optimize: null, + }, + ], + places: { + place__susceptible: { + kind: "uncoloured", + count: { + expression: + "scenario.population * (1 - scenario.infected_ratio)", + optimize: null, + }, + }, + place__infected: { + kind: "uncoloured", + count: { + expression: "scenario.population * scenario.infected_ratio", + optimize: null, + }, + }, + place__recovered: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + }, }, }, }, @@ -205,12 +301,60 @@ return { param__recovery_rate: "1.2", }, initialState: { - type: "per_place", + type: "adhoc", content: { - place__susceptible: - "scenario.population * (1 - scenario.infected_ratio)", - place__infected: "scenario.population * scenario.infected_ratio", - place__recovered: "0", + variables: [ + { + name: "population", + type: "integer", + expression: "1000", + exposed: true, + optimize: null, + }, + { + name: "infected_ratio", + type: "ratio", + expression: "0.05", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param__infection_rate", + expression: "0.6", + optimize: null, + }, + { + parameterId: "param__recovery_rate", + expression: "1.2", + optimize: null, + }, + ], + places: { + place__susceptible: { + kind: "uncoloured", + count: { + expression: + "scenario.population * (1 - scenario.infected_ratio)", + optimize: null, + }, + }, + place__infected: { + kind: "uncoloured", + count: { + expression: "scenario.population * scenario.infected_ratio", + optimize: null, + }, + }, + place__recovered: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + }, }, }, }, @@ -228,12 +372,60 @@ return { param__recovery_rate: "0.5", }, initialState: { - type: "per_place", + type: "adhoc", content: { - place__susceptible: - "scenario.population * (1 - scenario.infected_ratio)", - place__infected: "scenario.population * scenario.infected_ratio", - place__recovered: "0", + variables: [ + { + name: "population", + type: "integer", + expression: "100000", + exposed: true, + optimize: null, + }, + { + name: "infected_ratio", + type: "ratio", + expression: "0.00005", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param__infection_rate", + expression: "2.5", + optimize: null, + }, + { + parameterId: "param__recovery_rate", + expression: "0.5", + optimize: null, + }, + ], + places: { + place__susceptible: { + kind: "uncoloured", + count: { + expression: + "scenario.population * (1 - scenario.infected_ratio)", + optimize: null, + }, + }, + place__infected: { + kind: "uncoloured", + count: { + expression: "scenario.population * scenario.infected_ratio", + optimize: null, + }, + }, + place__recovered: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + }, }, }, }, diff --git a/libs/@hashintel/petrinaut-core/src/examples/supply-chain-profit.ts b/libs/@hashintel/petrinaut-core/src/examples/supply-chain-profit.ts index 22c8ab9eaee..746272b23d6 100644 --- a/libs/@hashintel/petrinaut-core/src/examples/supply-chain-profit.ts +++ b/libs/@hashintel/petrinaut-core/src/examples/supply-chain-profit.ts @@ -383,13 +383,133 @@ return revenue - variableCost - productionCapacityCost - marketingCost - expedit param_demand_multiplier: "scenario.demand_multiplier", }, initialState: { - type: "per_place", + type: "adhoc", content: { - place_raw_inventory: "200", - place_finished_goods: "100", - place_customer_demand: "0", - place_sold_orders: "0", - place_lost_sales: "0", + variables: [ + { + name: "production_rate", + type: "real", + expression: "125", + exposed: true, + optimize: null, + }, + { + name: "replenishment_aggressiveness", + type: "integer", + expression: "190", + exposed: true, + optimize: null, + }, + { + name: "batch_size", + type: "integer", + expression: "220", + exposed: true, + optimize: null, + }, + { + name: "selling_price", + type: "real", + expression: "37", + exposed: true, + optimize: null, + }, + { + name: "expedite_fraction", + type: "ratio", + expression: "0.33", + exposed: true, + optimize: null, + }, + { + name: "marketing_spend", + type: "real", + expression: "32", + exposed: true, + optimize: null, + }, + { + name: "demand_multiplier", + type: "real", + expression: "1", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param_production_rate", + expression: "scenario.production_rate", + optimize: null, + }, + { + parameterId: "param_replenishment_aggressiveness", + expression: "scenario.replenishment_aggressiveness", + optimize: null, + }, + { + parameterId: "param_batch_size", + expression: "scenario.batch_size", + optimize: null, + }, + { + parameterId: "param_selling_price", + expression: "scenario.selling_price", + optimize: null, + }, + { + parameterId: "param_expedite_fraction", + expression: "scenario.expedite_fraction", + optimize: null, + }, + { + parameterId: "param_marketing_spend", + expression: "scenario.marketing_spend", + optimize: null, + }, + { + parameterId: "param_demand_multiplier", + expression: "scenario.demand_multiplier", + optimize: null, + }, + ], + places: { + place_raw_inventory: { + kind: "uncoloured", + count: { + expression: "200", + optimize: null, + }, + }, + place_finished_goods: { + kind: "uncoloured", + count: { + expression: "100", + optimize: null, + }, + }, + place_customer_demand: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_sold_orders: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_lost_sales: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + }, }, }, }, @@ -421,13 +541,133 @@ return revenue - variableCost - productionCapacityCost - marketingCost - expedit param_demand_multiplier: "scenario.demand_multiplier", }, initialState: { - type: "per_place", + type: "adhoc", content: { - place_raw_inventory: "0", - place_finished_goods: "0", - place_customer_demand: "0", - place_sold_orders: "0", - place_lost_sales: "0", + variables: [ + { + name: "production_rate", + type: "real", + expression: "300", + exposed: true, + optimize: null, + }, + { + name: "replenishment_aggressiveness", + type: "integer", + expression: "160", + exposed: true, + optimize: null, + }, + { + name: "batch_size", + type: "integer", + expression: "600", + exposed: true, + optimize: null, + }, + { + name: "selling_price", + type: "real", + expression: "37", + exposed: true, + optimize: null, + }, + { + name: "expedite_fraction", + type: "ratio", + expression: "0.33", + exposed: true, + optimize: null, + }, + { + name: "marketing_spend", + type: "real", + expression: "32", + exposed: true, + optimize: null, + }, + { + name: "demand_multiplier", + type: "real", + expression: "1", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param_production_rate", + expression: "scenario.production_rate", + optimize: null, + }, + { + parameterId: "param_replenishment_aggressiveness", + expression: "scenario.replenishment_aggressiveness", + optimize: null, + }, + { + parameterId: "param_batch_size", + expression: "scenario.batch_size", + optimize: null, + }, + { + parameterId: "param_selling_price", + expression: "scenario.selling_price", + optimize: null, + }, + { + parameterId: "param_expedite_fraction", + expression: "scenario.expedite_fraction", + optimize: null, + }, + { + parameterId: "param_marketing_spend", + expression: "scenario.marketing_spend", + optimize: null, + }, + { + parameterId: "param_demand_multiplier", + expression: "scenario.demand_multiplier", + optimize: null, + }, + ], + places: { + place_raw_inventory: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_finished_goods: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_customer_demand: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_sold_orders: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_lost_sales: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + }, }, }, }, diff --git a/libs/@hashintel/petrinaut-core/src/examples/supply-chain-with-disruption.ts b/libs/@hashintel/petrinaut-core/src/examples/supply-chain-with-disruption.ts index 0ce27979690..9e90237f023 100644 --- a/libs/@hashintel/petrinaut-core/src/examples/supply-chain-with-disruption.ts +++ b/libs/@hashintel/petrinaut-core/src/examples/supply-chain-with-disruption.ts @@ -1693,26 +1693,203 @@ return orders.reduce((sum, o) => sum + o.age, 0) / orders.length;`, param_initial_finished_goods: "scenario.initial_finished_goods", }, initialState: { - type: "per_place", + type: "adhoc", content: { - place_supplier_a_available: "1", - place_supplier_a_down: "0", - place_supplier_b_available: "1", - place_supplier_b_down: "0", - place_raw_materials: "scenario.initial_raw_materials", - place_finished_goods: "scenario.initial_finished_goods", - place_damaged_inbound: "0", - place_scrap: "0", - place_delivered: "0", - place_lost: "0", - place_cancelled: "0", - place_machine_up: [[0.95, 0.08]], - place_machine_down: [], - place_inbound: [], - place_wip: [], - place_orders: [], - place_backorders: [], - place_outbound: [], + variables: [ + { + name: "demand_multiplier", + type: "real", + expression: "1", + exposed: true, + optimize: null, + }, + { + name: "a_share_bias", + type: "ratio", + expression: "1", + exposed: true, + optimize: null, + }, + { + name: "initial_raw_materials", + type: "integer", + expression: "8", + exposed: true, + optimize: null, + }, + { + name: "initial_finished_goods", + type: "integer", + expression: "12", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param_demand_rate", + expression: + "parameters.demand_rate * scenario.demand_multiplier", + optimize: null, + }, + { + parameterId: "param_supplier_a_order_rate", + expression: + "parameters.supplier_a_order_rate * scenario.a_share_bias", + optimize: null, + }, + { + parameterId: "param_supplier_b_order_rate", + expression: + "parameters.supplier_b_order_rate * (2 - scenario.a_share_bias)", + optimize: null, + }, + { + parameterId: "param_initial_raw_materials", + expression: "scenario.initial_raw_materials", + optimize: null, + }, + { + parameterId: "param_initial_finished_goods", + expression: "scenario.initial_finished_goods", + optimize: null, + }, + ], + places: { + place_supplier_a_available: { + kind: "uncoloured", + count: { + expression: "1", + optimize: null, + }, + }, + place_supplier_a_down: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_supplier_b_available: { + kind: "uncoloured", + count: { + expression: "1", + optimize: null, + }, + }, + place_supplier_b_down: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_raw_materials: { + kind: "uncoloured", + count: { + expression: "scenario.initial_raw_materials", + optimize: null, + }, + }, + place_damaged_inbound: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_finished_goods: { + kind: "uncoloured", + count: { + expression: "scenario.initial_finished_goods", + optimize: null, + }, + }, + place_scrap: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_delivered: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_lost: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_cancelled: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_inbound: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_wip: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_orders: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_backorders: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_outbound: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_machine_up: { + kind: "coloured", + variables: [], + rows: [ + { + kind: "fixed", + cells: [ + { + expression: "0.95", + optimize: null, + }, + { + expression: "0.08", + optimize: null, + }, + ], + }, + ], + sharedColumns: {}, + }, + place_machine_down: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + }, }, }, }, @@ -1754,26 +1931,203 @@ return orders.reduce((sum, o) => sum + o.age, 0) / orders.length;`, param_initial_finished_goods: "scenario.initial_finished_goods", }, initialState: { - type: "per_place", + type: "adhoc", content: { - place_supplier_a_available: "1", - place_supplier_a_down: "0", - place_supplier_b_available: "1", - place_supplier_b_down: "0", - place_raw_materials: "6", - place_finished_goods: "scenario.initial_finished_goods", - place_damaged_inbound: "0", - place_scrap: "0", - place_delivered: "0", - place_lost: "0", - place_cancelled: "0", - place_machine_up: [[0.9, 0.12]], - place_machine_down: [], - place_inbound: [], - place_wip: [], - place_orders: [], - place_backorders: [], - place_outbound: [], + variables: [ + { + name: "demand_multiplier", + type: "real", + expression: "1.8", + exposed: true, + optimize: null, + }, + { + name: "lead_time_multiplier", + type: "real", + expression: "1.7", + exposed: true, + optimize: null, + }, + { + name: "damage_threshold", + type: "real", + expression: "0.78", + exposed: true, + optimize: null, + }, + { + name: "initial_finished_goods", + type: "integer", + expression: "18", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param_demand_rate", + expression: + "parameters.demand_rate * scenario.demand_multiplier", + optimize: null, + }, + { + parameterId: "param_supplier_a_lead_time", + expression: + "parameters.supplier_a_lead_time * scenario.lead_time_multiplier", + optimize: null, + }, + { + parameterId: "param_supplier_b_lead_time", + expression: + "parameters.supplier_b_lead_time * scenario.lead_time_multiplier", + optimize: null, + }, + { + parameterId: "param_inbound_damage_threshold", + expression: "scenario.damage_threshold", + optimize: null, + }, + { + parameterId: "param_initial_finished_goods", + expression: "scenario.initial_finished_goods", + optimize: null, + }, + ], + places: { + place_supplier_a_available: { + kind: "uncoloured", + count: { + expression: "1", + optimize: null, + }, + }, + place_supplier_a_down: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_supplier_b_available: { + kind: "uncoloured", + count: { + expression: "1", + optimize: null, + }, + }, + place_supplier_b_down: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_raw_materials: { + kind: "uncoloured", + count: { + expression: "6", + optimize: null, + }, + }, + place_damaged_inbound: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_finished_goods: { + kind: "uncoloured", + count: { + expression: "scenario.initial_finished_goods", + optimize: null, + }, + }, + place_scrap: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_delivered: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_lost: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_cancelled: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_inbound: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_wip: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_orders: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_backorders: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_outbound: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_machine_up: { + kind: "coloured", + variables: [], + rows: [ + { + kind: "fixed", + cells: [ + { + expression: "0.9", + optimize: null, + }, + { + expression: "0.12", + optimize: null, + }, + ], + }, + ], + sharedColumns: {}, + }, + place_machine_down: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + }, }, }, }, @@ -1806,26 +2160,184 @@ return orders.reduce((sum, o) => sum + o.age, 0) / orders.length;`, param_initial_finished_goods: "scenario.initial_finished_goods", }, initialState: { - type: "per_place", + type: "adhoc", content: { - place_supplier_a_available: "0", - place_supplier_a_down: "1", - place_supplier_b_available: "1", - place_supplier_b_down: "0", - place_raw_materials: "8", - place_finished_goods: "scenario.initial_finished_goods", - place_damaged_inbound: "0", - place_scrap: "0", - place_delivered: "0", - place_lost: "0", - place_cancelled: "0", - place_machine_up: [[0.94, 0.1]], - place_machine_down: [], - place_inbound: [], - place_wip: [], - place_orders: [], - place_backorders: [], - place_outbound: [], + variables: [ + { + name: "a_recovery_rate", + type: "real", + expression: "0.08", + exposed: true, + optimize: null, + }, + { + name: "b_expedite_multiplier", + type: "real", + expression: "1.6", + exposed: true, + optimize: null, + }, + { + name: "initial_finished_goods", + type: "integer", + expression: "10", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param_supplier_a_repair_rate", + expression: "scenario.a_recovery_rate", + optimize: null, + }, + { + parameterId: "param_supplier_b_order_rate", + expression: + "parameters.supplier_b_order_rate * scenario.b_expedite_multiplier", + optimize: null, + }, + { + parameterId: "param_initial_finished_goods", + expression: "scenario.initial_finished_goods", + optimize: null, + }, + ], + places: { + place_supplier_a_available: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_supplier_a_down: { + kind: "uncoloured", + count: { + expression: "1", + optimize: null, + }, + }, + place_supplier_b_available: { + kind: "uncoloured", + count: { + expression: "1", + optimize: null, + }, + }, + place_supplier_b_down: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_raw_materials: { + kind: "uncoloured", + count: { + expression: "8", + optimize: null, + }, + }, + place_damaged_inbound: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_finished_goods: { + kind: "uncoloured", + count: { + expression: "scenario.initial_finished_goods", + optimize: null, + }, + }, + place_scrap: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_delivered: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_lost: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_cancelled: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_inbound: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_wip: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_orders: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_backorders: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_outbound: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_machine_up: { + kind: "coloured", + variables: [], + rows: [ + { + kind: "fixed", + cells: [ + { + expression: "0.94", + optimize: null, + }, + { + expression: "0.1", + optimize: null, + }, + ], + }, + ], + sharedColumns: {}, + }, + place_machine_down: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + }, }, }, }, @@ -1865,26 +2377,197 @@ return orders.reduce((sum, o) => sum + o.age, 0) / orders.length;`, param_initial_raw_materials: "scenario.initial_raw_materials", }, initialState: { - type: "per_place", + type: "adhoc", content: { - place_supplier_a_available: "1", - place_supplier_a_down: "0", - place_supplier_b_available: "1", - place_supplier_b_down: "0", - place_raw_materials: "scenario.initial_raw_materials", - place_finished_goods: "8", - place_damaged_inbound: "0", - place_scrap: "0", - place_delivered: "0", - place_lost: "0", - place_cancelled: "0", - place_machine_up: [[0.96, 0.06]], - place_machine_down: [], - place_inbound: [], - place_wip: [], - place_orders: [], - place_backorders: [], - place_outbound: [], + variables: [ + { + name: "a_order_multiplier", + type: "real", + expression: "0.35", + exposed: true, + optimize: null, + }, + { + name: "b_order_multiplier", + type: "real", + expression: "1.9", + exposed: true, + optimize: null, + }, + { + name: "b_risk_multiplier", + type: "real", + expression: "1.45", + exposed: true, + optimize: null, + }, + { + name: "initial_raw_materials", + type: "integer", + expression: "12", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param_supplier_a_order_rate", + expression: + "parameters.supplier_a_order_rate * scenario.a_order_multiplier", + optimize: null, + }, + { + parameterId: "param_supplier_b_order_rate", + expression: + "parameters.supplier_b_order_rate * scenario.b_order_multiplier", + optimize: null, + }, + { + parameterId: "param_supplier_b_risk_multiplier", + expression: "scenario.b_risk_multiplier", + optimize: null, + }, + { + parameterId: "param_initial_raw_materials", + expression: "scenario.initial_raw_materials", + optimize: null, + }, + ], + places: { + place_supplier_a_available: { + kind: "uncoloured", + count: { + expression: "1", + optimize: null, + }, + }, + place_supplier_a_down: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_supplier_b_available: { + kind: "uncoloured", + count: { + expression: "1", + optimize: null, + }, + }, + place_supplier_b_down: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_raw_materials: { + kind: "uncoloured", + count: { + expression: "scenario.initial_raw_materials", + optimize: null, + }, + }, + place_damaged_inbound: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_finished_goods: { + kind: "uncoloured", + count: { + expression: "8", + optimize: null, + }, + }, + place_scrap: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_delivered: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_lost: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_cancelled: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_inbound: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_wip: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_orders: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_backorders: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_outbound: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_machine_up: { + kind: "coloured", + variables: [], + rows: [ + { + kind: "fixed", + cells: [ + { + expression: "0.96", + optimize: null, + }, + { + expression: "0.06", + optimize: null, + }, + ], + }, + ], + sharedColumns: {}, + }, + place_machine_down: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + }, }, }, }, @@ -1926,26 +2609,203 @@ return orders.reduce((sum, o) => sum + o.age, 0) / orders.length;`, param_initial_finished_goods: "scenario.initial_finished_goods", }, initialState: { - type: "per_place", + type: "adhoc", content: { - place_supplier_a_available: "1", - place_supplier_a_down: "0", - place_supplier_b_available: "1", - place_supplier_b_down: "0", - place_raw_materials: "scenario.initial_raw_materials", - place_finished_goods: "scenario.initial_finished_goods", - place_damaged_inbound: "0", - place_scrap: "0", - place_delivered: "0", - place_lost: "0", - place_cancelled: "0", - place_machine_up: [[1, 0.03]], - place_machine_down: [], - place_inbound: [], - place_wip: [], - place_orders: [], - place_backorders: [], - place_outbound: [], + variables: [ + { + name: "initial_raw_materials", + type: "integer", + expression: "18", + exposed: true, + optimize: null, + }, + { + name: "initial_finished_goods", + type: "integer", + expression: "24", + exposed: true, + optimize: null, + }, + { + name: "maintenance_multiplier", + type: "real", + expression: "2.2", + exposed: true, + optimize: null, + }, + { + name: "supplier_recovery_multiplier", + type: "real", + expression: "1.8", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param_maintenance_rate", + expression: + "parameters.maintenance_rate * scenario.maintenance_multiplier", + optimize: null, + }, + { + parameterId: "param_supplier_a_repair_rate", + expression: + "parameters.supplier_a_repair_rate * scenario.supplier_recovery_multiplier", + optimize: null, + }, + { + parameterId: "param_supplier_b_repair_rate", + expression: + "parameters.supplier_b_repair_rate * scenario.supplier_recovery_multiplier", + optimize: null, + }, + { + parameterId: "param_initial_raw_materials", + expression: "scenario.initial_raw_materials", + optimize: null, + }, + { + parameterId: "param_initial_finished_goods", + expression: "scenario.initial_finished_goods", + optimize: null, + }, + ], + places: { + place_supplier_a_available: { + kind: "uncoloured", + count: { + expression: "1", + optimize: null, + }, + }, + place_supplier_a_down: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_supplier_b_available: { + kind: "uncoloured", + count: { + expression: "1", + optimize: null, + }, + }, + place_supplier_b_down: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_raw_materials: { + kind: "uncoloured", + count: { + expression: "scenario.initial_raw_materials", + optimize: null, + }, + }, + place_damaged_inbound: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_finished_goods: { + kind: "uncoloured", + count: { + expression: "scenario.initial_finished_goods", + optimize: null, + }, + }, + place_scrap: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_delivered: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_lost: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_cancelled: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place_inbound: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_wip: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_orders: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_backorders: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_outbound: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + place_machine_up: { + kind: "coloured", + variables: [], + rows: [ + { + kind: "fixed", + cells: [ + { + expression: "1", + optimize: null, + }, + { + expression: "0.03", + optimize: null, + }, + ], + }, + ], + sharedColumns: {}, + }, + place_machine_down: { + kind: "coloured", + variables: [], + rows: [], + sharedColumns: {}, + }, + }, }, }, }, diff --git a/libs/@hashintel/petrinaut-core/src/examples/vaccination-campaign.test.ts b/libs/@hashintel/petrinaut-core/src/examples/vaccination-campaign.test.ts index e8b20267ee1..472edb267a9 100644 --- a/libs/@hashintel/petrinaut-core/src/examples/vaccination-campaign.test.ts +++ b/libs/@hashintel/petrinaut-core/src/examples/vaccination-campaign.test.ts @@ -29,7 +29,13 @@ const infectedPlace = petriNetDefinition.places.find( const { artifacts } = compileHirArtifacts(petriNetDefinition, undefined, { includeHir: true, }); -const winterWaveHir = lowerScenarioToHir(winterWave); +const winterWaveHir = lowerScenarioToHir(winterWave, { + adHocContext: { + places: petriNetDefinition.places, + types: petriNetDefinition.types, + netParameters: petriNetDefinition.parameters, + }, +}); /** The two levers the optimization stories range over. */ type Levers = { vaccination_coverage: number; contact_reduction: number }; diff --git a/libs/@hashintel/petrinaut-core/src/examples/vaccination-campaign.ts b/libs/@hashintel/petrinaut-core/src/examples/vaccination-campaign.ts index 6978ee0fbe3..019cb268a44 100644 --- a/libs/@hashintel/petrinaut-core/src/examples/vaccination-campaign.ts +++ b/libs/@hashintel/petrinaut-core/src/examples/vaccination-campaign.ts @@ -213,14 +213,82 @@ return { param__contact_reduction: "scenario.contact_reduction", }, initialState: { - type: "per_place", + type: "adhoc", content: { - place__susceptible: - "scenario.population - scenario.initial_infected - Math.round((scenario.population - scenario.initial_infected) * scenario.vaccination_coverage)", - place__infected: "scenario.initial_infected", - place__recovered: "0", - place__vaccinated: - "Math.round((scenario.population - scenario.initial_infected) * scenario.vaccination_coverage)", + variables: [ + { + name: "population", + type: "integer", + expression: "1000", + exposed: true, + optimize: null, + }, + { + name: "initial_infected", + type: "integer", + expression: "20", + exposed: true, + optimize: null, + }, + { + name: "vaccination_coverage", + type: "ratio", + expression: "0.3", + exposed: true, + optimize: null, + }, + { + name: "contact_reduction", + type: "ratio", + expression: "0.2", + exposed: true, + optimize: null, + }, + ], + netParameters: [ + { + parameterId: "param__vaccination_coverage", + expression: "scenario.vaccination_coverage", + optimize: null, + }, + { + parameterId: "param__contact_reduction", + expression: "scenario.contact_reduction", + optimize: null, + }, + ], + places: { + place__susceptible: { + kind: "uncoloured", + count: { + expression: + "scenario.population - scenario.initial_infected - Math.round((scenario.population - scenario.initial_infected) * scenario.vaccination_coverage)", + optimize: null, + }, + }, + place__infected: { + kind: "uncoloured", + count: { + expression: "scenario.initial_infected", + optimize: null, + }, + }, + place__recovered: { + kind: "uncoloured", + count: { + expression: "0", + optimize: null, + }, + }, + place__vaccinated: { + kind: "uncoloured", + count: { + expression: + "Math.round((scenario.population - scenario.initial_infected) * scenario.vaccination_coverage)", + optimize: null, + }, + }, + }, }, }, }, diff --git a/libs/@hashintel/petrinaut-core/src/simulation/authoring/scenario/ad-hoc/scenario-to-ad-hoc-state.test.ts b/libs/@hashintel/petrinaut-core/src/simulation/authoring/scenario/ad-hoc/scenario-to-ad-hoc-state.test.ts index f59e258e903..46a603ef201 100644 --- a/libs/@hashintel/petrinaut-core/src/simulation/authoring/scenario/ad-hoc/scenario-to-ad-hoc-state.test.ts +++ b/libs/@hashintel/petrinaut-core/src/simulation/authoring/scenario/ad-hoc/scenario-to-ad-hoc-state.test.ts @@ -403,7 +403,7 @@ const synthesisContext = (net: SDCPN): AdHocSynthesisContext => ({ const compileOriginal = (candidate: Scenario, net: SDCPN) => { const result = compileScenario( candidate, - lowerScenarioToHir(candidate), + lowerScenarioToHir(candidate, { adHocContext: synthesisContext(net) }), net.parameters, net.places, net.types, @@ -441,13 +441,13 @@ const compileConverted = (candidate: Scenario, net: SDCPN) => { }; describe("adHocStateFromScenario over the core examples", () => { - it("covers every stored kind the examples ship", () => { - expect(exampleScenarios("per_place")).toHaveLength(22); - expect(exampleScenarios("code")).toHaveLength(2); - expect(exampleScenarios("adhoc")).toHaveLength(0); + it("stores every example scenario in the editable ad-hoc format", () => { + expect(exampleScenarios("per_place")).toHaveLength(0); + expect(exampleScenarios("code")).toHaveLength(0); + expect(exampleScenarios("adhoc")).toHaveLength(24); }); - it.each([...exampleScenarios("per_place"), ...exampleScenarios("code")])( + it.each(exampleScenarios("adhoc"))( "%s keeps every scenario parameter identifier verbatim", (_title, candidate, net) => { const converted = adHocStateFromScenario( @@ -466,14 +466,15 @@ describe("adHocStateFromScenario over the core examples", () => { }, ); - it.each(exampleScenarios("per_place"))( - "%s compiles to the same initial state and parameter values once converted", + it.each(exampleScenarios("adhoc"))( + "%s keeps its editable definition and compiled values when reopened", (_title, candidate, net) => { const converted = adHocStateFromScenario( candidate, synthesisContext(net), ); - expect(converted.kind).toBe("per_place"); + expect(converted.kind).toBe("adhoc"); + expect(converted.state).toEqual(candidate.initialState.content); const original = compileOriginal(candidate, net); const viaForm = compileConverted(candidate, net); expect(viaForm.initialState).toEqual(original.initialState); @@ -481,19 +482,9 @@ describe("adHocStateFromScenario over the core examples", () => { }, ); - it.each(exampleScenarios("code"))( - "%s keeps its code body and synthesizes the same parameters and overrides", + it.each(exampleScenarios("adhoc"))( + "%s synthesizes the same exposed parameters and overrides", (_title, candidate, net) => { - const converted = adHocStateFromScenario( - candidate, - synthesisContext(net), - ); - expect(converted.kind).toBe("code"); - if (converted.kind !== "code") { - return; - } - expect(converted.code).toBe(candidate.initialState.content); - expect(converted.state.places).toEqual({}); const synthesized = synthesizeConverted(candidate, net); expect(synthesized.scenarioParameters).toEqual( candidate.scenarioParameters, diff --git a/libs/@hashintel/petrinaut/docs/ad-hoc-scenarios.md b/libs/@hashintel/petrinaut/docs/ad-hoc-scenarios.md index 0d4b5cfbb84..55577aaedd6 100644 --- a/libs/@hashintel/petrinaut/docs/ad-hoc-scenarios.md +++ b/libs/@hashintel/petrinaut/docs/ad-hoc-scenarios.md @@ -16,11 +16,11 @@ The same form appears in three places: The form has up to three sections. Variables come first -- parameter overrides may read them: -- **Variables** -- named values (real, integer, boolean, or ratio -- a real between 0 and 1) written as `scenario.` in every expression below, exactly as scenario parameters are written in scenario code. Use them to drive many values from one number. Add one from the dimmed **Add a variable** line at the bottom of the list: like any cell, a first click selects it and a second click (or Enter, or its gutter's `+`) adds the variable -- or reach it with the down arrow from the last row; the fresh name opens ready to type. Each row starts with a small variable-glyph gutter whose menu offers **Delete variable**, and the add line's gutter shows a `+`. A variable's name edits like any other cell: select it, then press Enter (or click again) to edit, and Enter or Escape to leave. Its type select is a cell too: arrow keys move past it, Enter opens it. In the quick-simulation embedding, Variables sit above Parameters in the left column. +- **Variables** -- named values (real, integer, boolean, or ratio -- a real between 0 and 1) written as `scenario.` in every expression below, exactly as scenario parameters are written in scenario code. Use them to drive many values from one number. Add one from the dimmed **Add a variable** line at the bottom of the list: like any cell, a first click selects it and a second click (or Enter, or its gutter's `+`) adds the variable -- or reach it with the down arrow from the last row; the fresh name opens ready to type. Each row starts with a small variable-glyph gutter whose menu offers **Delete variable**, and the add line's gutter shows a `+`. A variable's name edits like any other cell: select it, then press Enter (or click again) to edit, and Enter or Escape to leave. Its type selector and compact dropdown chevron fit within the cell: arrow keys move past it, Enter opens it. In the quick-simulation embedding, Variables sit above Parameters in the left column. - **Parameters** -- one row per [net-level parameter](petri-net-extensions.md#global-parameters), showing its type and its value. An untouched parameter shows its default quietly, marked with a small `default` tag; enter an expression to override the value for this run -- it may read the Variables above. In the quick-simulation embedding this section sits under Variables in the left column, beside Initial state. -- **Initial state** -- one block per place in the net. Each place's title carries its token colour dot (grey for untyped places). +- **Initial state** -- one block per default starting place. Turn on the compact **Show all places** switch beside the Initial state title and info icon to include the other places. Turn it off to restore the filter. The switch appears only when there are other places to reveal. Each place's title carries its token colour dot (grey for untyped places). Filtering changes only what is visible; all place definitions are kept. -In the experiment panel each section collapses: click the chevron in its header, or focus the header and press Left to collapse and Right to expand. Place headers inside Initial state collapse the same way everywhere, and a collapsed place shows a one-line summary of its rows and token total. In the quick-simulation embedding, places start collapsed. +In the experiment panel each section collapses: click the chevron in its header, or focus the header and press Left to collapse and Right to expand. Place headers inside Initial state collapse the same way everywhere, and a collapsed place shows a one-line summary of its rows and token total. In the quick-simulation embedding, places start collapsed. Left on an expanded place collapses it and keeps focus on its header. Press Left again to move to the neighbouring focus group. Every value in the form is an expression. A first click selects a value; a second click, a double-click, or Enter opens the editor in place: a code input with completion and type checking at exactly the cell's position, the value's path (for example `Space › item 0 › x`) above it, and -- in the experiment panel with sweeps enabled -- the interval toggle below it. Expressions may use your Variables (`scenario.`), net parameters (`parameters.`), and arithmetic -- the same [expression language](scenarios.md#expression-language) scenarios use. Press Enter, Escape, or click elsewhere to close the editor. Escape closes only the innermost thing that is open -- a completion list, a bound edit, the editor itself -- and never the panel or dialog around the form; close those from their own buttons. Closing tidies a valid expression's formatting (spacing, redundant parentheses) without changing its meaning. A value may also be left **empty**: an empty cell reads as its type's neutral value -- 0 for numbers, `false` for booleans, `""` for text, the nil UUID -- shown grayed in the cell, and it is never an error. An empty dynamic-row count means 1 token; an empty place count means 0. @@ -28,6 +28,8 @@ Opening a value with Enter or a second click selects its whole content, so typin ### Keyboard editing and undo +Section headers stack at the top as you scroll. Earlier headers fade slightly; click one to return to that section. Upcoming section headers stay at the bottom; click one to jump ahead. A soft fade marks the edge where content scrolls beneath the headers and clears when you return to the section's start. Spreadsheet text does not select when dragged; text selection remains available inside an open editor. + Every table in the form is a keyboard grid: arrow keys move between cells, phantom rows and type selects included, and moving up from a dynamic row's cells lands on its count strip, so counts and bounds are editable without the mouse. While an editor is open on a value that is just a number (or empty), the up and down arrows step it by 1 (by 10 with Shift held); a ratio steps by 0.1 (by 0.01 with Shift held) and stays between 0 and 1; on a boolean value, Up sets `true` and Down sets `false`; text and UUID values leave the arrows to the editor. Where the form lays its sections out as side-by-side columns (the quick-simulation embedding), vertical arrows stay within a column, and a horizontal arrow at a table's edge crosses into the neighbouring column, returning you to the cell you last used there. Tab keeps its usual browser behaviour throughout the form (inside an open row menu it dismisses the menu, as menus do). A token table's column headers are the grid's top line. In a token table, the left arrow from a row's first cell reaches the **row gutter**: focusing it highlights and selects the whole row, Enter opens the row's menu, and Delete removes the row. The menu is a keyboard menu too: it opens with the current kind focused, arrow keys move through the items, Enter chooses, and Escape returns to the gutter. Every row action lives in that menu -- the row kinds and **Delete row**. The walk does not stop at a table's edge: moving down from a table's last row continues to the next part of the form -- a section header, a place header, the next table -- and moving up continues backwards the same way. Collapsed sections are skipped. @@ -52,7 +54,7 @@ A place with a [token type](petri-net-extensions.md#typed-vs-untyped-places) is Changing a row's kind never loses anything: its count (bounds included) is restored when you change back. The dimmed trailing row is a **phantom row**, and its cells follow the same selection model as every other cell: a first click selects one, and a second click (or Enter, or the row's `+` gutter) materializes a new fixed row. Remove a row from its gutter: the menu offers **Delete row**, and the Delete key removes it directly. In fixed rows, `i` is the row's position in the list and `count` is `1`. -Below the table, at the right, the place's **token total**: a number when every count resolves, otherwise the unresolved counts printed as they are (for example `2 + scenario.n_satellites tokens`). +Each typed place shows its **token total** at the top-right, aligned with its name, whether expanded or collapsed. This applies in Simulation Settings, scenario forms, and experiment forms, including computed-state previews. The total is a number when every count resolves, otherwise the unresolved counts printed as they are (for example `2 + scenario.n_satellites tokens`). ### Shared columns @@ -90,8 +92,8 @@ A saved scenario shown through the form in the experiment panel offers the same Saving keeps your form entries as the scenario's definition, so editing the scenario reopens exactly the form you left. -Selecting a saved ad-hoc scenario in Simulation Settings shows it through the same form, read-only: only the scenario parameters (the exposed Variables) take value edits, for that run alone; auxiliary Variables stay hidden, and the parameter overrides and initial state can be browsed with the usual keyboard navigation but not changed. Editing any scenario opens this form: a scenario saved per place by an earlier version or by the AI assistant opens converted, and saving stores it in the form's format; a scenario that defines its initial state as code keeps that code, shown read-only -- edit its name, description, Variables and Parameters here, or recreate it from the form with a Dynamic row (see [Scenarios](scenarios.md#scenarios-stored-as-code)). Such a scenario stores no form entries, so every Variable must be marked **Scenario Parameter** to be kept -- the form refuses to save one that is not. +Selecting a saved ad-hoc scenario in Simulation Settings shows it through the same form, read-only: only the scenario parameters (the exposed Variables) take value edits, for that run alone. The Parameters and Initial state sections show computed values, updating when you change a scenario parameter. Select a value to see its source expression in a floating cell over the selected value. The expression disappears when focus moves away. Auxiliary Variables stay hidden. Editing any scenario opens this form: a scenario saved per place by an earlier version or by the AI assistant opens converted, and saving stores it in the form's format; a scenario that defines its initial state as code keeps that code, shown read-only -- edit its name, description, Variables and Parameters here, or recreate it from the form with a Dynamic row (see [Scenarios](scenarios.md#scenarios-stored-as-code)). Such a scenario stores no form entries, so every Variable must be marked **Scenario Parameter** to be kept -- the form refuses to save one that is not. ## Errors -Ad-hoc definitions are validated as you type, on the value they belong to, and again when you run. In quick simulation, compile problems also appear in the Simulation Settings error banner; in the experiment panel, in the footer. +Ad-hoc definitions are validated as you type, on the value they belong to, and again when you run. Hover over an underlined value to read its error, or open the value editor to see the error below the input. In quick simulation, compile problems also appear in the Simulation Settings error banner; in the experiment panel, in the footer. diff --git a/libs/@hashintel/petrinaut/docs/examples.md b/libs/@hashintel/petrinaut/docs/examples.md index 6237c5cacfd..bff52a8dca0 100644 --- a/libs/@hashintel/petrinaut/docs/examples.md +++ b/libs/@hashintel/petrinaut/docs/examples.md @@ -2,6 +2,8 @@ Petrinaut includes several built-in example nets accessible from the **hamburger menu** (top-left) under **Load example**. The SIR model is the simplest starting point; the Supply Chain with Disruption net is the most complex. +Bundled scenarios use the [ad-hoc scenario form](ad-hoc-scenarios.md), so you can edit their Variables, parameter overrides, and initial-state tables. Dynamic rows keep generated machine fleets and satellite constellations linked to their scenario parameters. + ## SIR Epidemic Model The classic Susceptible-Infected-Recovered compartmental model from epidemiology, implemented as a stochastic Petri net. @@ -171,12 +173,12 @@ An orbital mechanics simulation: satellites are continuously launched into orbit - **`Distribution.map()` for coordinate conversion** -- a uniform launch angle is sampled once, then `.map()` derives both `x` (cosine) and `y` (sine) from the same underlying sample for a coherent polar-to-cartesian position. - **Predicate transitions based on geometry** -- "Collision" checks the distance between two satellites and "Crash" checks distance from the planet's surface, routing tokens to the Debris place. - **Arc weight 2** on the "Collision" transition -- it consumes two satellites from the Space place at once to evaluate pairwise proximity. -- **Scenarios** -- _Moon Orbit_ (low gravity, gentle arcs) and _Earth Orbit_ (high orbital velocities, frequent launches) preconfigure the gravitational constant, planet radius, and launch parameters. _Pre-deployed Constellation_ defines its initial state [as code](scenarios.md#scenarios-stored-as-code), building a ring of satellites with `range(...).map(...)` from two scenario parameters (`number_of_satellites`, `initial_altitude`). Each satellite starts tangentially at circular-orbit speed, so the whole ring stays in orbit from the first frame. +- **Scenarios** -- _Moon Orbit_ (low gravity, gentle arcs) and _Earth Orbit_ (high orbital velocities, frequent launches) preconfigure the gravitational constant, planet radius, and launch parameters. _Pre-deployed Constellation_ uses a dynamic row in the [ad-hoc scenario form](ad-hoc-scenarios.md) to build a ring of satellites from two scenario parameters (`number_of_satellites`, `initial_altitude`). Each satellite starts tangentially at circular-orbit speed, so the whole ring stays in orbit from the first frame. - **[Metrics](simulation.md)** -- satellites in orbit, debris objects, average orbital radius, and average orbital speed. Its **Average orbital radius** and **Average orbital speed** metrics reduce over the satellites' attributes and compile to the GPU as loops. **Suggested initial state:** no initial tokens needed -- pick a scenario (e.g. _Earth Orbit_) and press Play. The "LaunchSatellite" source transition creates satellites with randomized orbital positions and velocities. Select the Space place and open the visualizer preview to watch the orbits fill up. The velocity for a roughly circular orbit at radius `r` is approximately `sqrt(gravitational_constant / r)`. -**Bundled extras:** five scenarios -- **Moon Orbit**, **Earth Orbit**, **Mars Orbit**, and **Solar Orbit** tune the physical constants for very different orbital regimes, and **Pre-deployed Constellation** starts with a configurable ring of satellites already in orbit (its initial state is stored as code). Switch between them in Simulation Settings to compare. +**Bundled extras:** five scenarios -- **Moon Orbit**, **Earth Orbit**, **Mars Orbit**, and **Solar Orbit** tune the physical constants for very different orbital regimes, and **Pre-deployed Constellation** starts with a configurable ring of satellites already in orbit (its initial state is editable as a dynamic row). Switch between them in Simulation Settings to compare. **Key concepts:** [dynamics](petri-net-extensions.md#differential-equations-dynamics), [visualizers](petri-net-extensions.md#visualizer), [source transitions](useful-patterns.md#source-transitions-exogenous-arrivals), [distributions and `.map()`](petri-net-extensions.md#distributions), [arc weight](useful-patterns.md#arc-weight-for-multi-token-operations), [scenarios](scenarios.md). diff --git a/libs/@hashintel/petrinaut/docs/experiments.md b/libs/@hashintel/petrinaut/docs/experiments.md index 4b094472861..a7cea1f0045 100644 --- a/libs/@hashintel/petrinaut/docs/experiments.md +++ b/libs/@hashintel/petrinaut/docs/experiments.md @@ -39,7 +39,7 @@ experiments are not restored after a reload. With "No scenario" selected, the Scenario section shows the [ad-hoc scenario form](ad-hoc-scenarios.md): define the initial state and parameter values inline for this experiment, without saving a scenario. Left untouched, the experiment runs from the manually-set markings and defaults. The experiments table shows "Ad-hoc scenario" in its Scenario column for such runs. With [Parameter sweeps](#parameter-sweeps) enabled, every numeric value of the form carries the same interval toggle -- see [Interval selections](ad-hoc-scenarios.md#interval-selections-experiments). -With a scenario selected, the Scenario section shows it through the same form: the scenario parameters take value edits in worksheet style -- a ratio parameter's edit applies only between 0 and 1; outside, the form marks it and the run keeps the previous value -- each numeric one with the interval toggle when Parameter sweeps is on, and a collapsed **Computed state** sub-section underneath previews the exact parameter values and initial tokens each run will start with -- computed only when you open it, and recomputed as you change the values above. A swept parameter previews at the start of its range, the first combination the sweep runs, and the preview says so. The preview sits in its own tinted panel and scrolls as one, so a net with many places leaves the rest of the panel in reach. +With a scenario selected, the Scenario section shows it through the same form: the scenario parameters take value edits in worksheet style -- a ratio parameter's edit applies only between 0 and 1; outside, the form marks it and the run keeps the previous value -- each numeric one with the interval toggle when Parameter sweeps is on, and a collapsed **Computed state** sub-section underneath previews the exact parameter values and initial tokens each run will start with -- computed only when you open it, and recomputed as you change the values above. A swept parameter previews at the start of its range, the first combination the sweep runs, and the preview says so. The preview scrolls within a bordered panel, with Parameters and Initial state headers that stack as you scroll. Click a faded earlier header to return to its section, or an upcoming header at the bottom to jump ahead. Scrollbars overlay the content when you hover over a scrollable area, without shifting the columns. It initially shows default starting places; turn on **Show all places** beside Initial state to inspect the rest. The switch appears only when there are other places. Select a computed value to see its source expression in a floating cell over the selected value. The expression disappears when focus moves away. | **Runs** | `1000` | Positive integer; how many independent simulations to run. For a sweep the field reads **Max runs per selection**: each selection refines progressively (8, 25, 100, … 1000, 5000, …) up to this ceiling, so large budgets — 100,000 on the GPU — sharpen the distribution the longer you stay. | | **Time step (dt)** | `0.1` | Same meaning as in single-run simulations (see [Simulation](simulation.md#time-step-dt)). | | **Max time (seconds)** | `180` | Each run advances until simulation time reaches this value, then completes. | @@ -87,6 +87,8 @@ Two consequences worth knowing: - Progress reports the slowest worker's position, so the progress bar never runs ahead of the results behind it. - Several experiments running at once each use the same number of workers, so they compete for cores and all of them slow down. Run them one at a time if you want any single one to finish as fast as possible. +Use arrow keys to move between the form's sections, fields, scenario tables, metrics, and footer actions. Left collapses an expanded section or place; Right expands it. Text fields keep Left and Right for moving the caret until it reaches an edge. Tab follows the usual browser order. + ### Parameter sweeps Parameter sweeps are experimental and off by default. Turn on **Parameter sweeps** under Simulation in the [settings dialog](visual-settings.md#parameter-sweeps-experimental) to get the interval toggle on every numeric value of the experiment form: it reads **Sweep** on its own, and **Optimize** once [In-browser optimization](visual-settings.md#in-browser-optimization-experimental) is on with an optimizer that runs in your browser -- a host whose optimizer runs elsewhere keeps **Sweep**, since a sweep can only be optimized in the browser. Either word means the same thing on the value: an interval instead of one number. diff --git a/libs/@hashintel/petrinaut/docs/simulation.md b/libs/@hashintel/petrinaut/docs/simulation.md index e607ac78cee..18b61365131 100644 --- a/libs/@hashintel/petrinaut/docs/simulation.md +++ b/libs/@hashintel/petrinaut/docs/simulation.md @@ -34,13 +34,13 @@ Quick-action buttons next to the picker let you edit the selected scenario, crea Override values for this run: - With **No scenario** selected: the form's **Parameters** table -- an expression per [net-level parameter](petri-net-extensions.md#global-parameters), the default shown with a `default` tag until you override it; expressions may read the Variables above as `scenario.`. -- With a scenario selected: the **scenario parameters** are shown instead, pre-filled with that scenario's defaults. Net-level parameter values are fixed by the scenario's [parameter overrides](scenarios.md#parameters) and are not editable here. Every selected scenario shows through the [ad-hoc form](ad-hoc-scenarios.md): its scenario parameters take value edits in the left column, and its parameter overrides and initial state sit read-only in the right one -- browsable with the same keyboard navigation, but only a scenario edit (the pencil next to the picker) changes them. A scenario saved from the ad-hoc form shows its definition; any other scenario shows a computed preview of the exact tokens the run will start with, recomputed as you change parameter values (very large places preview their first 100 rows). +- With a scenario selected: the **scenario parameters** are shown instead, pre-filled with that scenario's defaults. Net-level parameter values are fixed by the scenario's [parameter overrides](scenarios.md#parameters) and are not editable here. Every selected scenario shows through the [ad-hoc form](ad-hoc-scenarios.md): its scenario parameters take value edits in the left column, and its parameter overrides and initial state sit read-only in the right one -- browsable with the same keyboard navigation, but only a scenario edit (the pencil next to the picker) changes them. Every scenario shows computed parameter values and the exact tokens the run will start with, recomputed as you change scenario parameters. Select a read-only value to see its source expression in a floating cell over the selected value. The expression disappears when focus moves away. Very large places preview their first 100 rows. Changes here do not modify the parameter definition or the scenario -- they only apply to the simulation. Parameter values are locked while a simulation is running. Reset the simulation to change them. ### Time step (dt) -The time step in seconds per frame. Controls the resolution of ODE integration and how frequently transitions are evaluated. +Set the time step in seconds per frame using the **Time Step** input beside the scenario picker in Simulation Settings. It controls the resolution of ODE integration and how frequently transitions are evaluated. Hover the info icon beside its label for a short explanation. - **Smaller dt** -- finer approximation, but slower computation. - **Larger dt** -- faster, but less accurate for continuous dynamics. @@ -61,6 +61,12 @@ If there are unresolved error-severity [diagnostics](petri-net-extensions.md#dia simulation-settings +### Navigating Simulation Settings + +Use arrow keys to move between the scenario picker, its action buttons, the time-step field, and the tables below. Enter opens a picker or edits a selected table value. Text fields keep Left and Right for moving the caret until it reaches an edge. Tab follows the usual browser order. + +The uppercase section headers stack at the top as you scroll each column. Earlier headers fade slightly; click one to return to that section. Upcoming section headers stay at the bottom; click one to jump ahead. A soft fade marks the edge where content scrolls beneath the headers and clears when you return to the section's start. Informational tooltips are skipped by Tab and arrow-key navigation. Scrollbars overlay the content when you hover over a scrollable area, without shifting the columns. Initial state starts with the places marked **Default starting place** in their properties. Turn on the compact **Show all places** switch beside the Initial state title and info icon to inspect the rest. The switch appears only when the model contains other places. Left collapses an expanded place; Left again moves to the neighbouring focus group. + ## How a frame is computed Each simulation step proceeds in two phases: diff --git a/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/ad-hoc-scenario-form.test.tsx b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/ad-hoc-scenario-form.test.tsx index 6f539ecc131..490bb5cba01 100644 --- a/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/ad-hoc-scenario-form.test.tsx +++ b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/ad-hoc-scenario-form.test.tsx @@ -81,6 +81,7 @@ const context: AdHocSynthesisContext = { name: "Pumps", colorId: "colour-pump", dynamicsEnabled: false, + showAsInitialState: true, differentialEquationId: null, x: 0, y: 0, @@ -90,6 +91,7 @@ const context: AdHocSynthesisContext = { name: "Queue", colorId: null, dynamicsEnabled: false, + showAsInitialState: true, differentialEquationId: null, x: 0, y: 0, @@ -147,6 +149,35 @@ const colouredPlace = (state: AdHocScenarioState | undefined) => { }; describe("AdHocScenarioForm", () => { + it("filters starting places without changing their authored state", async () => { + const onChange = vi.fn(); + render( + ({ + ...place, + showAsInitialState: place.id === "place-queue", + })), + }} + selection="none" + />, + ); + expect(screen.queryByRole("button", { name: "Pumps place" })).toBeNull(); + expect(screen.getByRole("button", { name: "Queue › count" })).toBeTruthy(); + fireEvent.click(screen.getByRole("checkbox", { name: "Show all places" })); + expect( + await screen.findByRole("button", { name: "Pumps place" }), + ).toBeTruthy(); + fireEvent.click(screen.getByRole("checkbox", { name: "Show all places" })); + await waitFor(() => + expect(screen.queryByRole("button", { name: "Pumps place" })).toBeNull(), + ); + expect(onChange).not.toHaveBeenCalled(); + }); + it("selects a row's kind from the gutter menu", async () => { let latest: AdHocScenarioState | undefined; render( @@ -360,7 +391,7 @@ describe("AdHocScenarioForm", () => { expect(place.count.expression).toBe("parameters.rate * 4"); }); - it("renders a synthesis error on the closed slot's trigger", () => { + it("keeps bound errors visible when the editor opens", async () => { const initial: AdHocScenarioState = { variables: [], netParameters: [], @@ -389,7 +420,33 @@ describe("AdHocScenarioForm", () => { const trigger = screen.getByRole("button", { name: "Pumps › item 0 › pressure", }); - expect(trigger.getAttribute("title")).toContain("nope"); + const error = trigger.getAttribute("title"); + expect(error).toBeTruthy(); + fireEvent.click(trigger); + expect((await screen.findByRole("alert")).textContent).toBe(error); + }); + + it("shows an invalid ratio value below valid optimization bounds", async () => { + render( + , + ); + const trigger = screen.getByTitle(/between 0 and 1/); + fireEvent.click(trigger); + expect((await screen.findByRole("alert")).textContent).toContain( + "between 0 and 1", + ); }); it("removes the row when Delete is pressed on its gutter", async () => { @@ -627,11 +684,13 @@ describe("AdHocScenarioForm", () => { it("walks between the form's members and toggles sections from their headers", async () => { render(); - // Variables lead the form; down from the parameters grid (one row) - // lands on the Initial state section header. + // A model with only starting places needs no visibility toggle. const rateValue = screen.getByRole("button", { name: "Rate" }); rateValue.focus(); fireEvent.keyDown(rateValue, { key: "ArrowDown" }); + expect( + screen.queryByRole("checkbox", { name: "Show all places" }), + ).toBeNull(); expect(document.activeElement).toBe( screen.getByRole("button", { name: "Toggle Initial state section" }), ); @@ -1246,6 +1305,16 @@ describe("AdHocScenarioForm", () => { fireEvent.keyDown(addVariable, { key: "ArrowLeft" }); expect(document.activeElement).toBe(optimizeToggle); + pumpsHeader.focus(); + fireEvent.keyDown(pumpsHeader, { key: "ArrowLeft" }); + expect(pumpsHeader.getAttribute("aria-expanded")).toBe("false"); + expect(document.activeElement).toBe(pumpsHeader); + fireEvent.keyDown(pumpsHeader, { key: "ArrowLeft" }); + expect(document.activeElement).toBe(optimizeToggle); + fireEvent.keyDown(optimizeToggle, { key: "ArrowRight" }); + expect(document.activeElement).toBe(pumpsHeader); + fireEvent.keyDown(pumpsHeader, { key: "ArrowRight" }); + // Within the places column the walk still chains: up from the token // table's column header lands on the place's own add-variable line. const pressureHeader = screen.getByRole("button", { diff --git a/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/ad-hoc-scenario-form.tsx b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/ad-hoc-scenario-form.tsx index 4625625f358..7fe3d78ca77 100644 --- a/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/ad-hoc-scenario-form.tsx +++ b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/ad-hoc-scenario-form.tsx @@ -35,6 +35,7 @@ import { use, useEffect, useRef, useState } from "react"; +import { Toggle } from "@hashintel/ds-components"; import { css, cx } from "@hashintel/ds-helpers/css"; import { adHocPlaceStateFor, @@ -46,7 +47,8 @@ import { } from "@hashintel/petrinaut-core"; import { LanguageClientContext } from "../../../react/lsp/context"; -import { FocusRoot, FocusStack } from "../../worksheet/focus-stack"; +import { FocusControls } from "../../worksheet/focus-controls"; +import { FocusStack } from "../../worksheet/focus-stack"; import { useFocusClearance } from "../../worksheet/use-focus-clearance"; import { useFocusHeader } from "../../worksheet/use-focus-member"; import { Section, SectionList } from "../section"; @@ -59,6 +61,8 @@ import { useAdHocLspSession } from "./use-ad-hoc-lsp-session"; import { useAdHocFormHistory } from "./use-form-history"; import { VariableRows } from "./variable-rows"; +export { FormSectionHeader } from "./form-section-header"; + import type { AdHocFocusTarget } from "./dependency-highlight"; import type { AdHocFormMode, @@ -69,6 +73,7 @@ import type { AdHocScenarioState, AdHocSlot, AdHocSynthesisContext, + AdHocValueTarget, } from "@hashintel/petrinaut-core"; // The CSS twin of useFocusClearance (which carries the shared 25px @@ -84,7 +89,22 @@ const focusClearanceStyle = css({ const placesListStyle = css({ display: "flex", flexDirection: "column", + gap: "1", +}); + +const placesVisibilityStyle = css({ + marginLeft: "1", gap: "1.5", + paddingY: "1", + flexShrink: "0", + whiteSpace: "nowrap", + "& [data-part='label']": { fontSize: "[11px]" }, + "& [data-part='control']": { + "--toggle-width": "22px", + "--toggle-height": "12px", + "--toggle-padding": "1px", + "--toggle-thumb-size": "8px", + }, }); export interface AdHocScenarioFormProps { @@ -100,6 +120,7 @@ export interface AdHocScenarioFormProps { * everything else is read-only yet keyboard-navigable and selectable. */ mode?: AdHocFormMode; + expressionFor?: (target: AdHocValueTarget) => string | undefined; /** * Custom arrangement: the host receives each group — already wired to the * form's contexts — and lays them out itself (e.g. Simulation Settings @@ -115,6 +136,7 @@ export interface AdHocScenarioFormProps { variables: React.ReactNode; parameters: React.ReactNode; places: React.ReactNode; + placesVisibilityControl: React.ReactNode; }) => React.ReactNode; /** Classname for the form's root element (the keyboard-handling div). */ className?: string; @@ -144,14 +166,16 @@ const NavigableSection: React.FC<{ title: string; tooltip: string; children: React.ReactNode; -}> = ({ title, tooltip, children }) => { + titleAction?: React.ReactNode; +}> = ({ title, tooltip, children, titleAction }) => { const [open, setOpen] = useState(true); const header = useFocusHeader({ - collapse: () => setOpen(false), - expand: () => setOpen(true), + collapse: open ? () => setOpen(false) : undefined, + expand: open ? undefined : () => setOpen(true), }); return (
{children}
@@ -172,11 +197,13 @@ export const AdHocScenarioForm: React.FC = ({ context, selection, mode = "author", + expressionFor = () => undefined, renderLayout, className, sessionId: externalSessionId, }) => { const sessionId = useAdHocLspSession(state, externalSessionId); + const [showAllPlaces, setShowAllPlaces] = useState(false); const { diagnosticsByUri, requestFormatExpression } = use( LanguageClientContext, ); @@ -300,6 +327,7 @@ export const AdHocScenarioForm: React.FC = ({ setFocusedValue, formatExpression: requestFormatExpression, mode, + expressionFor, dense: renderLayout !== undefined, overlayKeyDown: { capture: handleKeyDown, bubble: stopDeleteKeys }, }; @@ -322,9 +350,44 @@ export const AdHocScenarioForm: React.FC = ({ /> ); + const visiblePlaces = context.places.filter( + (place) => showAllPlaces || place.showAsInitialState, + ); + const hasOtherPlaces = context.places.some( + (place) => !place.showAsInitialState, + ); + const placesVisibilityControl = hasOtherPlaces ? ( + + + + ) : null; const placesList = ( -
- {context.places.map((place) => { +
+ {visiblePlaces.length === 0 ? ( +

+ {hasOtherPlaces + ? "No default starting places. Turn on “Show all places” to inspect the initial state." + : "No places defined."} +

+ ) : null} + {visiblePlaces.map((place) => { const placeState = adHocPlaceStateFor(state, context, place.id); const colour = place.colorId ? context.types.find((type) => type.id === place.colorId) @@ -356,57 +419,57 @@ export const AdHocScenarioForm: React.FC = ({ return ( - - {/* Undo/redo listens in the capture phase, so it sees keys before any + {/* Undo/redo listens in the capture phase, so it sees keys before any cell handler; open text fields and Monaco pass through untouched. */} -
- {renderLayout ? ( - - {renderLayout({ - variables: variableRows, - parameters: parameterRows, - places: placesList, - })} - - ) : ( - - - - {variableRows} - - - {parameterRows ? ( - - {parameterRows} - - ) : null} +
+ {renderLayout ? ( + + {renderLayout({ + variables: variableRows, + parameters: parameterRows, + places: placesList, + placesVisibilityControl, + })} + + ) : ( + + + + {variableRows} + + {parameterRows ? ( - {placesList} + {parameterRows} - - - )} -
- + ) : null} + + + {placesList} + +
+
+ )} +
); }; diff --git a/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/form-context.ts b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/form-context.ts index 63f0c046e85..fe296429675 100644 --- a/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/form-context.ts +++ b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/form-context.ts @@ -79,6 +79,7 @@ export type AdHocFormMode = "author" | "run"; export interface AdHocFormServices { /** What the form lets the user change; see {@link AdHocFormMode}. */ mode: AdHocFormMode; + expressionFor: (target: AdHocValueTarget) => string | undefined; /** The whole form state, as currently edited. */ formState: AdHocScenarioState; /** @@ -139,6 +140,7 @@ export interface AdHocFormServices { export const AdHocFormContext = createContext({ mode: "author", + expressionFor: () => undefined, formState: { variables: [], netParameters: [], places: {} }, dispatch: () => {}, synthesisContext: { netParameters: [], places: [], types: [] }, diff --git a/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/form-section-header.tsx b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/form-section-header.tsx new file mode 100644 index 00000000000..06f9efadaeb --- /dev/null +++ b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/form-section-header.tsx @@ -0,0 +1,53 @@ +import { css } from "@hashintel/ds-helpers/css"; + +import { FocusStack } from "../../worksheet/focus-stack"; +import { PointerHelpTooltip } from "../pointer-help-tooltip"; +import { StackedSectionHeader } from "../stacked-sections"; + +const headerStyle = css({ + position: "sticky", + top: "[0]", + zIndex: "[2]", + display: "flex", + alignItems: "center", + gap: "1", + minHeight: "[28px]", + paddingY: "1", + backgroundColor: "neutral.s00", +}); +const titleStyle = css({ + fontSize: "[var(--form-heading-size, 12px)]", + fontWeight: "semibold", + color: "neutral.a100", + textTransform: "[var(--form-heading-case, none)]", + letterSpacing: "[var(--form-heading-spacing, normal)]", +}); +const actionsStyle = css({ + display: "flex", + alignItems: "center", + gap: "1", + marginLeft: "auto", +}); + +export const FormSectionHeader: React.FC<{ + title: string; + titleAction?: React.ReactNode; + tooltip?: string; + spaceBefore?: boolean; + children?: React.ReactNode; +}> = ({ title, titleAction, tooltip, spaceBefore, children }) => ( + + {(renderTitle) => ( + <> + {renderTitle(title, titleStyle)} + {tooltip ? : null} + {titleAction || children ? ( + + {titleAction} + {children ?
{children}
: null} +
+ ) : null} + + )} +
+); diff --git a/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/parameter-rows.tsx b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/parameter-rows.tsx index 388245a8923..502ab74046e 100644 --- a/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/parameter-rows.tsx +++ b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/parameter-rows.tsx @@ -101,7 +101,7 @@ export const ParameterRows: React.FC = ({ entries }) => { target={target} value={entry} display={ - entry.optimize + entry.optimize || mode === "run" ? undefined : entry.expression || ( diff --git a/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/place-block.tsx b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/place-block.tsx index cec79ba52c1..fb64b394478 100644 --- a/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/place-block.tsx +++ b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/place-block.tsx @@ -6,9 +6,6 @@ * grid-track transition and makes the content inert; collapsed, the place * is one line: its name and a summary of its rows and token total. An * uncoloured place is a header plus one full-width count cell. - * - * The collapse chevron hangs in the left margin, so every place name — - * coloured or not — starts at the same x as the blocks beneath it. */ import { use, useState } from "react"; @@ -31,20 +28,16 @@ import type { } from "@hashintel/petrinaut-core"; const blockStyle = css({ - contentVisibility: "auto", - containIntrinsicSize: "[auto 200px]", display: "flex", flexDirection: "column", gap: "1.5", + "&[data-collapsed]": { gap: "0" }, }); const denseBlockStyle = css({ gap: "1", }); -// One line grammar for places: the fixed title width and line height are -// shared between an uncoloured place's row and a collapsed coloured -// place's header, so counts and collapsed summaries start at the same x. const headerStyle = css({ display: "flex", alignItems: "center", @@ -52,9 +45,6 @@ const headerStyle = css({ minHeight: "[26px]", }); -// The place-name trigger pulls itself left by its padding plus the chevron -// slot, so the dot + name align with the un-chevroned headers and the -// tables below. const placeNameButtonStyle = css({ display: "flex", alignItems: "center", @@ -62,10 +52,11 @@ const placeNameButtonStyle = css({ border: "none", background: "[transparent]", padding: "[2px 4px]", - marginLeft: "[-20px]", + marginLeft: "[-24px]", + minWidth: "[0]", borderRadius: "xs", - fontSize: "sm", - fontWeight: "semibold", + fontSize: "xs", + fontWeight: "medium", color: "neutral.s120", cursor: "pointer", _hover: { backgroundColor: "neutral.s10" }, @@ -76,29 +67,22 @@ const placeNameButtonStyle = css({ }, }); -// Collapsed, the title button takes the shared fixed width (the 20px -// chevron hang included), so the summary aligns with the uncoloured -// places' count cells. -const collapsedTitleButtonStyle = css({ - width: "[190px]", -}); - -const collapsedTitleNameStyle = css({ +const placeTitleNameStyle = css({ flex: "1", minWidth: "[0]", overflow: "hidden", whiteSpace: "nowrap", textAlign: "left", - maskImage: - "[linear-gradient(to right, black calc(100% - 14px), transparent)]", + textOverflow: "ellipsis", }); const chevronStyle = css({ display: "flex", alignItems: "center", justifyContent: "center", - color: "neutral.s70", + color: "neutral.s100", width: "[12px]", + flexShrink: "0", transition: "[transform 0.12s ease]", }); @@ -115,6 +99,8 @@ const colourDotStyle = css({ }); const summaryStyle = css({ + marginLeft: "auto", + flexShrink: "0", fontFamily: "mono", fontSize: "[10px]", color: "neutral.s80", @@ -153,20 +139,9 @@ const placeNameStyle = css({ alignItems: "center", gap: "1", padding: "[2px 0]", - fontSize: "sm", - fontWeight: "semibold", - color: "neutral.s120", -}); - -// The embedded (dense) rendering shrinks the titles a step and tightens -// their padding, so a long place list stays scannable in a panel. -const densePlaceNameStyle = css({ fontSize: "xs", fontWeight: "medium", -}); - -const headerSpacerStyle = css({ - flex: "1", + color: "neutral.s120", }); // An uncoloured place is one line: a fixed-width title, then the count @@ -187,7 +162,8 @@ const uncolouredCountTriggerStyle = css({ }); const uncolouredTitleStyle = css({ - width: "[170px]", + marginLeft: "[-4px]", + width: "[194px]", flexShrink: "0", overflow: "hidden", whiteSpace: "nowrap", @@ -250,22 +226,22 @@ export const ColouredPlaceBlock: React.FC = ({ setEverExpanded(true); } const { attach: attachHeader, onHeaderKeyDown } = useFocusHeader({ - collapse: () => setCollapsed(true), - expand: () => setCollapsed(false), + collapse: collapsed ? undefined : () => setCollapsed(true), + expand: collapsed ? () => setCollapsed(false) : undefined, }); const total = placeTotal(place.id); const totalText = total.resolved ? `${total.total}` : total.text; return ( -
+
- {collapsed ? ( - 0 || (total.resolved && total.total > 0)) && - summaryFilledStyle, - )} - > - {state.rows.length} row{state.rows.length === 1 ? "" : "s"} ·{" "} - {totalText} tokens - - ) : null} - + 0 || (total.resolved && total.total > 0)) && + summaryFilledStyle, + )} + > + {collapsed + ? `${state.rows.length} row${state.rows.length === 1 ? "" : "s"} · ` + : null} + {totalText} tokens +
= ({ place, state, }) => { - const { mode, dense } = use(AdHocFormContext); + const { mode } = use(AdHocFormContext); const target = { kind: "count" as const, placeId: place.id, row: null }; // The count cell is a single-element member: vertical arrows leave to the // neighbouring member, horizontal ones cross into a sibling column. @@ -336,19 +304,13 @@ export const UncolouredPlaceBlock: React.FC = ({ return (
- +
` — the Select drops `className` — and - * the visible box is an unnamed div under `[data-part='root']` styled by - * base-input variables, so the neutralization hits every div beneath the - * root; the dropdown itself is portalled out and keeps its own look. + * Fits the Select and its chevron inside the spreadsheet cell. The visible + * box is the root's direct div, whose ::after draws the chevron; the + * dropdown is portalled out and keeps its own styles. */ export const cellSelectStyle = css({ "& [data-part='root']": { width: "[100%!]", - minWidth: "[100%!]", + minWidth: "[0!]", height: "[28px!]", minHeight: "[0!]", + "--form-min-width": "0px", "--base-input-border-radius": "0px", "--base-input-background-color": "transparent", _hover: { @@ -398,21 +399,21 @@ export const cellSelectStyle = css({ boxShadow: "[none!]", backgroundColor: "[transparent!]", }, - // The trigger fills its cell so every select is the same width and the - // chevron sits at the same x; plain (non-code) face, quiet indicator. + "& [data-part='root'] > div": { + width: "[100%!]", + _after: { + width: "[5px]", + height: "[5px]", + marginLeft: "[6px]", + marginRight: "[8px]", + color: "neutral.s60", + }, + }, "& [data-part='trigger']": { width: "[100%!]", - justifyContent: "space-between", fontSize: "xs", height: "[28px!]", minHeight: "[0!]", paddingY: "[0!]", }, - "& [data-part='indicator']": { - color: "neutral.s60", - }, - "& [data-part='indicator'] svg": { - width: "[11px]", - height: "[11px]", - }, }); diff --git a/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/token-table.tsx b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/token-table.tsx index ea63013f8b1..b6324b9ecca 100644 --- a/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/token-table.tsx +++ b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/token-table.tsx @@ -9,8 +9,7 @@ * puts one value slot directly below the header, and renders the cells * beneath as dimmed derived copies whose clicks edit the shared value. A * phantom trailing row follows the cell selection model — the first click - * selects, the second (or Enter, or the gutter's +) materializes a fixed - * row — and the place's token total sits at the bottom. + * selects, the second (or Enter, or the gutter's +) materializes a fixed row. * * The whole table is a keyboard grid. Arrows and Tab move between cells; * vertical moves pass through the shared-values line and each dynamic row's @@ -132,18 +131,6 @@ const stripEditorOptimizedStyle = css({ backgroundColor: "[transparent]", }); -// The place total sits under the spreadsheet, outside it — one tight line, -// so it doesn't widen the gap to the next place block. -const totalTextStyle = css({ - textAlign: "right", - fontFamily: "mono", - fontSize: "[10px]", - lineHeight: "[1.2]", - color: "neutral.s80", - paddingX: "1", - marginTop: "[1px]", -}); - const targetKey = ({ stopId, column }: FocusStopTarget): string => `${stopId}:${column}`; @@ -158,8 +145,7 @@ export const TokenTable: React.FC = ({ colour, state, }) => { - const { mode, placeTotal, selection, setFocusedValue, dispatch } = - use(AdHocFormContext); + const { mode, selection, setFocusedValue, dispatch } = use(AdHocFormContext); // Run mode: cells and gutters stay focusable and walkable, but nothing // edits and no rows are added or removed. const readOnly = mode === "run"; @@ -198,7 +184,6 @@ export const TokenTable: React.FC = ({ const sharedColumnIndexes = elements.flatMap((element, columnIndex) => state.sharedColumns[element.name] ? [columnIndex] : [], ); - const total = placeTotal(place.id); // Every keyboard-reachable line of the table, top to bottom, declared as // worksheet stops: the column headers, the shared values (a sparse line), @@ -524,179 +509,174 @@ export const TokenTable: React.FC = ({ }; return ( - <> - - - - - {elements.map((element, columnIndex) => { - const shared = Boolean(state.sharedColumns[element.name]); - return ( - + + + + {elements.map((element, columnIndex) => { + const shared = Boolean(state.sharedColumns[element.name]); + return ( + + - - - - - ); - })} - - - - {/* Shared values: one slot directly below each shared header. */} - {hasSharedColumns ? ( - - - - {elements.map((element, columnIndex) => { - const shared = state.sharedColumns[element.name]; - if (!shared) { - return ; - } - const target = { - kind: "column" as const, - placeId: place.id, - column: columnIndex, - }; - return ( - - - onFocusTarget({ - stopId: "shared", - column: columnIndex, - }) - } - onTriggerKeyDown={onKeyDown({ - stopId: "shared", - column: columnIndex, - })} - /> - - ); - })} - - - ) : null} - - {state.rows.map((row, rowIndex) => renderDataRow(row, rowIndex))} + {element.name} + + + + ); + })} + + - {/* Phantom trailing row: a first click selects a phantom cell; a - click on the selected cell, a double-click, or Enter materializes - the row. The gutter's + materializes directly. Run mode adds no - rows, so the line is gone entirely. */} - {readOnly ? null : ( - - materializeRow(0)} - > - {elements.map((element, columnIndex) => ( + {/* Shared values: one slot directly below each shared header. */} + {hasSharedColumns ? ( + + + + {elements.map((element, columnIndex) => { + const shared = state.sharedColumns[element.name]; + if (!shared) { + return ; + } + const target = { + kind: "column" as const, + placeId: place.id, + column: columnIndex, + }; + return ( - + ); return ( <> - + {trigger} + {showSource ? ( + + ) : null} {open && rect ? (
= ({ />
) : null} - {boundsError ? ( -
{boundsError}
+ {error ? ( +
+ {error} +
) : null}
diff --git a/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/value-editor/computed-expression.tsx b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/value-editor/computed-expression.tsx new file mode 100644 index 00000000000..fb9b75f383a --- /dev/null +++ b/libs/@hashintel/petrinaut/src/ui/components/ad-hoc-scenario-form/value-editor/computed-expression.tsx @@ -0,0 +1,110 @@ +import { Portal } from "@ark-ui/react/portal"; +import { useLayoutEffect, useState } from "react"; + +import { usePortalContainerRef } from "@hashintel/ds-components"; +import { css } from "@hashintel/ds-helpers/css"; + +import { OverlayScrollArea } from "../../overlay-scroll-area"; + +const expressionStyle = css({ + position: "fixed", + zIndex: "popover", + display: "flex", + flexDirection: "column", + backgroundColor: "neutral.s00", + color: "neutral.fg.body", + border: "[1px solid {colors.blue.s70}]", + borderRadius: "xs", + boxShadow: "[0 3px 12px -4px rgba(0,0,0,0.18)]", + pointerEvents: "auto", +}); +const codeStyle = css({ + margin: "[0]", + paddingX: "2", + paddingY: "1", + fontFamily: "mono", + fontSize: "[12px]", + lineHeight: "[18px]", + whiteSpace: "pre-wrap", + overflowWrap: "anywhere", + userSelect: "text", +}); + +export const ComputedExpression: React.FC<{ + id: string; + expression: string; + anchorRef: React.RefObject; +}> = ({ id, expression, anchorRef }) => { + const portalContainerRef = usePortalContainerRef(); + const [bounds, setBounds] = useState<{ + top: number; + left: number; + width: number; + minHeight: number; + maxHeight: number; + } | null>(null); + const [visible, setVisible] = useState(true); + useLayoutEffect(() => { + const anchor = anchorRef.current; + if (!anchor) { + return; + } + const measure = () => { + const rect = anchor.getBoundingClientRect(); + const longestLine = Math.max( + ...expression.split("\n").map((line) => line.length), + ); + const width = Math.min( + window.innerWidth - 16, + Math.max(rect.width, Math.min(560, longestLine * 7.3 + 18)), + ); + setBounds({ + top: rect.top, + left: Math.max( + 8, + rect.left + width <= window.innerWidth - 8 + ? rect.left + : rect.right - width, + ), + width, + minHeight: rect.height, + maxHeight: Math.max( + rect.height, + Math.min(240, window.innerHeight - rect.top - 8), + ), + }); + }; + const resize = new ResizeObserver(measure); + resize.observe(anchor); + const intersection = new IntersectionObserver(([entry]) => + setVisible(entry?.isIntersecting ?? false), + ); + intersection.observe(anchor); + window.addEventListener("resize", measure); + window.addEventListener("scroll", measure, true); + measure(); + return () => { + resize.disconnect(); + intersection.disconnect(); + window.removeEventListener("resize", measure); + window.removeEventListener("scroll", measure, true); + }; + }, [anchorRef, expression]); + + return bounds && visible ? ( + +
event.preventDefault()} + style={bounds} + > + +
+            {expression}
+          
+
+
+
+ ) : null; +}; diff --git a/libs/@hashintel/petrinaut/src/ui/components/overlay-scroll-area.tsx b/libs/@hashintel/petrinaut/src/ui/components/overlay-scroll-area.tsx new file mode 100644 index 00000000000..82f78f61ec4 --- /dev/null +++ b/libs/@hashintel/petrinaut/src/ui/components/overlay-scroll-area.tsx @@ -0,0 +1,71 @@ +import { ScrollArea } from "@ark-ui/react/scroll-area"; + +import { css, cx } from "@hashintel/ds-helpers/css"; + +const rootStyle = css({ + display: "flex", + flexDirection: "column", + flex: "[1]", + minHeight: "[0]", + minWidth: "[0]", + overflow: "hidden", +}); +const viewportStyle = css({ + flex: "[1]", + minHeight: "[0]", + minWidth: "[0]", + scrollbarWidth: "[none]", + scrollbarGutter: "auto", + "&::-webkit-scrollbar": { display: "none" }, +}); +const scrollbarStyle = css({ + zIndex: "[4]", + padding: "[2px]", + opacity: "[0]", + pointerEvents: "none", + transition: "[opacity 120ms ease]", + "&[data-hover], &[data-dragging]": { opacity: "[1]", pointerEvents: "auto" }, + "&[data-orientation=vertical]": { width: "[8px]" }, + "&[data-orientation=horizontal]": { height: "[8px]" }, + "&[data-orientation=vertical]:not([data-overflow-y]), &[data-orientation=horizontal]:not([data-overflow-x])": + { display: "none" }, + "@media (prefers-reduced-motion: reduce)": { transition: "[none]" }, +}); +const thumbStyle = css({ + borderRadius: "full", + backgroundColor: "neutral.a60", + "&[data-orientation=horizontal]": { height: "[100%]" }, + "&[data-orientation=vertical]": { width: "[100%]" }, +}); + +export const overlayScrollDrawerBodyStyle = css({ + display: "flex", + overflow: "hidden", +}); +export const overlayScrollDrawerViewportStyle = css({ + paddingX: "[var(--panel-horizontal-padding)]", + paddingBottom: "5", +}); + +export const OverlayScrollArea: React.FC<{ + children: React.ReactNode; + className?: string; + viewportClassName?: string; +}> = ({ children, className, viewportClassName }) => ( + + + + {children} + + + + + + + + + +); diff --git a/libs/@hashintel/petrinaut/src/ui/components/pointer-help-tooltip.test.tsx b/libs/@hashintel/petrinaut/src/ui/components/pointer-help-tooltip.test.tsx new file mode 100644 index 00000000000..87f6b249f51 --- /dev/null +++ b/libs/@hashintel/petrinaut/src/ui/components/pointer-help-tooltip.test.tsx @@ -0,0 +1,31 @@ +/** @vitest-environment jsdom */ +import { cleanup, fireEvent, render, screen } from "@testing-library/react"; +import { afterEach, expect, it } from "vitest"; + +import { FocusControls } from "../worksheet/focus-controls"; +import { PointerHelpTooltip } from "./pointer-help-tooltip"; + +afterEach(cleanup); + +it("keeps informational tooltips out of Tab and arrow navigation after rendering", () => { + const toolbar = (content: string) => ( + + + + + + ); + const { container, rerender } = render(toolbar("Help")); + const trigger = container.querySelector( + '[data-scope="tooltip"][data-part="trigger"]', + ); + expect(trigger?.tabIndex).toBe(-1); + rerender(toolbar("Updated help")); + expect(trigger?.tabIndex).toBe(-1); + const scenario = screen.getByRole("button", { name: "Scenario" }); + scenario.focus(); + fireEvent.keyDown(scenario, { key: "ArrowRight" }); + expect(document.activeElement).toBe( + screen.getByRole("spinbutton", { name: "Time step" }), + ); +}); diff --git a/libs/@hashintel/petrinaut/src/ui/components/pointer-help-tooltip.tsx b/libs/@hashintel/petrinaut/src/ui/components/pointer-help-tooltip.tsx new file mode 100644 index 00000000000..0726a975a45 --- /dev/null +++ b/libs/@hashintel/petrinaut/src/ui/components/pointer-help-tooltip.tsx @@ -0,0 +1,31 @@ +import { useEffect, useRef } from "react"; + +import { HelpTooltip } from "@hashintel/ds-components"; +import { css, cx } from "@hashintel/ds-helpers/css"; + +const wrapperStyle = css({ + display: "inline-flex", + alignItems: "center", + flexShrink: "0", +}); +const iconStyle = css({ top: "[0]", marginLeft: "[0]", display: "block" }); + +export const PointerHelpTooltip: React.FC< + React.ComponentProps +> = ({ className, ...props }) => { + const rootRef = useRef(null); + useEffect(() => { + // DS adds a tab stop to informational icons; these forms reserve stops for controls. + const trigger = rootRef.current?.querySelector( + '[data-scope="tooltip"][data-part="trigger"]', + ); + if (trigger) { + trigger.tabIndex = -1; + } + }); + return ( + + + + ); +}; diff --git a/libs/@hashintel/petrinaut/src/ui/components/scroll-fade.tsx b/libs/@hashintel/petrinaut/src/ui/components/scroll-fade.tsx new file mode 100644 index 00000000000..b49166e4546 --- /dev/null +++ b/libs/@hashintel/petrinaut/src/ui/components/scroll-fade.tsx @@ -0,0 +1,69 @@ +import { css } from "@hashintel/ds-helpers/css"; + +import type { CSSProperties } from "react"; + +const fadeStyle = css({ + position: "absolute", + left: "[0]", + right: "[0]", + pointerEvents: "none", + zIndex: "[3]", + "&[data-animated]": { + transition: "[opacity 150ms ease]", + "@media (prefers-reduced-motion: reduce)": { transition: "[none]" }, + }, +}); + +const layerStyle = css({ + position: "absolute", + inset: "[0]", +}); + +export const ScrollFade: React.FC<{ + edge: "top" | "bottom"; + visible: boolean; + size?: number; + blur?: number; + offset?: CSSProperties["top"]; + color?: string; + animated?: boolean; +}> = ({ + edge, + visible, + size = 16, + blur = 0, + offset = 0, + color = "var(--colors-neutral-s00)", + animated = true, +}) => ( + +); diff --git a/libs/@hashintel/petrinaut/src/ui/components/section.tsx b/libs/@hashintel/petrinaut/src/ui/components/section.tsx index 3ea16ba033b..75f865136a9 100644 --- a/libs/@hashintel/petrinaut/src/ui/components/section.tsx +++ b/libs/@hashintel/petrinaut/src/ui/components/section.tsx @@ -1,10 +1,13 @@ import { Collapsible } from "@ark-ui/react/collapsible"; -import { type ReactNode, use } from "react"; +import { type ReactNode, use, useState } from "react"; import { Button, HelpTooltip } from "@hashintel/ds-components"; import { css, cx } from "@hashintel/ds-helpers/css"; import { UserSettingsContext } from "../../react/state/user-settings-context"; +import { useFocusHeader } from "../worksheet/use-focus-member"; +import { PointerHelpTooltip } from "./pointer-help-tooltip"; +import { StackedSectionHeader, StackedSections } from "./stacked-sections"; // -- SectionList (wrapper) -------------------------------------------------- @@ -22,15 +25,32 @@ const sectionListStyle = css({ interface SectionListProps { children: ReactNode; + stacked?: boolean; } -export const SectionList = ({ children }: SectionListProps) => ( -
{children}
-); +export const SectionList = ({ children, stacked }: SectionListProps) => + stacked ? ( + {children} + ) : ( +
{children}
+ ); // -- Section ----------------------------------------------------------------- +const stackedSectionStyle = css({ + display: "contents", + "&[data-state=open] + [data-section] > [data-stack-anchor]": { + marginTop: "2", + }, +}); +const stackedContentStyle = css({ + paddingBottom: "2", + borderBottom: "[1px solid {colors.neutral.a20}]", + "&[data-part=content]": { overflow: "visible" }, +}); + const sectionStyle = css({ + "&:has([data-stacked-sections]) > [data-part=content]": { overflow: "clip" }, display: "flex", flexDirection: "column", position: "relative", @@ -60,6 +80,8 @@ const fillHeightSectionStyle = css({ }); const headerStyle = css({ + "&[data-stack-header]": { paddingY: "1" }, + "&[data-stack-header]::after": { display: "none" }, position: "sticky", top: "[0]", zIndex: "[2]", @@ -163,6 +185,8 @@ const fillHeightContentStyle = css({ interface SectionProps { title: string; + titleAction?: ReactNode; + stacked?: boolean; tooltip?: string; collapsible?: boolean; defaultOpen?: boolean; @@ -190,6 +214,8 @@ interface SectionProps { export const Section = ({ title, + titleAction, + stacked = false, tooltip, collapsible = false, defaultOpen = true, @@ -205,52 +231,88 @@ export const Section = ({ children, className, }: SectionProps) => { + const [internalOpen, setInternalOpen] = useState(defaultOpen); + const expanded = open ?? internalOpen; + const setExpanded = (next: boolean) => { + setInternalOpen(next); + onOpenChange?.(next); + }; + const header = useFocusHeader({ + collapse: expanded ? () => setExpanded(false) : undefined, + expand: expanded ? undefined : () => setExpanded(true), + }); const headerLeft = ( + renderTitle?: (text: string, className: string) => ReactNode, + ) => (
{renderHeaderLeading?.()} - {title} - {tooltip && } + {renderTitle ? ( + renderTitle(title, titleStyle) + ) : ( + {title} + )} + {tooltip && + (stacked ? ( + + ) : ( + + ))} + {titleAction}
); const { showAnimations } = use(UserSettingsContext); + const renderHeaderContent = ( + renderTitle?: (text: string, className: string) => ReactNode, + ) => ( + <> +
+ {headerLeft(renderTitle)} + {renderHeaderAction &&
{renderHeaderAction()}
} + + + +
+ {renderStickyBand && ( +
{renderStickyBand()}
+ )} + + ); + if (collapsible) { return ( onOpenChange(details.open) : undefined - } + open={expanded} + onOpenChange={(details) => setExpanded(details.open)} lazyMount={unmountOnCollapse} unmountOnExit={unmountOnCollapse} - className={cx(sectionStyle, className)} + data-section + className={cx(stacked ? stackedSectionStyle : sectionStyle, className)} > -
-
- {headerLeft} - {renderHeaderAction &&
{renderHeaderAction()}
} - - - + {stacked ? ( + + {renderHeaderContent} + + ) : ( +
+ {renderHeaderContent()}
- {renderStickyBand && ( -
{renderStickyBand()}
- )} -
+ )}
{children}
@@ -261,6 +323,7 @@ export const Section = ({ return (
-
+
- {headerLeft} + {headerLeft()} {renderHeaderAction &&
{renderHeaderAction()}
}
{renderStickyBand && ( diff --git a/libs/@hashintel/petrinaut/src/ui/components/spreadsheet.tsx b/libs/@hashintel/petrinaut/src/ui/components/spreadsheet.tsx index d3fb8cc181a..1641b76f300 100644 --- a/libs/@hashintel/petrinaut/src/ui/components/spreadsheet.tsx +++ b/libs/@hashintel/petrinaut/src/ui/components/spreadsheet.tsx @@ -49,7 +49,7 @@ const tableContainerStyle = css({ borderWidth: "[1px]", borderStyle: "solid", borderColor: "neutral.bd.subtle", - borderRadius: "sm", + borderRadius: "md", overflow: "auto", width: "[100%]", backgroundColor: "neutral.s10", diff --git a/libs/@hashintel/petrinaut/src/ui/components/stacked-sections.test.tsx b/libs/@hashintel/petrinaut/src/ui/components/stacked-sections.test.tsx new file mode 100644 index 00000000000..cfb1ec48798 --- /dev/null +++ b/libs/@hashintel/petrinaut/src/ui/components/stacked-sections.test.tsx @@ -0,0 +1,134 @@ +/** @vitest-environment jsdom */ +import { + cleanup, + fireEvent, + render, + screen, + waitFor, +} from "@testing-library/react"; +import { afterEach, expect, it, vi } from "vitest"; + +import { StackedSectionHeader, StackedSections } from "./stacked-sections"; + +const sectionNames = ["Variables", "Parameters", "Initial state"]; + +afterEach(() => { + cleanup(); + vi.restoreAllMocks(); + vi.unstubAllGlobals(); +}); + +it("stacks previous headings and returns to the selected section in its own scroll area", async () => { + vi.stubGlobal( + "ResizeObserver", + class { + observe() {} + disconnect() {} + }, + ); + vi.stubGlobal("matchMedia", () => ({ matches: true })); + const scrollTo = vi.fn(); + vi.spyOn(HTMLElement.prototype, "getBoundingClientRect").mockImplementation( + function measureSection(this: HTMLElement) { + const scroller = this.closest('[data-testid="scroll-area"]'); + const headers = Array.from( + scroller?.querySelectorAll("[data-stack-header]") ?? [], + ); + const header = this.hasAttribute("data-stack-anchor") + ? this.nextElementSibling + : this; + const index = headers.indexOf(header as Element); + const top = + index < 0 ? 100 : 112 + index * 200 - (scroller?.scrollTop ?? 0); + return { + top, + bottom: top + 32, + height: 32, + left: 0, + right: 400, + width: 400, + x: 0, + y: top, + toJSON: () => ({}), + }; + }, + ); + render( +
+ + {sectionNames.map((name) => ( +
+ + {(title) => title(name)} + +
{name} content
+
+ ))} +
+
, + ); + const variables = screen.getByRole("button", { name: "Back to Variables" }); + const parameters = screen.getByRole("button", { + name: /(?:Back|Go) to Parameters/, + }); + const initialState = screen.getByRole("button", { + name: /(?:Back|Go) to Initial state/, + }); + expect(variables.tabIndex).toBe(-1); + const scroller = screen.getByTestId("scroll-area"); + scroller.scrollTo = scrollTo; + Object.defineProperty(scroller, "clientHeight", { value: 220 }); + Object.defineProperty(scroller, "scrollHeight", { + get: () => + 450 + + Number.parseFloat( + scroller.querySelector("[data-stack-tail]")?.style + .height ?? "0", + ), + }); + fireEvent.scroll(scroller); + await waitFor(() => + expect(parameters.getAttribute("aria-label")).toBe("Go to Parameters"), + ); + expect(initialState.tabIndex).toBe(0); + await waitFor(() => + expect( + scroller.querySelector("[data-stack-tail]")?.style.height, + ).toBe("118px"), + ); + expect( + parameters.closest("[data-stack-header]")?.style.bottom, + ).toBe("16px"); + expect( + initialState.closest("[data-stack-header]")?.style.bottom, + ).toBe("-16px"); + fireEvent.click(initialState); + expect(scrollTo).toHaveBeenLastCalledWith({ top: 348, behavior: "instant" }); + scroller.scrollTop = 400; + fireEvent.scroll(scroller); + await waitFor(() => expect(variables.tabIndex).toBe(0)); + expect(parameters.tabIndex).toBe(0); + expect(initialState.tabIndex).toBe(-1); + expect( + initialState.closest("[data-stack-header]")?.style.top, + ).toBe("52px"); + fireEvent.click(parameters); + expect(scrollTo).toHaveBeenCalledWith({ top: 180, behavior: "instant" }); + const parameterFade = parameters + .closest("[data-stack-header]") + ?.querySelector('[data-scroll-fade="top"]'); + scroller.scrollTop = 183; + fireEvent.scroll(scroller); + await waitFor(() => expect(parameterFade?.style.opacity).toBe("1")); + scroller.scrollTop = 180.5; + fireEvent.scroll(scroller); + await waitFor(() => expect(parameterFade?.style.opacity).toBe("0")); + fireEvent.click(variables); + expect(scrollTo).toHaveBeenLastCalledWith({ top: 12, behavior: "instant" }); + scroller.scrollTop = 0; + fireEvent.scroll(scroller); + await waitFor(() => expect(variables.tabIndex).toBe(-1)); +}); diff --git a/libs/@hashintel/petrinaut/src/ui/components/stacked-sections.tsx b/libs/@hashintel/petrinaut/src/ui/components/stacked-sections.tsx new file mode 100644 index 00000000000..e18fdb983d5 --- /dev/null +++ b/libs/@hashintel/petrinaut/src/ui/components/stacked-sections.tsx @@ -0,0 +1,350 @@ +import { + createContext, + use, + useId, + useLayoutEffect, + useRef, + useState, +} from "react"; + +import { css, cx } from "@hashintel/ds-helpers/css"; + +import { UserSettingsContext } from "../../react/state/user-settings-context"; +import { FocusControls } from "../worksheet/focus-controls"; +import { ScrollFade } from "./scroll-fade"; + +interface HeaderPosition { + id: string; + top: number; + inactive: boolean; + upcoming: boolean; + bottom: number; + topFade: boolean; + bottomFade: boolean; +} + +const StackContext = createContext<{ + positions: HeaderPosition[]; + jump: (id: string) => void; +} | null>(null); + +const stackStyle = css({ + display: "flex", + flexDirection: "column", + minWidth: "[0]", +}); +const headerStyle = css({ + position: "sticky", + zIndex: "[3]", + backgroundColor: "neutral.s00", + flexShrink: "0", + "&[data-inactive] > :not([data-scroll-fade])": { opacity: "[0.6]" }, +}); +const animatedStyle = css({ + "& > *": { transition: "[opacity 160ms ease]" }, + "@media (prefers-reduced-motion: reduce)": { + "& > *": { transition: "[none]" }, + }, +}); +const anchorStyle = css({ + height: "[0]", + flexShrink: "0", + pointerEvents: "none", +}); +const sectionSpacingStyle = css({ marginTop: "3" }); +const titleButtonStyle = css({ + color: "[inherit]", + font: "inherit", + textAlign: "left", + border: "none", + padding: "[0]", + background: "[transparent]", + cursor: "pointer", + borderRadius: "xs", + "&[tabindex='-1']": { cursor: "default" }, + _focusVisible: { + outline: "[2px solid {colors.blue.s70}]", + outlineOffset: "[2px]", + }, +}); + +const scrollContentTop = (element: HTMLElement) => { + const paddingTop = Number.parseFloat(getComputedStyle(element).paddingTop); + return ( + element.getBoundingClientRect().top + + element.clientTop + + (Number.isFinite(paddingTop) ? paddingTop : 0) + ); +}; + +export const StackedSections: React.FC<{ + children: React.ReactNode; + className?: string; +}> = ({ children, className }) => { + const rootRef = useRef(null); + const scrollRef = useRef(null); + const [positions, setPositions] = useState([]); + const [trailingSpace, setTrailingSpace] = useState(0); + const { showAnimations } = use(UserSettingsContext); + + useLayoutEffect(() => { + const root = rootRef.current; + if (!root) { + return; + } + let scroller: HTMLElement | null = root; + while ( + scroller && + !/(auto|scroll)/.test(getComputedStyle(scroller).overflowY) + ) { + scroller = scroller.parentElement; + } + if (!scroller) { + return; + } + scrollRef.current = scroller; + let frame = 0; + const update = () => { + const headers = Array.from( + root.querySelectorAll("[data-stack-header]"), + ).filter((header) => header.closest("[data-stacked-sections]") === root); + let top = -( + Number.parseFloat(getComputedStyle(scroller).paddingTop) || 0 + ); + // A drawer's containing section may already pin its own header above this stack. + let parent = root.parentElement; + while (parent && parent !== scroller) { + if (parent.hasAttribute("data-section")) { + const header = parent.querySelector( + ":scope > [data-section-header]", + ); + if (header) { + top += header.getBoundingClientRect().height; + } + } + parent = parent.parentElement; + } + const scrollTop = scrollContentTop(scroller); + let active = 0; + const paddingBottom = + Number.parseFloat(getComputedStyle(scroller).paddingBottom) || 0; + const scrollBottom = + scroller.getBoundingClientRect().top + + scroller.clientTop + + scroller.clientHeight; + const next = headers + .map((header, index) => { + const id = header.dataset.stackHeader ?? ""; + const anchor = header.previousElementSibling; + const position = { + id, + top, + inactive: false, + upcoming: false, + bottom: 0, + topFade: false, + bottomFade: false, + }; + if ( + anchor && + anchor.getBoundingClientRect().top <= scrollTop + top + 1 + ) { + active = index; + } + top += header.getBoundingClientRect().height; + return position; + }) + .map((position, index) => ({ ...position, inactive: index < active })); + let bottom = 0; + let firstUpcoming = -1; + for (let index = next.length - 1; index >= 0; index--) { + const position = next[index]; + const header = headers[index]; + if (!position || !header) { + continue; + } + position.bottom = bottom - paddingBottom; + const height = header.getBoundingClientRect().height; + const anchorTop = + header.previousElementSibling?.getBoundingClientRect().top ?? 0; + position.upcoming = + index > active && anchorTop + height > scrollBottom - bottom + 1; + if (position.upcoming) { + firstUpcoming = index; + } + bottom += height; + } + const activePosition = next[active]; + if (activePosition) { + const anchorTop = + headers[active]?.previousElementSibling?.getBoundingClientRect() + .top ?? 0; + activePosition.topFade = anchorTop < scrollTop + activePosition.top - 2; + } + const upcomingPosition = next[firstUpcoming]; + if (upcomingPosition) { + upcomingPosition.bottomFade = true; + } + const lastPosition = next.at(-1); + const lastAnchor = headers.at(-1)?.previousElementSibling; + const tail = root.querySelector( + ":scope > [data-stack-tail]", + ); + if (lastPosition && lastAnchor && tail && scroller.clientHeight > 0) { + const currentSpace = Number.parseFloat(tail.style.height) || 0; + const targetScroll = + scroller.scrollTop + + lastAnchor.getBoundingClientRect().top - + scrollTop - + lastPosition.top; + const availableScroll = + scroller.scrollHeight - scroller.clientHeight - currentSpace; + setTrailingSpace( + Math.max(0, Math.ceil(targetScroll - availableScroll)), + ); + } + setPositions((previous) => + previous.length === next.length && + previous.every((position, index) => { + const candidate = next[index]; + return ( + candidate?.id === position.id && + candidate.top === position.top && + candidate.inactive === position.inactive && + candidate.upcoming === position.upcoming && + candidate.bottom === position.bottom && + candidate.topFade === position.topFade && + candidate.bottomFade === position.bottomFade + ); + }) + ? previous + : next, + ); + }; + const schedule = () => { + cancelAnimationFrame(frame); + frame = requestAnimationFrame(update); + }; + const resize = new ResizeObserver(schedule); + resize.observe(root); + resize.observe(scroller); + const mutations = new MutationObserver(schedule); + mutations.observe(root, { childList: true, subtree: true }); + scroller.addEventListener("scroll", schedule, { passive: true }); + update(); + return () => { + cancelAnimationFrame(frame); + resize.disconnect(); + mutations.disconnect(); + scroller.removeEventListener("scroll", schedule); + scrollRef.current = null; + }; + }, []); + + const jump = (id: string) => { + const root = rootRef.current; + const scroller = scrollRef.current; + const anchor = Array.from( + root?.querySelectorAll("[data-stack-anchor]") ?? [], + ).find((element) => element.dataset.stackAnchor === id); + if (!scroller || !anchor) { + return; + } + const top = positions.find((position) => position.id === id)?.top ?? 0; + scroller.scrollTo({ + top: + scroller.scrollTop + + anchor.getBoundingClientRect().top - + scrollContentTop(scroller) - + top, + behavior: + showAnimations && + !window.matchMedia("(prefers-reduced-motion: reduce)").matches + ? "smooth" + : "instant", + }); + }; + + return ( + +
+ {children} + + + ); +}; + +export const StackedSectionHeader: React.FC<{ + className?: string; + spaceBefore?: boolean; + children: ( + title: (text: string, className?: string) => React.ReactNode, + ) => React.ReactNode; +}> = ({ className, spaceBefore, children }) => { + const id = useId(); + const stack = use(StackContext); + const position = stack?.positions.find((entry) => entry.id === id); + const { showAnimations } = use(UserSettingsContext); + const title = (text: string, titleClassName?: string) => + stack ? ( + + + + ) : ( + {text} + ); + return ( + <> + ); diff --git a/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/BottomPanel/subviews/simulation-settings.tsx b/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/BottomPanel/subviews/simulation-settings.tsx index ff6ee76c335..b742e69b2df 100644 --- a/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/BottomPanel/subviews/simulation-settings.tsx +++ b/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/BottomPanel/subviews/simulation-settings.tsx @@ -3,12 +3,11 @@ import { use, useState } from "react"; import { Banner, Button, - HelpTooltip, Icon, NumberInput, Select, } from "@hashintel/ds-components"; -import { css, cva, cx } from "@hashintel/ds-helpers/css"; +import { css, cx } from "@hashintel/ds-helpers/css"; import { classicRunParameterValues, classicRunVariables, @@ -26,8 +25,14 @@ import { SDCPNContext } from "../../../../../../react/state/sdcpn-context"; import { AdHocScenarioForm, FormLayoutColumn, + FormSectionHeader, } from "../../../../../components/ad-hoc-scenario-form/ad-hoc-scenario-form"; -import { useScrollOverflow } from "../../../../../hooks/use-scroll-overflow"; +import { OverlayScrollArea } from "../../../../../components/overlay-scroll-area"; +import { PointerHelpTooltip } from "../../../../../components/pointer-help-tooltip"; +import { StackedSections } from "../../../../../components/stacked-sections"; +import { FocusControls } from "../../../../../worksheet/focus-controls"; +import { FocusRoot, FocusStack } from "../../../../../worksheet/focus-stack"; +import { scenarioExpressions } from "../../../../shared/scenario-expressions"; import { ViewScenarioDrawer } from "../../SimulateView/scenarios/view-scenario-drawer"; import { scenarioRunParameterValues, @@ -43,6 +48,9 @@ import type { AdHocScenarioState } from "@hashintel/petrinaut-core"; // and owns its insets instead: a tighter top, no bottom padding at all so the // form's columns can scroll through the panel's full height. const rootStyle = css({ + "--form-heading-case": "uppercase", + "--form-heading-size": "10px", + "--form-heading-spacing": "0.5px", display: "flex", flexDirection: "column", height: "full", @@ -59,7 +67,7 @@ const scenarioRowStyle = css({ // Small right inset so the row's controls don't hug the panel edge, // matching the form's columns below. paddingRight: "2", - marginBottom: "3", + marginBottom: "1.5", }); // The picker reads as one control, not a full-panel bar; the Time Step @@ -109,8 +117,9 @@ const scenarioSelectWrapperStyle = css({ // align. const containerStyle = css({ display: "grid", - gridTemplateColumns: "[1fr 1.4fr]", - gap: "8", + gridTemplateColumns: "[minmax(0, 1fr) minmax(0, 1.4fr)]", + gap: "3", + minWidth: "[0]", flex: "[1]", minHeight: "[0]", }); @@ -118,9 +127,8 @@ const containerStyle = css({ // The left column stacks two titled blocks in one scroll area; the gap // separates them. const leftColumnSectionsStyle = css({ - display: "flex", - flexDirection: "column", - gap: "6", + display: "contents", + "& > div": { display: "contents" }, }); // The form wraps the whole grid, so its keyboard handling covers both @@ -132,44 +140,17 @@ const adHocFormRootStyle = css({ minHeight: "[0]", }); -const initialStateTitleRowStyle = css({ - display: "flex", - alignItems: "center", - gap: "1", -}); - -const initialStateSpacerStyle = css({ - flex: "[1]", -}); - // The inline form while a simulation is live: visible but inert and dimmed, // matching the panel's disabled inputs. const lockedFormStyle = css({ opacity: "[0.5]", }); -const sectionStyle = css({ - display: "flex", - flexDirection: "column", - gap: "1", - minHeight: "[0]", -}); - -// Lets the parameters section absorb the column's remaining height so its -// list scrolls to the panel bottom. -const fillSectionStyle = css({ - flex: "[1]", -}); - -const sectionTitleStyle = css({ - fontSize: "[10px]", - fontWeight: "semibold", - textTransform: "uppercase", - color: "neutral.a100", - letterSpacing: "[0.5px]", -}); - const labelStyle = css({ + display: "inline-flex", + alignItems: "center", + gap: "1", + whiteSpace: "nowrap", fontSize: "xs", fontWeight: "medium", color: "neutral.fg.body", @@ -180,63 +161,12 @@ const smallLabelStyle = css({ fontWeight: "normal", }); -const parametersScrollWrapperStyle = css({ - position: "relative", - flex: "[1]", - minHeight: "[0]", - display: "flex", - flexDirection: "column", -}); - -/** - * White fades over the edges the list can still be scrolled towards — at the - * top once scrolled, at the bottom while more content is below. Overflow state - * is tracked by the shared `useScrollOverflow` hook. - */ -const parametersFadeStyle = cva({ - base: { - position: "absolute", - left: "[0]", - right: "[0]", - height: "[16px]", - pointerEvents: "none", - zIndex: "[1]", - opacity: "[0]", - transition: "[opacity 150ms ease]", - }, - variants: { - position: { - top: { - top: "[0]", - background: - "[linear-gradient(to bottom, var(--colors-neutral-s00), transparent)]", - }, - bottom: { - bottom: "[0]", - background: - "[linear-gradient(to top, var(--colors-neutral-s00), transparent)]", - }, - }, - visible: { true: { opacity: "[1]" } }, - }, -}); - const parametersListStyle = css({ - display: "flex", - flexDirection: "column", overflowY: "auto", flex: "[1]", minHeight: "[0]", - // End padding: scrolls with the content, giving the last row breathing - // room without reserving fixed space below the list. - paddingBottom: "3", - // Small right inset so row values don't hug the scrollbar/column edge. - paddingRight: "2", - // Bleed: place headers pull their chevron 18px left of the tables; the - // padding/negative-margin pair keeps positions identical while extending - // the clip box so the chevron isn't cropped. - paddingLeft: "[18px]", - marginLeft: "[-18px]", + minWidth: "[0]", + paddingBottom: "4", }); // The Clear affordance stays quiet until pointed at: it wipes the whole @@ -301,36 +231,13 @@ const scenarioMessagesStyle = css({ // -- Component ---------------------------------------------------------------- -/** - * Wraps a form column in a container with white scroll fades: at the top - * once the column is scrolled, at the bottom while more content is below. - */ const ParametersScrollArea: React.FC<{ children: React.ReactNode }> = ({ children, -}) => { - const { scrollRef, canScrollUp, canScrollDown, onScroll } = - useScrollOverflow(); - - return ( -
-
-
- {children} -
-
-
- ); -}; +}) => ( + + {children} + +); const NO_SCENARIO = "__none__"; @@ -387,7 +294,13 @@ const SimulationSettingsContent: React.FC = () => { // materialized into literal read-only rows. const selectedClassicScenario = selectedScenario && !selectedAdHocScenario ? selectedScenario : undefined; - const classicHir = useScenarioHir(selectedClassicScenario); + const scenarioHir = useScenarioHir(selectedScenario, { + adHocContext: { + netParameters: globalParameters, + places, + types: extensions.colors ? types : [], + }, + }); // `seededFrom` is the persisted scenario definition the run state came // from, by content: saving an edit to the selected scenario changes it, so // the form reseeds to the new definition instead of showing the old one @@ -475,12 +388,13 @@ const SimulationSettingsContent: React.FC = () => { types: extensions.colors ? types : [], }; const onScenarioRunChange = (next: AdHocScenarioState) => { - if (!selectedAdHocScenario) { + if (!selectedAdHocScenario || !scenarioRun) { return; } - setScenarioRun((current) => current && { ...current, state: next }); + const updated = { ...scenarioRun.state, variables: next.variables }; + setScenarioRun((current) => current && { ...current, state: updated }); for (const { identifier, value } of scenarioRunParameterValues( - next, + updated, adHocFormContext, )) { setScenarioParameterValue(identifier, value); @@ -505,55 +419,39 @@ const SimulationSettingsContent: React.FC = () => { } }; - // What the run-mode branch renders, for either scenario kind. A classic - // scenario's places come from compiling its initial state with the - // current parameter values; until that preview is ready (or when it - // fails) the notice explains and the Initial state section stays empty. const scenarioRunView: { state: AdHocScenarioState; onChange: (next: AdHocScenarioState) => void; notice: string | null; previewReady: boolean; } | null = (() => { - if ( - selectedAdHocScenario && - scenarioRun?.scenarioId === selectedAdHocScenario.id - ) { - return { - state: scenarioRun.state, - onChange: onScenarioRunChange, - notice: null, - previewReady: true, - }; - } - if ( - !selectedClassicScenario || - scenarioRun?.scenarioId !== selectedClassicScenario.id - ) { + if (!selectedScenario || scenarioRun?.scenarioId !== selectedScenario.id) { return null; } const withoutPreview = (notice: string) => ({ state: { variables: scenarioRun.state.variables, - netParameters: Object.entries( - selectedClassicScenario.parameterOverrides, - ).map(([parameterId, expression]) => ({ - parameterId, - expression, - optimize: null, - })), + netParameters: Object.entries(selectedScenario.parameterOverrides).map( + ([parameterId, expression]) => ({ + parameterId, + expression, + optimize: null, + }), + ), places: {}, }, - onChange: onClassicRunChange, + onChange: selectedAdHocScenario + ? onScenarioRunChange + : onClassicRunChange, notice, previewReady: false, }); - if (classicHir.error !== null) { + if (scenarioHir.error !== null) { return withoutPreview( - `The initial state preview could not be compiled: ${classicHir.error}`, + `The initial state preview could not be compiled: ${scenarioHir.error}`, ); } - if (classicHir.hir === null) { + if (scenarioHir.hir === null) { return withoutPreview("Compiling the initial state preview…"); } const numericValues = createUserKeyedRecord(); @@ -564,8 +462,8 @@ const SimulationSettingsContent: React.FC = () => { } } const outcome = compileScenario( - selectedClassicScenario, - classicHir.hir, + selectedScenario, + scenarioHir.hir, globalParameters, places, adHocFormContext.types, @@ -579,7 +477,7 @@ const SimulationSettingsContent: React.FC = () => { ); } const materialized = classicScenarioRunState( - selectedClassicScenario, + selectedScenario, outcome.result.initialState, { places, types: adHocFormContext.types }, scenarioParameterValues, @@ -588,8 +486,23 @@ const SimulationSettingsContent: React.FC = () => { state: { ...materialized.state, variables: scenarioRun.state.variables, + netParameters: globalParameters.flatMap((parameter) => { + const resolved = + outcome.result.parameterValues[parameter.variableName]; + return resolved === undefined + ? [] + : [ + { + parameterId: parameter.id, + expression: resolved, + optimize: null, + }, + ]; + }), }, - onChange: onClassicRunChange, + onChange: selectedAdHocScenario + ? onScenarioRunChange + : onClassicRunChange, notice: materialized.truncated.length > 0 ? `Preview truncated: ${materialized.truncated @@ -611,8 +524,10 @@ const SimulationSettingsContent: React.FC = () => { const timeStepControl = (
{ ); return ( -
- setIsViewScenarioOpen(false)} - scenario={selectedScenario} - /> - - {/* The scenario picker and Time Step share the top row, so the form's + + +
+ setIsViewScenarioOpen(false)} + scenario={selectedScenario} + /> + + {/* The scenario picker and Time Step share the top row, so the form's two columns below keep the full panel width and their headers start at the same height. */} -
-
- Scenario -
- + setContextScenarioId( + scenarioId === NO_SCENARIO ? null : scenarioId, + ) + } + items={scenarioOptions} + size="xs" + disabled={isSimulationActive} + renderItem={(value) => { + const option = scenarioOptions.find( + (opt) => opt.value === value, + ); + return ( + + {value === NO_SCENARIO && ( + + )} + + {option?.text} + + + ); }} - > - {value === NO_SCENARIO && ( - - )} - - {option?.text} - - - ); - }} - /> -
-
- {selectedScenario && ( -
-
- {timeStepControl} -
+ /> +
+
+ {selectedScenario && ( +
+
+ {timeStepControl} +
+ - {adHocActive ? ( - /* No scenario: Variables and Parameters share the left panel + {adHocActive ? ( + /* No scenario: Variables and Parameters share the left panel column, Initial state fills the right one, laid out through renderLayout — the form's keyboard handling wraps the whole grid, and each visual column is one FormLayoutColumn in the keyboard flow. This embedding offers no Optimize/expose toggles. */ - ( -
- -
- -
-
-
-
Variables
- + ( +
+ + +
+
+ + {variables}
- {variableRows} -
-
-
-
Parameters
- +
+ + {parameterRows ?? ( +
+ No parameters defined +
+ )}
- {parameterRows ?? ( -
- No parameters defined -
- )}
-
-
-
- - - -
-
-
Initial state
- - - -
- - {/* Like every input in this panel, the definition locks - while a simulation is live — an edit would dispose the - run. The scroll container stays interactive so the - content can still be reviewed mid-run. */} -
- {placesList} -
-
+ + + + + + + + + +
+ {placesList} +
+
+
-
-
- )} - /> - ) : scenarioRunView ? ( - /* A selected scenario, shown through the form in run mode: the + )} + /> + ) : scenarioRunView ? ( + /* A selected scenario, shown through the form in run mode: the scenario's parameters (its exposed Variables) take value edits in the left column; Parameters and Initial state sit read-only in the right one, still walkable and selectable. The run state reseeds in the same render pass as the selection, so this arm renders whenever a scenario is selected. */ - ( -
- -
- -
-
-
- Scenario parameters -
- -
- {scenarioParameterRows ?? ( -
- This scenario exposes no parameters -
- )} -
-
-
-
- -
- -
-
-
-
Parameters
- -
- {parameterRows ?? ( + ( +
+ + + +
+ {variables ?? (
- No parameters defined + This scenario exposes no parameters
)}
-
-
-
Initial state
- + + + + +
+
+ + {scenarioRunView.previewReady + ? (parameterRows ?? ( +
+ No parameters defined +
+ )) + : null} +
+
+ + {scenarioRunView.notice === null ? null : ( +
+ {scenarioRunView.notice} +
+ )} + {scenarioRunView.previewReady ? placesList : null}
- {scenarioRunView.notice === null ? null : ( -
- {scenarioRunView.notice} -
- )} - {scenarioRunView.previewReady ? placesList : null}
-
- + +
-
-
+ )} + /> + ) : null} + + {scenarioCompilationErrors && ( + + + Scenario failed to compile — its parameter overrides and initial + state are not applied. + + + {scenarioCompilationErrors.map((compilationError) => ( + + {compilationError.message} + + ))} + + )} - /> - ) : null} - - {scenarioCompilationErrors && ( - - - Scenario failed to compile — its parameter overrides and initial - state are not applied. - - - {scenarioCompilationErrors.map((compilationError) => ( - - {compilationError.message} - - ))} - - - )} -
+
+ + ); }; diff --git a/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/create-experiment-drawer.test.tsx b/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/create-experiment-drawer.test.tsx index b5b5fec7fbf..05ca6b0e30d 100644 --- a/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/create-experiment-drawer.test.tsx +++ b/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/create-experiment-drawer.test.tsx @@ -414,6 +414,13 @@ const unparameterizedContextValue: SDCPNContextValue = { }; beforeEach(() => { + class ObserverStub { + observe() {} + unobserve() {} + disconnect() {} + } + vi.stubGlobal("ResizeObserver", ObserverStub); + vi.stubGlobal("IntersectionObserver", ObserverStub); // `isWebGpuAvailable()` only reads `navigator.gpu`, so a bare object is enough — // and spreading the real Navigator would drop its prototype. vi.stubGlobal("navigator", { gpu: {} }); diff --git a/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/create-experiment-drawer.tsx b/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/create-experiment-drawer.tsx index cea8cdad797..5dc7db94717 100644 --- a/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/create-experiment-drawer.tsx +++ b/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/create-experiment-drawer.tsx @@ -31,9 +31,16 @@ import { useOptimizationSource } from "../../../../../../react/optimizations/use import { SDCPNContext } from "../../../../../../react/state/sdcpn-context"; import { UserSettingsContext } from "../../../../../../react/state/user-settings-context"; import { AdHocScenarioForm } from "../../../../../components/ad-hoc-scenario-form/ad-hoc-scenario-form"; +import { + OverlayScrollArea, + overlayScrollDrawerBodyStyle, + overlayScrollDrawerViewportStyle, +} from "../../../../../components/overlay-scroll-area"; import { Section, SectionList } from "../../../../../components/section"; import { CodeEditor } from "../../../../../monaco/code-editor"; import { getMetricDocumentUri } from "../../../../../monaco/editor-paths"; +import { FocusControls } from "../../../../../worksheet/focus-controls"; +import { FocusRoot, FocusStack } from "../../../../../worksheet/focus-stack"; import { useMetricLspSession } from "../metrics/metric-form"; import { summarizeMetricLspErrors } from "../metrics/metric-lsp"; import { @@ -1173,261 +1180,313 @@ export const CreateExperimentDrawer = ({ } return ( - - - - -
-
- Name - -
-
-
- {/* A sweep refines each selection progressively (8, 25, 100, + + + + + + + + + +
+ +
+ + +
+
+ +
+
+ {/* A sweep refines each selection progressively (8, 25, 100, ... 1000, 5000, ...) up to this budget, so for sweeps this is a ceiling, not a batch size — 100,000 is a reasonable value on the GPU. */} - - {sweepSummary ? "Max runs per selection" : "Runs"} - - - setRunCount( - nextRunCount === null ? "" : String(nextRunCount), - ) - } - /> -
-
- Time step - - setDt(nextDt === null ? "" : String(nextDt)) - } - /> -
-
- Max time (s) - - setMaxTime(nextMaxTime === null ? "" : String(nextMaxTime)) - } - /> -
- {/* A labelled cell in the same grid as Runs / Time step / Max time: + + + setRunCount( + nextRunCount === null ? "" : String(nextRunCount), + ) + } + /> +
+
+ + + setDt(nextDt === null ? "" : String(nextDt)) + } + /> +
+
+ + + setMaxTime( + nextMaxTime === null ? "" : String(nextMaxTime), + ) + } + /> +
+ {/* A labelled cell in the same grid as Runs / Time step / Max time: the backend is a property of the experiment like the rest, and a bare control below the grid read as an orphan. */} - {webGpuEnabled && webGpuAvailable && ( -
- Backend - -
- )} -
- {/* Only shown once WebGPU is switched on in settings — otherwise the + {webGpuEnabled && webGpuAvailable && ( +
+ Backend + +
+ )} +
+ + {/* Only shown once WebGPU is switched on in settings — otherwise the choice does not exist and the row would be noise. */} -
- -
-
- { + const option = scenarioOptions.find( + (opt) => opt.value === value, + ); + return ( + + {value === NO_SCENARIO_VALUE && ( + + )} + {option?.text} + + ); + }} + /> +
+ + + {selectedScenario ? ( + // The selected scenario shows through the form in run mode: + // scenario parameters editable in worksheet style, and a + // collapsed "Computed state" preview of the exact values and + // tokens each run starts with. + <> + + setParamInputs((prev) => { + const next = { ...prev }; + for (const update of updates) { + next[update.identifier] = update.input; + } + return next; + }) + } + /> + {sweepSummaryLine} + + ) : ( + // With no scenario, the experiment's Initial State + Parameters + // are defined inline and compile through a scenario generated + // at experiment start, never persisted. Left untouched, the + // experiment runs from the model's own initial marking. + <> + + {sweepSummaryLine} + + )} +
+ + {objectiveEnabled ? ( + + + + ) : null} + + {constraintsEnabled ? ( + + + + ) : null} + +
+ +
+
+ + {metricDrafts.length === 0 + ? "No experiment metrics" + : `${metricDrafts.length} experiment metric${ + metricDrafts.length === 1 ? "" : "s" + }`} + + +
+ + {metricDrafts.map((metric) => ( + + handleMetricLspDiagnosticsChange( + metric.id, + diagnostics, + ) + } + onRemove={() => handleMetricRemove(metric.id)} /> - )} - {option?.text} - - ); - }} - /> -
- - {selectedScenario ? ( - // The selected scenario shows through the form in run mode: - // scenario parameters editable in worksheet style, and a - // collapsed "Computed state" preview of the exact values and - // tokens each run starts with. - <> - - setParamInputs((prev) => { - const next = { ...prev }; - for (const update of updates) { - next[update.identifier] = update.input; - } - return next; - }) - } - /> - {sweepSummaryLine} - - ) : ( - // With no scenario, the experiment's Initial State + Parameters - // are defined inline and compile through a scenario generated - // at experiment start, never persisted. Left untouched, the - // experiment runs from the model's own initial marking. - <> - - {sweepSummaryLine} - - )} -
- - {objectiveEnabled ? ( - - ) : null} - - {constraintsEnabled ? ( - - ) : null} - -
-
-
- - {metricDrafts.length === 0 - ? "No experiment metrics" - : `${metricDrafts.length} experiment metric${ - metricDrafts.length === 1 ? "" : "s" - }`} - + ))} +
+ +
+
+ +
+ {footerError} + ) : undefined + } + actions={ + -
- - {metricDrafts.map((metric) => ( - - handleMetricLspDiagnosticsChange(metric.id, diagnostics) +
- - - - {footerError} - ) : undefined - } - actions={ - <> - - - - } - /> - + prefix={ + isSubmitting ? ( + + ) : objectiveEnabled ? ( + + ) : sweepSummary ? undefined : ( + + ) + } + onClick={() => { + void handleSubmit(); + }} + > + {submitLabel} + + + } + /> + + + ); }; diff --git a/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/experiment-scenario-run.test.tsx b/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/experiment-scenario-run.test.tsx index 2ad03958f03..cedb47dc012 100644 --- a/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/experiment-scenario-run.test.tsx +++ b/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/experiment-scenario-run.test.tsx @@ -49,6 +49,7 @@ const place = (index: number) => ({ name: `Place ${index}`, colorId: null, dynamicsEnabled: false, + showAsInitialState: true, differentialEquationId: null, x: 0, y: 0, @@ -93,6 +94,40 @@ const languageClient = { }; describe("ExperimentScenarioRun", () => { + it("shows the computed value and reveals its source on keyboard focus", async () => { + render( + + {}} + /> + , + ); + fireEvent.click( + screen.getByRole("button", { name: "Toggle Computed state section" }), + ); + const value = await screen.findByRole("button", { + name: "Place 1 › count", + }); + expect(value.textContent).toBe("7"); + fireEvent.mouseEnter(value); + expect(screen.queryByText("scenario.rate")).toBeNull(); + fireEvent.keyDown(document.body, { key: "Tab" }); + value.focus(); + const expression = await screen.findByText("scenario.rate"); + expect(value.contains(expression)).toBe(false); + expect(expression.closest("[data-computed-expression]")).not.toBeNull(); + expect(value.getAttribute("aria-describedby")).toBe(expression.id); + expect(value.textContent).toBe("7"); + expect(screen.queryByRole("tooltip")).toBeNull(); + fireEvent.blur(value); + await waitFor(() => expect(screen.queryByText("scenario.rate")).toBeNull()); + expect(screen.queryByLabelText("Expression")).toBeNull(); + }); + it("renders the computed initial state in a bounded scroll region", async () => { render( @@ -117,7 +152,9 @@ describe("ExperimentScenarioRun", () => { // A net with many places — or one coloured place with many token rows — // would otherwise push Metrics and the drawer's footer out of view. expect(region).not.toBeNull(); - expect(region!.className).toContain("ov-y_auto"); + expect( + region!.querySelector('[data-part="viewport"]')?.getAttribute("style"), + ).toContain("overflow: auto"); expect(region!.className).toMatch(/max-h_\[\d+px\]/); // Parameters and initial state scroll together inside it, and it reads as // a panel rather than more form. @@ -125,7 +162,7 @@ describe("ExperimentScenarioRun", () => { expect(region!.querySelector("[aria-label='Place 1 › count']")).not.toBe( null, ); - expect(region!.className).toContain("bg-c_neutral.s20"); + expect(region!.className).toContain("bg-c_neutral.s00"); expect(region!.className).toContain("bd-c_neutral.bd.subtle"); }); diff --git a/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/experiment-scenario-run.tsx b/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/experiment-scenario-run.tsx index 4b9fef4b039..e22d5dc8df6 100644 --- a/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/experiment-scenario-run.tsx +++ b/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/experiments/experiment-scenario-run.tsx @@ -22,8 +22,12 @@ import { useScenarioHir } from "../../../../../../react/simulation/use-scenario- import { AdHocScenarioForm, FormLayoutColumn, + FormSectionHeader, } from "../../../../../components/ad-hoc-scenario-form/ad-hoc-scenario-form"; +import { OverlayScrollArea } from "../../../../../components/overlay-scroll-area"; import { Section } from "../../../../../components/section"; +import { StackedSections } from "../../../../../components/stacked-sections"; +import { scenarioExpressions } from "../../../../shared/scenario-expressions"; import { scenarioRunInputs } from "./experiment-scenario-inputs"; import type { ExperimentParameterInput } from "../../../../../../react/experiments/parameter-grid"; @@ -40,41 +44,17 @@ const emptyMessageStyle = css({ color: "neutral.s80", }); -const groupTitleStyle = css({ - fontSize: "xs", - fontWeight: "semibold", - textTransform: "uppercase", - letterSpacing: "wide", - color: "neutral.s80", -}); - -const groupStyle = css({ - display: "flex", - flexDirection: "column", - gap: "1.5", -}); +const groupStyle = css({ display: "contents" }); -// The computed state is a preview, not part of the form: a net with many -// places (or a coloured place with many token rows) would otherwise push -// Metrics and the drawer's own footer out of view. Parameters and initial -// state share one bounded region and scroll together, tinted so the preview -// reads as a panel the form writes into rather than more form. The left -// padding covers the 20px the place headers hang their chevron into, plus a -// gutter, so the hang is not clipped by the region's own overflow. const computedStatePreviewStyle = css({ display: "flex", flexDirection: "column", - gap: "3", maxHeight: "[320px]", - overflowY: "auto", - backgroundColor: "neutral.s20", + backgroundColor: "neutral.s00", borderWidth: "[1px]", borderStyle: "solid", borderColor: "neutral.bd.subtle", borderRadius: "md", - paddingY: "2", - paddingRight: "2", - paddingLeft: "[28px]", }); const noticeStyle = css({ @@ -286,7 +266,13 @@ export const ExperimentScenarioRun: React.FC = ({ context={context} selection={selection} mode="run" - renderLayout={({ variables, parameters, places }) => ( + expressionFor={scenarioExpressions(scenario, context)} + renderLayout={({ + variables, + parameters, + places, + placesVisibilityControl, + }) => ( {exposesParameters ? ( variables @@ -307,18 +293,27 @@ export const ExperimentScenarioRun: React.FC = ({
{computed.notice}
)} {computed?.ready ? ( -
-
-
Parameters
- {parameters ?? ( -
No parameters
- )} -
-
-
Initial state
- {places} -
-
+ + +
+ + {parameters ?? ( +
No parameters
+ )} +
+
+ + {places} +
+
+
) : null}
diff --git a/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/scenarios/ad-hoc-scenario-authoring.tsx b/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/scenarios/ad-hoc-scenario-authoring.tsx index 293b17574d6..a13c76280c7 100644 --- a/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/scenarios/ad-hoc-scenario-authoring.tsx +++ b/libs/@hashintel/petrinaut/src/ui/views/Editor/panels/SimulateView/scenarios/ad-hoc-scenario-authoring.tsx @@ -29,6 +29,11 @@ import { AdHocScenarioForm, FormLayoutColumn, } from "../../../../../components/ad-hoc-scenario-form/ad-hoc-scenario-form"; +import { + OverlayScrollArea, + overlayScrollDrawerBodyStyle, + overlayScrollDrawerViewportStyle, +} from "../../../../../components/overlay-scroll-area"; import { Section, SectionList } from "../../../../../components/section"; import { CodeEditor } from "../../../../../monaco/code-editor"; import { SimulationPanel } from "../shared/simulation-panel"; @@ -224,64 +229,72 @@ export const AdHocScenarioAuthoringBody: React.FC<{ }> = ({ authoring, children }) => { const { code } = authoring; return ( - -
- - + +
+ - - -