sad-mcp 1.0.3 → 1.1.1
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/README.md +63 -56
- package/dist/bpmn/export-bpmn.d.ts +8 -0
- package/dist/bpmn/export-bpmn.js +167 -0
- package/dist/bpmn/index.d.ts +18 -0
- package/dist/bpmn/index.js +23 -0
- package/dist/bpmn/layout.d.ts +22 -0
- package/dist/bpmn/layout.js +424 -0
- package/dist/bpmn/routing.d.ts +6 -0
- package/dist/bpmn/routing.js +410 -0
- package/dist/bpmn/svg.d.ts +26 -0
- package/dist/bpmn/svg.js +396 -0
- package/dist/bpmn/template.d.ts +16 -0
- package/dist/bpmn/template.js +276 -0
- package/dist/bpmn/types.d.ts +155 -0
- package/dist/bpmn/types.js +4 -0
- package/dist/bpmn/validate.d.ts +4 -0
- package/dist/bpmn/validate.js +487 -0
- package/dist/prompts.js +8 -1
- package/dist/tools.js +188 -9
- package/package.json +5 -2
- package/skills/_shared/export-buttons.md +249 -0
- package/skills/_shared/layout-recipes.md +213 -0
- package/skills/_shared/model-shape.md +126 -0
- package/skills/bpmn-analysis/NOTATION.md +151 -0
- package/skills/bpmn-analysis/SKILL.md +161 -185
- package/skills/bpmn-render/SKILL.md +31 -248
- package/skills/uml-class-diagram/NOTATION.md +80 -0
- package/skills/uml-class-diagram/SKILL.md +202 -168
- package/skills/uml-state-diagram/NOTATION.md +96 -0
- package/skills/uml-state-diagram/SKILL.md +192 -422
- package/skills/uml-use-case-diagram/NOTATION.md +221 -0
- package/skills/uml-use-case-diagram/SKILL.md +427 -496
- package/skills/bpmn-analysis/SKILL.backup.md +0 -359
package/README.md
CHANGED
|
@@ -1,84 +1,91 @@
|
|
|
1
1
|
# sad-mcp
|
|
2
2
|
|
|
3
|
-
MCP server that gives students access to **Software Analysis and Design** course materials through Claude Desktop.
|
|
3
|
+
MCP server that gives students access to **Software Analysis and Design** course materials and diagram tools through Claude Desktop.
|
|
4
4
|
|
|
5
|
-
##
|
|
5
|
+
## Student Setup
|
|
6
6
|
|
|
7
|
-
|
|
8
|
-
- Provides `search_materials` and `list_materials` **tools** for Claude to query course content
|
|
9
|
-
- Extracts text from PPTX, PDF, DOCX, XLSX, and plain text files
|
|
10
|
-
- Caches files locally to avoid repeated downloads
|
|
11
|
-
- Tracks anonymous usage for research purposes
|
|
7
|
+
### Step 1 — Find your config file
|
|
12
8
|
|
|
13
|
-
|
|
9
|
+
| How you installed Claude Desktop | Config file location |
|
|
10
|
+
|---|---|
|
|
11
|
+
| **Microsoft Store** (Windows) | `%LOCALAPPDATA%\Packages\Claude_pzs8sxrjxfjjc\LocalCache\Roaming\Claude\claude_desktop_config.json` |
|
|
12
|
+
| **Standard installer** (Windows) | `%APPDATA%\Roaming\Claude\claude_desktop_config.json` |
|
|
13
|
+
| **Mac** | `~/Library/Application Support/Claude/claude_desktop_config.json` |
|
|
14
14
|
|
|
15
|
-
|
|
15
|
+
Not sure which? Search your user profile for `claude_desktop_config.json`.
|
|
16
16
|
|
|
17
|
-
|
|
18
|
-
{
|
|
19
|
-
"mcpServers": {
|
|
20
|
-
"sad-course": {
|
|
21
|
-
"command": "npx",
|
|
22
|
-
"args": ["-y", "sad-mcp@latest"]
|
|
23
|
-
}
|
|
24
|
-
}
|
|
25
|
-
}
|
|
26
|
-
```
|
|
17
|
+
### Step 2 — Edit the config file
|
|
27
18
|
|
|
28
|
-
|
|
19
|
+
Open the file in a text editor and add the `sad-mcp` entry. If the file already has other MCP servers, add alongside them:
|
|
29
20
|
|
|
30
21
|
```json
|
|
31
22
|
{
|
|
32
23
|
"mcpServers": {
|
|
33
|
-
"sad-
|
|
34
|
-
"command": "
|
|
24
|
+
"sad-mcp": {
|
|
25
|
+
"command": "npx",
|
|
35
26
|
"args": ["-y", "sad-mcp@latest"]
|
|
36
27
|
}
|
|
37
28
|
}
|
|
38
29
|
}
|
|
39
30
|
```
|
|
40
31
|
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
32
|
+
> **Windows note:** If Claude Desktop doesn't find `npx`, use the full path:
|
|
33
|
+
> ```json
|
|
34
|
+
> {
|
|
35
|
+
> "mcpServers": {
|
|
36
|
+
> "sad-mcp": {
|
|
37
|
+
> "command": "C:\\Program Files\\nodejs\\npx.cmd",
|
|
38
|
+
> "args": ["-y", "sad-mcp@latest"]
|
|
39
|
+
> }
|
|
40
|
+
> }
|
|
41
|
+
> }
|
|
42
|
+
> ```
|
|
49
43
|
|
|
50
|
-
|
|
44
|
+
### Step 3 — Restart Claude Desktop
|
|
51
45
|
|
|
52
|
-
|
|
46
|
+
Fully quit Claude Desktop (system tray → Quit — not just close the window), then reopen it.
|
|
53
47
|
|
|
54
|
-
|
|
48
|
+
### Step 4 — Authenticate with Google
|
|
55
49
|
|
|
56
|
-
|
|
50
|
+
On the first tool call, a browser window will open for Google authentication. Sign in with your **@post.bgu.ac.il** account. After that, the server connects automatically on every restart.
|
|
57
51
|
|
|
58
|
-
|
|
59
|
-
|------|---------|
|
|
60
|
-
| `tokens.json` | Google OAuth refresh token |
|
|
61
|
-
| `anonymous-id.txt` | Random UUID for usage tracking |
|
|
62
|
-
| `usage-log.jsonl` | Local usage event log |
|
|
63
|
-
| `cache/` | Downloaded file cache (1-hour TTL) |
|
|
64
|
-
| `cache-index.json` | Cache metadata |
|
|
52
|
+
---
|
|
65
53
|
|
|
66
|
-
##
|
|
67
|
-
|
|
68
|
-
```bash
|
|
69
|
-
npm install
|
|
70
|
-
npm run build # compile TypeScript
|
|
71
|
-
npm run dev # watch mode
|
|
72
|
-
```
|
|
73
|
-
|
|
74
|
-
## Publishing
|
|
75
|
-
|
|
76
|
-
```bash
|
|
77
|
-
# bump version in package.json
|
|
78
|
-
npm publish
|
|
79
|
-
```
|
|
54
|
+
## What it does
|
|
80
55
|
|
|
81
|
-
|
|
56
|
+
### Course materials
|
|
57
|
+
- Search and browse lectures, transcripts, and past exams from the course Google Drive
|
|
58
|
+
- Extracts text from PPTX, PDF, DOCX files for full-text search
|
|
59
|
+
|
|
60
|
+
### Diagram tools
|
|
61
|
+
| Tool | What it does |
|
|
62
|
+
|---|---|
|
|
63
|
+
| `bpmn_analysis` | Analyze a business process and produce a BPMN 1.0 model |
|
|
64
|
+
| `bpmn_validate_model` | Validate the JSON model before rendering |
|
|
65
|
+
| `bpmn_render` | Render the validated model as an HTML file saved to your Desktop |
|
|
66
|
+
| `uml_use_case` | Create a UML use case diagram |
|
|
67
|
+
| `uml_class_diagram` | Create a UML class diagram |
|
|
68
|
+
| `uml_state_diagram` | Create a UML state diagram |
|
|
69
|
+
| `uml_write_file` | Save a generated UML diagram to your Desktop |
|
|
70
|
+
|
|
71
|
+
### Course material tools
|
|
72
|
+
| Tool | What it does |
|
|
73
|
+
|---|---|
|
|
74
|
+
| `search_materials` | Full-text search across all course materials |
|
|
75
|
+
| `list_materials` | List available materials by category |
|
|
76
|
+
| `get_material` | Read the full text of a specific file |
|
|
77
|
+
| `list_exams` | List available past exams |
|
|
78
|
+
| `practice_exam` | Get a past exam to practice with |
|
|
79
|
+
|
|
80
|
+
---
|
|
81
|
+
|
|
82
|
+
## Requirements
|
|
83
|
+
|
|
84
|
+
- [Claude Desktop](https://claude.ai/download) installed
|
|
85
|
+
- [Node.js](https://nodejs.org/) v18 or later (verify: `node --version` in a terminal)
|
|
86
|
+
- A `@post.bgu.ac.il` Google account with access to the course Drive folder
|
|
87
|
+
|
|
88
|
+
---
|
|
82
89
|
|
|
83
90
|
## License
|
|
84
91
|
|
|
@@ -0,0 +1,167 @@
|
|
|
1
|
+
// Generates BPMN 2.0 XML (with DI section) server-side, using the
|
|
2
|
+
// coordinates already computed by the layout pass. The VP export button
|
|
3
|
+
// embedded in the HTML just triggers a download of this precomputed
|
|
4
|
+
// string — no DOM walking, no getBBox() calls.
|
|
5
|
+
//
|
|
6
|
+
// Reference namespaces from OMG BPMN 2.0:
|
|
7
|
+
// bpmn http://www.omg.org/spec/BPMN/20100524/MODEL
|
|
8
|
+
// bpmndi http://www.omg.org/spec/BPMN/20100524/DI
|
|
9
|
+
// dc http://www.omg.org/spec/DD/20100524/DC
|
|
10
|
+
// di http://www.omg.org/spec/DD/20100524/DI
|
|
11
|
+
import { escapeXml } from "./svg.js";
|
|
12
|
+
export function buildBPMNXml(laid) {
|
|
13
|
+
const m = laid.model;
|
|
14
|
+
const title = escapeXml(m.title.en || m.title.he || "process");
|
|
15
|
+
// Map pool id → process id (each pool gets its own process element)
|
|
16
|
+
const processIds = new Map();
|
|
17
|
+
m.pools.forEach((p, i) => processIds.set(p.id, `process_${i + 1}`));
|
|
18
|
+
const processLines = [];
|
|
19
|
+
const collabLines = [];
|
|
20
|
+
// Participants reference pool processes
|
|
21
|
+
for (const p of m.pools) {
|
|
22
|
+
const procId = processIds.get(p.id);
|
|
23
|
+
collabLines.push(` <bpmn:participant id="${escapeXml(p.id)}" name="${escapeXml(p.name)}" processRef="${procId}"/>`);
|
|
24
|
+
}
|
|
25
|
+
for (const mf of m.messageFlows) {
|
|
26
|
+
const src = mf.fromElement ?? mf.fromPool;
|
|
27
|
+
const tgt = mf.toElement ?? mf.toPool;
|
|
28
|
+
const name = mf.label ? ` name="${escapeXml(mf.label)}"` : "";
|
|
29
|
+
collabLines.push(` <bpmn:messageFlow id="${escapeXml(mf.id)}" sourceRef="${escapeXml(src)}" targetRef="${escapeXml(tgt)}"${name}/>`);
|
|
30
|
+
}
|
|
31
|
+
// One bpmn:process block per pool
|
|
32
|
+
const processBlocks = [];
|
|
33
|
+
for (const p of m.pools) {
|
|
34
|
+
const procId = processIds.get(p.id);
|
|
35
|
+
const poolElements = m.elements.filter((el) => {
|
|
36
|
+
if (el.kind === "task" || el.kind === "gateway" || el.kind === "event" || el.kind === "collapsedSubProcess") {
|
|
37
|
+
return el.pool === p.id;
|
|
38
|
+
}
|
|
39
|
+
return false;
|
|
40
|
+
});
|
|
41
|
+
const poolFlows = m.sequenceFlows.filter((f) => {
|
|
42
|
+
const src = m.elements.find((e) => e.id === f.from);
|
|
43
|
+
const tgt = m.elements.find((e) => e.id === f.to);
|
|
44
|
+
if (!src || !tgt)
|
|
45
|
+
return false;
|
|
46
|
+
const srcPool = src.pool;
|
|
47
|
+
const tgtPool = tgt.pool;
|
|
48
|
+
return srcPool === p.id && tgtPool === p.id;
|
|
49
|
+
});
|
|
50
|
+
// Lanes (if organization pool with lanes)
|
|
51
|
+
const laneSetLines = [];
|
|
52
|
+
if (p.lanes.length > 0) {
|
|
53
|
+
laneSetLines.push(` <bpmn:laneSet id="${procId}_laneset">`);
|
|
54
|
+
for (const lane of p.lanes) {
|
|
55
|
+
const laneElements = poolElements.filter((e) => e.lane === lane.id);
|
|
56
|
+
laneSetLines.push(` <bpmn:lane id="${escapeXml(lane.id)}" name="${escapeXml(lane.name)}">`);
|
|
57
|
+
for (const le of laneElements) {
|
|
58
|
+
laneSetLines.push(` <bpmn:flowNodeRef>${escapeXml(le.id)}</bpmn:flowNodeRef>`);
|
|
59
|
+
}
|
|
60
|
+
laneSetLines.push(` </bpmn:lane>`);
|
|
61
|
+
}
|
|
62
|
+
laneSetLines.push(` </bpmn:laneSet>`);
|
|
63
|
+
}
|
|
64
|
+
// Element lines
|
|
65
|
+
const elLines = [];
|
|
66
|
+
for (const el of poolElements) {
|
|
67
|
+
const id = escapeXml(el.id);
|
|
68
|
+
const name = escapeXml(el.name ?? "");
|
|
69
|
+
if (el.kind === "task") {
|
|
70
|
+
elLines.push(` <bpmn:task id="${id}" name="${name}"/>`);
|
|
71
|
+
}
|
|
72
|
+
else if (el.kind === "collapsedSubProcess") {
|
|
73
|
+
elLines.push(` <bpmn:subProcess id="${id}" name="${name}"/>`);
|
|
74
|
+
}
|
|
75
|
+
else if (el.kind === "gateway") {
|
|
76
|
+
const tag = el.gatewayType === "AND" ? "parallelGateway"
|
|
77
|
+
: el.gatewayType === "OR" ? "inclusiveGateway"
|
|
78
|
+
: "exclusiveGateway";
|
|
79
|
+
elLines.push(` <bpmn:${tag} id="${id}" name="${name}"/>`);
|
|
80
|
+
}
|
|
81
|
+
else if (el.kind === "event") {
|
|
82
|
+
const tag = el.eventType === "start" ? "startEvent"
|
|
83
|
+
: el.eventType === "end" ? "endEvent"
|
|
84
|
+
: "intermediateCatchEvent";
|
|
85
|
+
elLines.push(` <bpmn:${tag} id="${id}" name="${name}"/>`);
|
|
86
|
+
}
|
|
87
|
+
}
|
|
88
|
+
// Data stores and objects are declared at process level
|
|
89
|
+
for (const el of m.elements) {
|
|
90
|
+
if (el.kind === "dataStore") {
|
|
91
|
+
elLines.push(` <bpmn:dataStoreReference id="${escapeXml(el.id)}" name="${escapeXml(el.name)}"/>`);
|
|
92
|
+
}
|
|
93
|
+
else if (el.kind === "dataObject") {
|
|
94
|
+
elLines.push(` <bpmn:dataObjectReference id="${escapeXml(el.id)}" name="${escapeXml(el.name)}"/>`);
|
|
95
|
+
}
|
|
96
|
+
}
|
|
97
|
+
for (const f of poolFlows) {
|
|
98
|
+
const name = f.label ? ` name="${escapeXml(f.label)}"` : "";
|
|
99
|
+
elLines.push(` <bpmn:sequenceFlow id="${escapeXml(f.id)}" sourceRef="${escapeXml(f.from)}" targetRef="${escapeXml(f.to)}"${name}/>`);
|
|
100
|
+
}
|
|
101
|
+
processBlocks.push(` <bpmn:process id="${procId}" name="${escapeXml(p.name)}" isExecutable="false">
|
|
102
|
+
${laneSetLines.join("\n")}
|
|
103
|
+
${elLines.join("\n")}
|
|
104
|
+
</bpmn:process>`);
|
|
105
|
+
}
|
|
106
|
+
// DI section — harvest coords from layout
|
|
107
|
+
const diLines = [];
|
|
108
|
+
// Pool shapes
|
|
109
|
+
for (const p of laid.pools) {
|
|
110
|
+
diLines.push(` <bpmndi:BPMNShape id="${escapeXml(p.poolId)}_di" bpmnElement="${escapeXml(p.poolId)}" isHorizontal="true">
|
|
111
|
+
<dc:Bounds x="${round(p.x)}" y="${round(p.y)}" width="${round(p.w)}" height="${round(p.h)}"/>
|
|
112
|
+
</bpmndi:BPMNShape>`);
|
|
113
|
+
for (const ln of p.lanes) {
|
|
114
|
+
if (!ln.laneId)
|
|
115
|
+
continue;
|
|
116
|
+
diLines.push(` <bpmndi:BPMNShape id="${escapeXml(ln.laneId)}_di" bpmnElement="${escapeXml(ln.laneId)}" isHorizontal="true">
|
|
117
|
+
<dc:Bounds x="${round(ln.x)}" y="${round(ln.y)}" width="${round(ln.w)}" height="${round(ln.h)}"/>
|
|
118
|
+
</bpmndi:BPMNShape>`);
|
|
119
|
+
}
|
|
120
|
+
}
|
|
121
|
+
// Element shapes
|
|
122
|
+
for (const [id, pl] of laid.placements) {
|
|
123
|
+
diLines.push(` <bpmndi:BPMNShape id="${escapeXml(id)}_di" bpmnElement="${escapeXml(id)}">
|
|
124
|
+
<dc:Bounds x="${round(pl.box.x)}" y="${round(pl.box.y)}" width="${round(pl.box.w)}" height="${round(pl.box.h)}"/>
|
|
125
|
+
</bpmndi:BPMNShape>`);
|
|
126
|
+
}
|
|
127
|
+
// Sequence flow edges
|
|
128
|
+
for (const r of laid.sequenceRoutes) {
|
|
129
|
+
const waypoints = r.points.map((p) => ` <di:waypoint x="${round(p.x)}" y="${round(p.y)}"/>`).join("\n");
|
|
130
|
+
diLines.push(` <bpmndi:BPMNEdge id="${escapeXml(r.id)}_di" bpmnElement="${escapeXml(r.id)}">
|
|
131
|
+
${waypoints}
|
|
132
|
+
</bpmndi:BPMNEdge>`);
|
|
133
|
+
}
|
|
134
|
+
for (const r of laid.messageRoutes) {
|
|
135
|
+
const waypoints = r.points.map((p) => ` <di:waypoint x="${round(p.x)}" y="${round(p.y)}"/>`).join("\n");
|
|
136
|
+
diLines.push(` <bpmndi:BPMNEdge id="${escapeXml(r.id)}_di" bpmnElement="${escapeXml(r.id)}">
|
|
137
|
+
${waypoints}
|
|
138
|
+
</bpmndi:BPMNEdge>`);
|
|
139
|
+
}
|
|
140
|
+
const xml = `<?xml version="1.0" encoding="UTF-8"?>
|
|
141
|
+
<bpmn:definitions xmlns:bpmn="http://www.omg.org/spec/BPMN/20100524/MODEL"
|
|
142
|
+
xmlns:bpmndi="http://www.omg.org/spec/BPMN/20100524/DI"
|
|
143
|
+
xmlns:dc="http://www.omg.org/spec/DD/20100524/DC"
|
|
144
|
+
xmlns:di="http://www.omg.org/spec/DD/20100524/DI"
|
|
145
|
+
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
|
|
146
|
+
id="Definitions_1" targetNamespace="http://bpmn.io/schema/bpmn">
|
|
147
|
+
${processBlocks.join("\n")}
|
|
148
|
+
<bpmn:collaboration id="collab_1">
|
|
149
|
+
${collabLines.join("\n")}
|
|
150
|
+
</bpmn:collaboration>
|
|
151
|
+
<bpmndi:BPMNDiagram id="BPMNDiagram_1">
|
|
152
|
+
<bpmndi:BPMNPlane id="BPMNPlane_1" bpmnElement="collab_1">
|
|
153
|
+
${diLines.join("\n")}
|
|
154
|
+
</bpmndi:BPMNPlane>
|
|
155
|
+
</bpmndi:BPMNDiagram>
|
|
156
|
+
</bpmn:definitions>`;
|
|
157
|
+
return xml;
|
|
158
|
+
}
|
|
159
|
+
function round(n) { return Math.round(n); }
|
|
160
|
+
// Returned for completeness — a caller may want the stable safe title
|
|
161
|
+
export function safeFilename(m) {
|
|
162
|
+
const base = (m.title.en || m.title.he || "process")
|
|
163
|
+
.replace(/[^\p{L}\p{N}\s_-]/gu, "")
|
|
164
|
+
.replace(/\s+/g, "_")
|
|
165
|
+
.slice(0, 60);
|
|
166
|
+
return base || "process";
|
|
167
|
+
}
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
import { layoutModel } from "./layout.js";
|
|
2
|
+
import { routeAll } from "./routing.js";
|
|
3
|
+
import { computeStats, renderHTML, type RenderStats } from "./template.js";
|
|
4
|
+
import { parseAndValidate, validateModel, formatIssues } from "./validate.js";
|
|
5
|
+
import type { DiagramModel, ValidationIssue } from "./types.js";
|
|
6
|
+
import { safeFilename } from "./export-bpmn.js";
|
|
7
|
+
export type RenderResult = {
|
|
8
|
+
ok: true;
|
|
9
|
+
html: string;
|
|
10
|
+
stats: RenderStats;
|
|
11
|
+
filenameBase: string;
|
|
12
|
+
} | {
|
|
13
|
+
ok: false;
|
|
14
|
+
issues: ValidationIssue[];
|
|
15
|
+
};
|
|
16
|
+
export declare function renderBPMN(rawJson: string | object): RenderResult;
|
|
17
|
+
export { validateModel, parseAndValidate, formatIssues, layoutModel, routeAll, renderHTML, computeStats, safeFilename, };
|
|
18
|
+
export type { DiagramModel, ValidationIssue };
|
|
@@ -0,0 +1,23 @@
|
|
|
1
|
+
// Public entry point for the BPMN rendering pipeline.
|
|
2
|
+
// Pipeline: raw JSON → validate → layout → route → render HTML.
|
|
3
|
+
import { layoutModel } from "./layout.js";
|
|
4
|
+
import { routeAll } from "./routing.js";
|
|
5
|
+
import { computeStats, renderHTML } from "./template.js";
|
|
6
|
+
import { parseAndValidate, validateModel, formatIssues } from "./validate.js";
|
|
7
|
+
import { safeFilename } from "./export-bpmn.js";
|
|
8
|
+
export function renderBPMN(rawJson) {
|
|
9
|
+
const vr = typeof rawJson === "string"
|
|
10
|
+
? parseAndValidate(rawJson)
|
|
11
|
+
: validateModel(rawJson);
|
|
12
|
+
if (!vr.ok)
|
|
13
|
+
return { ok: false, issues: vr.issues };
|
|
14
|
+
const laid = routeAll(layoutModel(vr.model));
|
|
15
|
+
const html = renderHTML(laid);
|
|
16
|
+
return {
|
|
17
|
+
ok: true,
|
|
18
|
+
html,
|
|
19
|
+
stats: computeStats(laid),
|
|
20
|
+
filenameBase: safeFilename(vr.model),
|
|
21
|
+
};
|
|
22
|
+
}
|
|
23
|
+
export { validateModel, parseAndValidate, formatIssues, layoutModel, routeAll, renderHTML, computeStats, safeFilename, };
|
|
@@ -0,0 +1,22 @@
|
|
|
1
|
+
import type { DiagramModel, LaidOutModel } from "./types.js";
|
|
2
|
+
export declare const L: {
|
|
3
|
+
readonly TASK_W: 140;
|
|
4
|
+
readonly TASK_H: 64;
|
|
5
|
+
readonly GW: 48;
|
|
6
|
+
readonly EVT_R: 18;
|
|
7
|
+
readonly COL_W: 186;
|
|
8
|
+
readonly GAP_X: 46;
|
|
9
|
+
readonly GAP_Y: 20;
|
|
10
|
+
readonly POOL_HEADER_W: 30;
|
|
11
|
+
readonly LANE_HEADER_W: 24;
|
|
12
|
+
readonly POOL_VGAP: 16;
|
|
13
|
+
readonly LANE_MIN_H: 140;
|
|
14
|
+
readonly LANE_CORRIDOR_H: 56;
|
|
15
|
+
readonly EMPTY_POOL_H: 60;
|
|
16
|
+
readonly CANVAS_TOP: 72;
|
|
17
|
+
readonly CANVAS_LEFT_PAD: 20;
|
|
18
|
+
readonly CANVAS_RIGHT_PAD: 40;
|
|
19
|
+
readonly CANVAS_BOTTOM_PAD: 20;
|
|
20
|
+
readonly MIN_CANVAS_W: 1400;
|
|
21
|
+
};
|
|
22
|
+
export declare function layoutModel(m: DiagramModel): LaidOutModel;
|