@tellegen/svelte 0.1.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +19 -0
- package/README.md +70 -0
- package/dist/Sparkline.svelte +100 -0
- package/dist/Sparkline.svelte.d.ts +8 -0
- package/dist/Sparkline.svelte.d.ts.map +1 -0
- package/dist/TellegenMap.svelte +1430 -0
- package/dist/TellegenMap.svelte.d.ts +14 -0
- package/dist/TellegenMap.svelte.d.ts.map +1 -0
- package/dist/TellegenProvider.svelte +38 -0
- package/dist/TellegenProvider.svelte.d.ts +9 -0
- package/dist/TellegenProvider.svelte.d.ts.map +1 -0
- package/dist/TellegenShell.svelte +126 -0
- package/dist/TellegenShell.svelte.d.ts +4 -0
- package/dist/TellegenShell.svelte.d.ts.map +1 -0
- package/dist/TellegenViewer.svelte +19 -0
- package/dist/TellegenViewer.svelte.d.ts +4 -0
- package/dist/TellegenViewer.svelte.d.ts.map +1 -0
- package/dist/api.d.ts +44 -0
- package/dist/api.d.ts.map +1 -0
- package/dist/api.js +137 -0
- package/dist/colors.d.ts +51 -0
- package/dist/colors.d.ts.map +1 -0
- package/dist/colors.js +140 -0
- package/dist/components/AppFooter.svelte +73 -0
- package/dist/components/AppFooter.svelte.d.ts +19 -0
- package/dist/components/AppFooter.svelte.d.ts.map +1 -0
- package/dist/components/AppHeader.svelte +405 -0
- package/dist/components/AppHeader.svelte.d.ts +4 -0
- package/dist/components/AppHeader.svelte.d.ts.map +1 -0
- package/dist/components/BindingLines.svelte +101 -0
- package/dist/components/BindingLines.svelte.d.ts +4 -0
- package/dist/components/BindingLines.svelte.d.ts.map +1 -0
- package/dist/components/BusPicker.svelte +227 -0
- package/dist/components/BusPicker.svelte.d.ts +4 -0
- package/dist/components/BusPicker.svelte.d.ts.map +1 -0
- package/dist/components/ControlPanel.svelte +154 -0
- package/dist/components/ControlPanel.svelte.d.ts +19 -0
- package/dist/components/ControlPanel.svelte.d.ts.map +1 -0
- package/dist/components/DemandSlider.svelte +271 -0
- package/dist/components/DemandSlider.svelte.d.ts +4 -0
- package/dist/components/DemandSlider.svelte.d.ts.map +1 -0
- package/dist/components/DisplayControls.svelte +81 -0
- package/dist/components/DisplayControls.svelte.d.ts +19 -0
- package/dist/components/DisplayControls.svelte.d.ts.map +1 -0
- package/dist/components/DropZone.svelte +46 -0
- package/dist/components/DropZone.svelte.d.ts +19 -0
- package/dist/components/DropZone.svelte.d.ts.map +1 -0
- package/dist/components/FormulationSelector.svelte +82 -0
- package/dist/components/FormulationSelector.svelte.d.ts +19 -0
- package/dist/components/FormulationSelector.svelte.d.ts.map +1 -0
- package/dist/components/LocalCaseDetails.svelte +253 -0
- package/dist/components/LocalCaseDetails.svelte.d.ts +4 -0
- package/dist/components/LocalCaseDetails.svelte.d.ts.map +1 -0
- package/dist/components/MulticonductorDetails.svelte +280 -0
- package/dist/components/MulticonductorDetails.svelte.d.ts +19 -0
- package/dist/components/MulticonductorDetails.svelte.d.ts.map +1 -0
- package/dist/components/NetworkStats.svelte +75 -0
- package/dist/components/NetworkStats.svelte.d.ts +19 -0
- package/dist/components/NetworkStats.svelte.d.ts.map +1 -0
- package/dist/components/PlacementCue.svelte +35 -0
- package/dist/components/PlacementCue.svelte.d.ts +19 -0
- package/dist/components/PlacementCue.svelte.d.ts.map +1 -0
- package/dist/components/RatingSlider.svelte +273 -0
- package/dist/components/RatingSlider.svelte.d.ts +4 -0
- package/dist/components/RatingSlider.svelte.d.ts.map +1 -0
- package/dist/components/RestoreDefaultsButton.svelte +34 -0
- package/dist/components/RestoreDefaultsButton.svelte.d.ts +19 -0
- package/dist/components/RestoreDefaultsButton.svelte.d.ts.map +1 -0
- package/dist/components/SensitivityReadout.svelte +126 -0
- package/dist/components/SensitivityReadout.svelte.d.ts +4 -0
- package/dist/components/SensitivityReadout.svelte.d.ts.map +1 -0
- package/dist/components/SizeLegend.svelte +55 -0
- package/dist/components/SizeLegend.svelte.d.ts +19 -0
- package/dist/components/SizeLegend.svelte.d.ts.map +1 -0
- package/dist/components/SolveCard.svelte +84 -0
- package/dist/components/SolveCard.svelte.d.ts +4 -0
- package/dist/components/SolveCard.svelte.d.ts.map +1 -0
- package/dist/components/TopMovers.svelte +68 -0
- package/dist/components/TopMovers.svelte.d.ts +19 -0
- package/dist/components/TopMovers.svelte.d.ts.map +1 -0
- package/dist/components.d.ts +19 -0
- package/dist/components.d.ts.map +1 -0
- package/dist/components.js +18 -0
- package/dist/context.svelte.d.ts +20 -0
- package/dist/context.svelte.d.ts.map +1 -0
- package/dist/context.svelte.js +43 -0
- package/dist/controller.svelte.d.ts +334 -0
- package/dist/controller.svelte.d.ts.map +1 -0
- package/dist/controller.svelte.js +2026 -0
- package/dist/display.d.ts +31 -0
- package/dist/display.d.ts.map +1 -0
- package/dist/display.js +63 -0
- package/dist/drop-classify.d.ts +48 -0
- package/dist/drop-classify.d.ts.map +1 -0
- package/dist/drop-classify.js +92 -0
- package/dist/format.d.ts +30 -0
- package/dist/format.d.ts.map +1 -0
- package/dist/format.js +49 -0
- package/dist/index.d.ts +21 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/index.js +12 -0
- package/dist/map.d.ts +9 -0
- package/dist/map.d.ts.map +1 -0
- package/dist/map.js +4 -0
- package/dist/multiconductor.d.ts +63 -0
- package/dist/multiconductor.d.ts.map +1 -0
- package/dist/multiconductor.js +255 -0
- package/dist/state.svelte.d.ts +258 -0
- package/dist/state.svelte.d.ts.map +1 -0
- package/dist/state.svelte.js +323 -0
- package/dist/study-package.d.ts +9 -0
- package/dist/study-package.d.ts.map +1 -0
- package/dist/study-package.js +17 -0
- package/dist/styles.css +393 -0
- package/dist/synthetic-layout.d.ts +12 -0
- package/dist/synthetic-layout.d.ts.map +1 -0
- package/dist/synthetic-layout.js +271 -0
- package/dist/types.d.ts +6 -0
- package/dist/types.d.ts.map +1 -0
- package/dist/types.js +1 -0
- package/package.json +67 -0
|
@@ -0,0 +1,255 @@
|
|
|
1
|
+
/** Pure helpers for the multiconductor viewing path: place a distribution
|
|
2
|
+
* bus/terminal graph onto the map, and the phase/edge/attachment palette the
|
|
3
|
+
* layers and the terminal detail share. No solve, no reactive state here — the
|
|
4
|
+
* `MulticonductorCase` state and the map own those. */
|
|
5
|
+
import { placeSyntheticTopology } from './synthetic-layout.js';
|
|
6
|
+
import { extent } from './format.js';
|
|
7
|
+
const ATTACHMENT_ORDER = [
|
|
8
|
+
'source',
|
|
9
|
+
'generator',
|
|
10
|
+
'ibr',
|
|
11
|
+
'load',
|
|
12
|
+
'shunt'
|
|
13
|
+
];
|
|
14
|
+
/** Flatten a bus's per-terminal attachments to the distinct kinds present, in a
|
|
15
|
+
* stable render order. */
|
|
16
|
+
function attachmentKindsOf(bus) {
|
|
17
|
+
const present = new Set();
|
|
18
|
+
for (const list of Object.values(bus.terminal_attachments ?? {})) {
|
|
19
|
+
for (const a of list)
|
|
20
|
+
present.add(a.kind);
|
|
21
|
+
}
|
|
22
|
+
return ATTACHMENT_ORDER.filter((kind) => present.has(kind));
|
|
23
|
+
}
|
|
24
|
+
function placedBus(bus, lon, lat) {
|
|
25
|
+
return {
|
|
26
|
+
id: bus.id,
|
|
27
|
+
lon,
|
|
28
|
+
lat,
|
|
29
|
+
terminals: bus.terminals,
|
|
30
|
+
grounded: bus.grounded,
|
|
31
|
+
load_kw: bus.load_kw,
|
|
32
|
+
gen_kw: bus.gen_kw,
|
|
33
|
+
has_source: bus.has_source,
|
|
34
|
+
attachmentKinds: attachmentKindsOf(bus),
|
|
35
|
+
terminalAttachments: bus.terminal_attachments ?? {}
|
|
36
|
+
};
|
|
37
|
+
}
|
|
38
|
+
/** Case-insensitive lookup from a bus id to its position; the graph stores ids
|
|
39
|
+
* in their source case while edges reference the canonical id, which can differ
|
|
40
|
+
* only in case. */
|
|
41
|
+
function positionIndex(coords) {
|
|
42
|
+
const lower = new Map();
|
|
43
|
+
for (const [id, xy] of coords)
|
|
44
|
+
lower.set(id.toLowerCase(), xy);
|
|
45
|
+
return (id) => coords.get(id) ?? lower.get(id.toLowerCase());
|
|
46
|
+
}
|
|
47
|
+
/** Build the placed view from a coordinate map keyed by bus id. Buses without a
|
|
48
|
+
* position are dropped, and so is any edge missing an endpoint position. */
|
|
49
|
+
function viewFrom(graph, coords) {
|
|
50
|
+
const at = positionIndex(coords);
|
|
51
|
+
const buses = [];
|
|
52
|
+
for (const bus of graph.buses) {
|
|
53
|
+
const xy = at(bus.id);
|
|
54
|
+
if (xy)
|
|
55
|
+
buses.push(placedBus(bus, xy[0], xy[1]));
|
|
56
|
+
}
|
|
57
|
+
const edges = [];
|
|
58
|
+
for (const edge of graph.edges) {
|
|
59
|
+
const from = at(edge.from);
|
|
60
|
+
const to = at(edge.to);
|
|
61
|
+
if (!from || !to)
|
|
62
|
+
continue;
|
|
63
|
+
edges.push({
|
|
64
|
+
id: edge.id,
|
|
65
|
+
kind: edge.kind,
|
|
66
|
+
from: edge.from,
|
|
67
|
+
to: edge.to,
|
|
68
|
+
conductors: edge.conductors,
|
|
69
|
+
closed: edge.closed,
|
|
70
|
+
n_phases: edge.n_phases,
|
|
71
|
+
path: [from, to]
|
|
72
|
+
});
|
|
73
|
+
}
|
|
74
|
+
return { buses, edges };
|
|
75
|
+
}
|
|
76
|
+
/** Place a geographic graph: each bus's `xy` is `[longitude, latitude]` and
|
|
77
|
+
* drops straight onto the map. */
|
|
78
|
+
export function buildGeographicView(graph) {
|
|
79
|
+
const coords = new Map();
|
|
80
|
+
for (const bus of graph.buses) {
|
|
81
|
+
if (bus.xy)
|
|
82
|
+
coords.set(bus.id, bus.xy);
|
|
83
|
+
}
|
|
84
|
+
return viewFrom(graph, coords);
|
|
85
|
+
}
|
|
86
|
+
/** Whether at least two buses carry a planar `xy`, enough to fit a layout to. */
|
|
87
|
+
function hasPlanarCoords(graph) {
|
|
88
|
+
let n = 0;
|
|
89
|
+
for (const bus of graph.buses)
|
|
90
|
+
if (bus.xy)
|
|
91
|
+
n++;
|
|
92
|
+
return n >= 2;
|
|
93
|
+
}
|
|
94
|
+
/** Fit provided planar coordinates into a longitude/latitude box at `center`,
|
|
95
|
+
* preserving the drawing's shape. Mirrors the box the synthetic layout uses so
|
|
96
|
+
* the two placement kinds read at the same scale. Buses without a position are
|
|
97
|
+
* dropped; the map falls back to the layout when too few carry one. */
|
|
98
|
+
function projectPlanar(graph, center) {
|
|
99
|
+
const placed = graph.buses.filter((b) => b.xy);
|
|
100
|
+
const xs = placed.map((b) => b.xy[0]);
|
|
101
|
+
const ys = placed.map((b) => b.xy[1]);
|
|
102
|
+
const { min: minX, max: maxX } = extent(xs);
|
|
103
|
+
const { min: minY, max: maxY } = extent(ys);
|
|
104
|
+
const sx = maxX - minX || 1;
|
|
105
|
+
const sy = maxY - minY || 1;
|
|
106
|
+
const span = Math.min(4.5, Math.max(0.32, Math.sqrt(Math.max(placed.length, 1)) * 0.08));
|
|
107
|
+
const lonScale = Math.max(Math.cos((center.lat * Math.PI) / 180), 0.25);
|
|
108
|
+
const latSpan = span;
|
|
109
|
+
const lonSpan = span / lonScale;
|
|
110
|
+
const coords = new Map();
|
|
111
|
+
for (const bus of placed) {
|
|
112
|
+
// Normalize into [0,1] with a small inset, then into the box at center. Y
|
|
113
|
+
// is flipped so larger planar y reads as further north.
|
|
114
|
+
const nx = 0.04 + ((bus.xy[0] - minX) / sx) * 0.92;
|
|
115
|
+
const ny = 0.04 + ((bus.xy[1] - minY) / sy) * 0.92;
|
|
116
|
+
coords.set(bus.id, [
|
|
117
|
+
center.lon + (nx - 0.5) * lonSpan,
|
|
118
|
+
center.lat + (ny - 0.5) * latSpan
|
|
119
|
+
]);
|
|
120
|
+
}
|
|
121
|
+
return coords;
|
|
122
|
+
}
|
|
123
|
+
/** Build a numeric-id `Topology` from the graph so the shared synthetic force
|
|
124
|
+
* layout can lay it out. Bus ids become array indices; the string id rides in
|
|
125
|
+
* `uid`, and edges map their endpoints to those indices. */
|
|
126
|
+
function toTopology(graph) {
|
|
127
|
+
const idByIndex = graph.buses.map((b) => b.id);
|
|
128
|
+
const indexById = new Map();
|
|
129
|
+
graph.buses.forEach((b, i) => indexById.set(b.id.toLowerCase(), i));
|
|
130
|
+
const index = (id) => indexById.get(id.toLowerCase());
|
|
131
|
+
const topology = {
|
|
132
|
+
buses: graph.buses.map((b, i) => ({
|
|
133
|
+
id: i,
|
|
134
|
+
uid: b.id,
|
|
135
|
+
demand_mw: b.load_kw,
|
|
136
|
+
gen_mw: b.gen_kw
|
|
137
|
+
})),
|
|
138
|
+
branches: graph.edges.flatMap((e, i) => {
|
|
139
|
+
const from = index(e.from);
|
|
140
|
+
const to = index(e.to);
|
|
141
|
+
if (from === undefined || to === undefined)
|
|
142
|
+
return [];
|
|
143
|
+
return [
|
|
144
|
+
{
|
|
145
|
+
id: i,
|
|
146
|
+
uid: e.id,
|
|
147
|
+
from,
|
|
148
|
+
to,
|
|
149
|
+
rate_mw: 0,
|
|
150
|
+
status: e.closed ? 1 : 0
|
|
151
|
+
}
|
|
152
|
+
];
|
|
153
|
+
})
|
|
154
|
+
};
|
|
155
|
+
return { topology, idByIndex };
|
|
156
|
+
}
|
|
157
|
+
/** Lay the graph out with the shared synthetic force layout at `center`, then
|
|
158
|
+
* map the numeric-id result back to string bus ids. */
|
|
159
|
+
function layoutSynthetic(graph, center) {
|
|
160
|
+
const { topology, idByIndex } = toTopology(graph);
|
|
161
|
+
const placed = placeSyntheticTopology(topology, center);
|
|
162
|
+
const coords = new Map();
|
|
163
|
+
for (const bus of placed.buses) {
|
|
164
|
+
const id = idByIndex[bus.id];
|
|
165
|
+
if (id !== undefined)
|
|
166
|
+
coords.set(id, [bus.lon, bus.lat]);
|
|
167
|
+
}
|
|
168
|
+
return coords;
|
|
169
|
+
}
|
|
170
|
+
/** Place a non-geographic graph at a map `center`: fit the provided planar
|
|
171
|
+
* coordinates when the case carries them, otherwise fall back to the shared
|
|
172
|
+
* synthetic force layout. */
|
|
173
|
+
export function placeMultiView(graph, center) {
|
|
174
|
+
const coords = hasPlanarCoords(graph)
|
|
175
|
+
? projectPlanar(graph, center)
|
|
176
|
+
: layoutSynthetic(graph, center);
|
|
177
|
+
return viewFrom(graph, coords);
|
|
178
|
+
}
|
|
179
|
+
// ---------------------------------------------------------------------------
|
|
180
|
+
// Palette: phase-colored conductors, edge kinds, attachment badges. The hues
|
|
181
|
+
// reuse the app's warm/earth family so the multiconductor view sits beside the
|
|
182
|
+
// single-phase view without a palette clash.
|
|
183
|
+
// ---------------------------------------------------------------------------
|
|
184
|
+
/** Rust, green, and steel-blue for the three phases; a warm gray for the
|
|
185
|
+
* neutral/ground return. Distinct in hue and lightness so they survive color
|
|
186
|
+
* vision deficiency and never read as the LMP ramp. */
|
|
187
|
+
const PHASE_A = [194, 86, 75, 255];
|
|
188
|
+
const PHASE_B = [74, 143, 95, 255];
|
|
189
|
+
const PHASE_C = [63, 111, 187, 255];
|
|
190
|
+
const NEUTRAL = [120, 114, 102, 255];
|
|
191
|
+
/** Color a conductor by its terminal name. OpenDSS node numbers map 1/2/3 to
|
|
192
|
+
* the three phases; a named phase (`a`/`b`/`c`) maps the same way; anything else
|
|
193
|
+
* (neutral `n`, ground, the fourth wire) is the neutral gray. */
|
|
194
|
+
export function phaseColor(terminal) {
|
|
195
|
+
switch (terminal.trim().toLowerCase()) {
|
|
196
|
+
case '1':
|
|
197
|
+
case 'a':
|
|
198
|
+
return PHASE_A;
|
|
199
|
+
case '2':
|
|
200
|
+
case 'b':
|
|
201
|
+
return PHASE_B;
|
|
202
|
+
case '3':
|
|
203
|
+
case 'c':
|
|
204
|
+
return PHASE_C;
|
|
205
|
+
default:
|
|
206
|
+
return NEUTRAL;
|
|
207
|
+
}
|
|
208
|
+
}
|
|
209
|
+
/** True when a terminal is a phase conductor (not a neutral/ground return). */
|
|
210
|
+
export function isPhaseTerminal(terminal) {
|
|
211
|
+
return ['1', '2', '3', 'a', 'b', 'c'].includes(terminal.trim().toLowerCase());
|
|
212
|
+
}
|
|
213
|
+
/** Base color for an edge by kind and state. Lines are the warm gray of the
|
|
214
|
+
* single-phase branches; transformers are steel; a switch is amber when closed
|
|
215
|
+
* and a faded red when open. */
|
|
216
|
+
export function edgeColor(kind, closed) {
|
|
217
|
+
if (kind === 'transformer')
|
|
218
|
+
return [96, 118, 140, 235];
|
|
219
|
+
if (kind === 'switch')
|
|
220
|
+
return closed ? [212, 116, 34, 235] : [179, 38, 30, 150];
|
|
221
|
+
return [138, 131, 117, 210];
|
|
222
|
+
}
|
|
223
|
+
/** Edge stroke width in pixels, growing with conductor count so a three-phase
|
|
224
|
+
* feeder reads heavier than a single-phase lateral. Transformers draw a touch
|
|
225
|
+
* wider to stand out as the equipment they are. */
|
|
226
|
+
export function edgeWidth(kind, nPhases) {
|
|
227
|
+
const base = 1.4 + 0.7 * Math.min(Math.max(nPhases, 1), 4);
|
|
228
|
+
return kind === 'transformer' ? base + 1 : base;
|
|
229
|
+
}
|
|
230
|
+
const ATTACHMENT_COLOR = {
|
|
231
|
+
source: [63, 111, 187, 255],
|
|
232
|
+
generator: [74, 143, 95, 255],
|
|
233
|
+
ibr: [120, 158, 70, 255],
|
|
234
|
+
load: [178, 94, 0, 255],
|
|
235
|
+
shunt: [138, 108, 168, 255]
|
|
236
|
+
};
|
|
237
|
+
/** Badge color for an attachment kind. */
|
|
238
|
+
export function attachmentColor(kind) {
|
|
239
|
+
return ATTACHMENT_COLOR[kind];
|
|
240
|
+
}
|
|
241
|
+
/** A short glyph for an attachment kind, for the panel legend and badges. */
|
|
242
|
+
export function attachmentGlyph(kind) {
|
|
243
|
+
switch (kind) {
|
|
244
|
+
case 'source':
|
|
245
|
+
return 'src';
|
|
246
|
+
case 'generator':
|
|
247
|
+
return 'gen';
|
|
248
|
+
case 'ibr':
|
|
249
|
+
return 'ibr';
|
|
250
|
+
case 'load':
|
|
251
|
+
return 'load';
|
|
252
|
+
case 'shunt':
|
|
253
|
+
return 'sh';
|
|
254
|
+
}
|
|
255
|
+
}
|
|
@@ -0,0 +1,258 @@
|
|
|
1
|
+
import type { CaseSummary, DemandDeltas, Network, NetworkBranch, NetworkBus, SensitivityColumn, Solution, SolveIteration } from './api.js';
|
|
2
|
+
import { type BranchRatingDeltas, type CaseFileSummary, type DistGraph, type IngestedDistCase, type SensTarget, type Topology } from '@tellegen/engine';
|
|
3
|
+
import type { MultiView } from './multiconductor.js';
|
|
4
|
+
export type SolveBackend = 'clarabel-wasm' | 'clarabel-wasm-server-sensitivity' | 'rust-server';
|
|
5
|
+
/** A map framing request: a case id, 'all', or one branch to center. */
|
|
6
|
+
export type FrameTarget = string | 'all' | {
|
|
7
|
+
caseId: string;
|
|
8
|
+
branchId: number;
|
|
9
|
+
};
|
|
10
|
+
export type DemandRangeMode = 'local' | 'full';
|
|
11
|
+
export type DisplayMode = 'lmp' | 'angle' | 'voltage';
|
|
12
|
+
/** The case a removal promoted to active, so the caller can hydrate it: a backend
|
|
13
|
+
* case needs its network/solution loaded, a local needs a browser solve, and
|
|
14
|
+
* `none` means nothing remains (or the removal left the active case untouched). */
|
|
15
|
+
export type FallbackTarget = {
|
|
16
|
+
kind: 'backend';
|
|
17
|
+
id: string;
|
|
18
|
+
} | {
|
|
19
|
+
kind: 'local';
|
|
20
|
+
id: string;
|
|
21
|
+
} | {
|
|
22
|
+
kind: 'none';
|
|
23
|
+
};
|
|
24
|
+
/** Substations from a PowerWorld .pwd display file. Positions are inferred
|
|
25
|
+
* from diagram coordinates, not surveyed latitude and longitude. */
|
|
26
|
+
export interface LocalSubstations {
|
|
27
|
+
points: {
|
|
28
|
+
number: number;
|
|
29
|
+
name: string;
|
|
30
|
+
lon: number;
|
|
31
|
+
lat: number;
|
|
32
|
+
}[];
|
|
33
|
+
approximate: true;
|
|
34
|
+
}
|
|
35
|
+
type CoordsKind = 'file' | 'synthetic_pending' | 'synthetic' | 'manual' | 'geofile';
|
|
36
|
+
type LocalView = {
|
|
37
|
+
buses: NetworkBus[];
|
|
38
|
+
branches: NetworkBranch[];
|
|
39
|
+
};
|
|
40
|
+
/** The fields a parsed file supplies at creation; the solve state defaults. */
|
|
41
|
+
export interface LocalCaseInit {
|
|
42
|
+
id: string;
|
|
43
|
+
label: string;
|
|
44
|
+
fileName: string;
|
|
45
|
+
summary?: CaseFileSummary | null;
|
|
46
|
+
networkJson?: string;
|
|
47
|
+
topology?: Topology;
|
|
48
|
+
coordsKind?: CoordsKind;
|
|
49
|
+
view?: LocalView | null;
|
|
50
|
+
substations?: LocalSubstations;
|
|
51
|
+
}
|
|
52
|
+
/** A case file parsed in the browser. Network cases can solve after they have
|
|
53
|
+
* coordinates; a .pwd display file has no case summary, substations only. A
|
|
54
|
+
* class with a stable identity and reactive fields, like CaseState: the solve
|
|
55
|
+
* and sensitivity flows mutate fields directly (each is $state, so the panel
|
|
56
|
+
* re-renders) and the seq tokens stay attached across overlapping async
|
|
57
|
+
* callbacks, so a stale solve can neither freeze the UI nor clobber a newer one. */
|
|
58
|
+
export declare class LocalCase {
|
|
59
|
+
readonly id: string;
|
|
60
|
+
readonly label: string;
|
|
61
|
+
readonly fileName: string;
|
|
62
|
+
/** Case stats; null for a .pwd display only entry. */
|
|
63
|
+
summary: CaseFileSummary | null;
|
|
64
|
+
/** Raw powerio Network JSON for the browser solver branch. */
|
|
65
|
+
networkJson: string | undefined;
|
|
66
|
+
/** Topology for synthetic placement when the file has no coordinates. */
|
|
67
|
+
topology: Topology | undefined;
|
|
68
|
+
coordsKind: CoordsKind | undefined;
|
|
69
|
+
/** Map geometry when the file carried or received coordinates. */
|
|
70
|
+
view: LocalView | null;
|
|
71
|
+
syntheticCenter: {
|
|
72
|
+
lon: number;
|
|
73
|
+
lat: number;
|
|
74
|
+
} | undefined;
|
|
75
|
+
geoSource: string | undefined;
|
|
76
|
+
geoWarnings: string[] | undefined;
|
|
77
|
+
network: Network | null;
|
|
78
|
+
baseSolution: Solution | null;
|
|
79
|
+
solution: Solution | null;
|
|
80
|
+
sensitivity: SensitivityColumn | null;
|
|
81
|
+
deltas: DemandDeltas;
|
|
82
|
+
/** Committed branch rating deltas (MW from base, keyed by branch). */
|
|
83
|
+
ratings: BranchRatingDeltas;
|
|
84
|
+
/** The OPF formulation the browser Study solves for this case: DC OPF (default),
|
|
85
|
+
* full AC OPF, or the SOCWR relaxation. Changing it rebuilds the Study. */
|
|
86
|
+
formulation: import("@tellegen/engine").BrowserFormulation;
|
|
87
|
+
iterations: SolveIteration[];
|
|
88
|
+
solving: boolean;
|
|
89
|
+
solveMs: number | null;
|
|
90
|
+
solveBackend: SolveBackend | null;
|
|
91
|
+
solveFallbackReason: string | null;
|
|
92
|
+
/** Monotone token: only the latest solve may write this case. */
|
|
93
|
+
solveSeq: number;
|
|
94
|
+
/** Monotone token: only the latest sensitivity request may write this case. */
|
|
95
|
+
sensitivitySeq: number;
|
|
96
|
+
predictedObjective: number | null;
|
|
97
|
+
/** Present for a PowerWorld .pwd display only entry. */
|
|
98
|
+
substations: LocalSubstations | undefined;
|
|
99
|
+
constructor(init: LocalCaseInit);
|
|
100
|
+
get perturbed(): boolean;
|
|
101
|
+
}
|
|
102
|
+
/** One islanded network with its own solver state on the server. API
|
|
103
|
+
* payloads are reassigned wholesale, so $state.raw throughout. */
|
|
104
|
+
export declare class CaseState {
|
|
105
|
+
readonly id: string;
|
|
106
|
+
readonly name: string;
|
|
107
|
+
network: Network | null;
|
|
108
|
+
/** Raw powerio Network JSON for the browser solver; fetched lazily. */
|
|
109
|
+
networkJson: string | null;
|
|
110
|
+
/** Boot solution at base demand; never changes. */
|
|
111
|
+
baseSolution: Solution | null;
|
|
112
|
+
/** Exact solution at the current committed perturbation. */
|
|
113
|
+
solution: Solution | null;
|
|
114
|
+
sensitivity: SensitivityColumn | null;
|
|
115
|
+
/** Committed demand deltas (MW from base, keyed by bus). */
|
|
116
|
+
deltas: DemandDeltas;
|
|
117
|
+
/** Committed branch rating deltas (MW from base, keyed by branch). */
|
|
118
|
+
ratings: BranchRatingDeltas;
|
|
119
|
+
/** The OPF formulation the browser Study solves for this case: DC OPF (default),
|
|
120
|
+
* full AC OPF, or the SOCWR relaxation. Changing it rebuilds the Study. */
|
|
121
|
+
formulation: import("@tellegen/engine").BrowserFormulation;
|
|
122
|
+
iterations: SolveIteration[];
|
|
123
|
+
solving: boolean;
|
|
124
|
+
solveMs: number | null;
|
|
125
|
+
solveBackend: SolveBackend | null;
|
|
126
|
+
solveFallbackReason: string | null;
|
|
127
|
+
/** Monotone token: only the latest solve may write this case. */
|
|
128
|
+
solveSeq: number;
|
|
129
|
+
/** Monotone token: only the latest sensitivity request may write this case. */
|
|
130
|
+
sensitivitySeq: number;
|
|
131
|
+
/** Closer for this case's in-flight server solve stream, if any. Owned per
|
|
132
|
+
* case so closing one case's stream never strands another's solve. */
|
|
133
|
+
closeStream: (() => void) | null;
|
|
134
|
+
/** Objective change the gradient predicted for the last commit, to score
|
|
135
|
+
* the preview once the exact solve lands. */
|
|
136
|
+
predictedObjective: number | null;
|
|
137
|
+
constructor(summary: CaseSummary);
|
|
138
|
+
get perturbed(): boolean;
|
|
139
|
+
}
|
|
140
|
+
/** A case the solver can run: a server-backed case or a browser-parsed local case. */
|
|
141
|
+
export type SolvableCase = CaseState | LocalCase;
|
|
142
|
+
/** The multiconductor ingest payload without the graph: the summary counts,
|
|
143
|
+
* connected load/generation, coordinate provenance, and warnings. */
|
|
144
|
+
export type MultiCaseSummary = Omit<IngestedDistCase, 'graph'>;
|
|
145
|
+
/** How a multiconductor case is placed on the map. `geographic` positions drop
|
|
146
|
+
* straight on; `planar`/`synthetic` need a map center, so they sit `pending`
|
|
147
|
+
* until the user places them. */
|
|
148
|
+
export type MultiCoordsKind = 'geographic' | 'planar' | 'synthetic';
|
|
149
|
+
/** A multiconductor distribution case parsed in the browser, viewed only: no
|
|
150
|
+
* formulation, no sliders, no Study. It carries the bus/terminal graph, its
|
|
151
|
+
* placed map view, and the selected bus whose terminal detail expands. Fields
|
|
152
|
+
* are reactive like the solvable cases so the panel and map track them. */
|
|
153
|
+
export declare class MulticonductorCase {
|
|
154
|
+
readonly id: string;
|
|
155
|
+
readonly label: string;
|
|
156
|
+
readonly fileName: string;
|
|
157
|
+
/** Summary counts and coordinate provenance from the parse. */
|
|
158
|
+
summary: MultiCaseSummary | null;
|
|
159
|
+
/** The render-ready bus/terminal graph. */
|
|
160
|
+
graph: DistGraph | null;
|
|
161
|
+
/** Placement kind resolved at ingest from the case's coordinate space. */
|
|
162
|
+
coordsKind: MultiCoordsKind;
|
|
163
|
+
/** The placed map view; null until placed (planar/synthetic await a center). */
|
|
164
|
+
view: MultiView | null;
|
|
165
|
+
syntheticCenter: {
|
|
166
|
+
lon: number;
|
|
167
|
+
lat: number;
|
|
168
|
+
} | undefined;
|
|
169
|
+
/** The selected bus id, whose terminal stack and incident conductors expand;
|
|
170
|
+
* null when nothing is selected. String-keyed: distribution bus ids are names. */
|
|
171
|
+
selectedBusId: string | null;
|
|
172
|
+
constructor(init: {
|
|
173
|
+
id: string;
|
|
174
|
+
label: string;
|
|
175
|
+
fileName: string;
|
|
176
|
+
summary: MultiCaseSummary;
|
|
177
|
+
graph: DistGraph;
|
|
178
|
+
coordsKind: MultiCoordsKind;
|
|
179
|
+
view?: MultiView | null;
|
|
180
|
+
});
|
|
181
|
+
/** Whether the case is placed and ready to render. */
|
|
182
|
+
get placed(): boolean;
|
|
183
|
+
/** The selected bus's placed detail, or null. */
|
|
184
|
+
get selectedBus(): import("./multiconductor.js").PlacedMultiBus | null;
|
|
185
|
+
}
|
|
186
|
+
export declare class AppState {
|
|
187
|
+
#private;
|
|
188
|
+
cases: CaseState[];
|
|
189
|
+
activeCaseId: string | null;
|
|
190
|
+
/** Selected bus in the active case. */
|
|
191
|
+
selectedBus: number | null;
|
|
192
|
+
/** Selected branch in the active case; mutually exclusive with selectedBus. */
|
|
193
|
+
selectedBranch: number | null;
|
|
194
|
+
/** Live slider value (MW from base) before commit; null when idle. */
|
|
195
|
+
previewDeltaMw: number | null;
|
|
196
|
+
/** Live rating slider value (MW from base) before commit; null when idle. */
|
|
197
|
+
previewRatingMw: number | null;
|
|
198
|
+
/** True while the demand control should keep the map in LMP preview mode. */
|
|
199
|
+
previewActive: boolean;
|
|
200
|
+
/** Engine first-order LMP preview for the live drag: predicted change in LMP
|
|
201
|
+
* ($/MWh) per bus at the previewed edit, scoped to the case and selection
|
|
202
|
+
* target (bus or branch) it was computed for. Set by the Study path; null when
|
|
203
|
+
* no Study preview applies (the map then falls back to the JS
|
|
204
|
+
* sensitivity-times-step preview). Reassigned wholesale, so $state.raw. */
|
|
205
|
+
previewLmp: {
|
|
206
|
+
caseId: string;
|
|
207
|
+
target: SensTarget;
|
|
208
|
+
delta: Map<number, number>;
|
|
209
|
+
} | null;
|
|
210
|
+
demandRangeMode: DemandRangeMode;
|
|
211
|
+
displayMode: DisplayMode;
|
|
212
|
+
sensitivityLoading: boolean;
|
|
213
|
+
/** Re-runs the operation behind the current `error`, when one applies. Every
|
|
214
|
+
* write to `error` clears it, so a retry op can never outlive its message. */
|
|
215
|
+
errorRetry: (() => void) | null;
|
|
216
|
+
get error(): string | null;
|
|
217
|
+
set error(message: string | null);
|
|
218
|
+
/** Case files parsed in the browser via the powerio wasm module. */
|
|
219
|
+
localCases: LocalCase[];
|
|
220
|
+
/** Local case the panel shows; clicking a bundled case or a bus clears it. */
|
|
221
|
+
activeLocalId: string | null;
|
|
222
|
+
placingLocalId: string | null;
|
|
223
|
+
/** Multiconductor distribution cases parsed in the browser (viewing only). */
|
|
224
|
+
multiCases: MulticonductorCase[];
|
|
225
|
+
/** Multiconductor case the panel shows; mutually exclusive with the solvable
|
|
226
|
+
* active ids. */
|
|
227
|
+
activeMultiId: string | null;
|
|
228
|
+
/** Multiconductor case awaiting placement on the map. */
|
|
229
|
+
placingMultiId: string | null;
|
|
230
|
+
dragOver: boolean;
|
|
231
|
+
parsingFile: boolean;
|
|
232
|
+
/** Map framing request: bump seq so repeat targets still fly. `requestFrame`
|
|
233
|
+
* returns a promise the map resolves when the camera lands (or immediately
|
|
234
|
+
* when it cannot fly), so a caller can defer heavy work until the animation
|
|
235
|
+
* finishes. */
|
|
236
|
+
frameTarget: FrameTarget;
|
|
237
|
+
frameSeq: number;
|
|
238
|
+
get active(): CaseState | null;
|
|
239
|
+
byId(id: string): CaseState | null;
|
|
240
|
+
get activeLocal(): LocalCase | null;
|
|
241
|
+
get activeMulti(): MulticonductorCase | null;
|
|
242
|
+
/** Whether any case is awaiting a click-to-place on the map (local or multi). */
|
|
243
|
+
get placingId(): string | null;
|
|
244
|
+
addLocal(c: LocalCase): void;
|
|
245
|
+
/** Add a multiconductor case and make it active. A case that still needs a
|
|
246
|
+
* map center (planar/synthetic, no view yet) enters placement. */
|
|
247
|
+
addMulti(c: MulticonductorCase): void;
|
|
248
|
+
removeMulti(id: string): FallbackTarget;
|
|
249
|
+
removeCase(id: string): FallbackTarget;
|
|
250
|
+
removeLocal(id: string): FallbackTarget;
|
|
251
|
+
activateFallback(): FallbackTarget;
|
|
252
|
+
requestFrame(target: FrameTarget): Promise<void>;
|
|
253
|
+
/** The map calls this when the requested camera move has landed. */
|
|
254
|
+
settleFrame(): void;
|
|
255
|
+
}
|
|
256
|
+
export declare function createAppState(): AppState;
|
|
257
|
+
export {};
|
|
258
|
+
//# sourceMappingURL=state.svelte.d.ts.map
|
|
@@ -0,0 +1 @@
|
|
|
1
|
+
{"version":3,"file":"state.svelte.d.ts","sourceRoot":"","sources":["../src/lib/state.svelte.ts"],"names":[],"mappings":"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"}
|