Skip to content

Commit 3b7c83f

Browse files
Added two sample translation scripts
1 parent 7edc22a commit 3b7c83f

File tree

9 files changed

+315
-18
lines changed

9 files changed

+315
-18
lines changed

.gitignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,2 +1,3 @@
11
node_modules
22
dist
3+
samples/out/*

.npmignore

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1 @@
1+
samples

samples/.vscode/launch.json

Lines changed: 24 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,24 @@
1+
{
2+
// Use IntelliSense to learn about possible attributes.
3+
// Hover to view descriptions of existing attributes.
4+
// For more information, visit: https://go.microsoft.com/fwlink/?linkid=830387
5+
"version": "0.2.0",
6+
"configurations": [
7+
{
8+
"name": "plantUML",
9+
"program": "${workspaceFolder}/plantUML.ts",
10+
"request": "launch",
11+
"preLaunchTask": "tsc: build - tsconfig.json",
12+
"outFiles": ["${workspaceFolder}/out/**/*.js"],
13+
"type": "node"
14+
},
15+
{
16+
"name": "jsSequenceDiagrams",
17+
"program": "${workspaceFolder}/jsSequenceDiagrams.ts",
18+
"request": "launch",
19+
"preLaunchTask": "tsc: build - tsconfig.json",
20+
"outFiles": ["${workspaceFolder}/out/**/*.js"],
21+
"type": "node"
22+
}
23+
]
24+
}

samples/jsSequenceDiagrams.ts

Lines changed: 42 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,42 @@
1+
// Sample: translate an .art-trace file to the .ms format (see https://bramp.github.io/js-sequence-diagrams/)
2+
import fs from 'fs';
3+
import { fileURLToPath } from 'url';
4+
import path, { dirname } from 'path';
5+
const __filename = fileURLToPath(import.meta.url);
6+
const __dirname = dirname(__filename);
7+
8+
import readline from 'readline';
9+
import { parseLine, InstanceDecl, MessageOccurrance, TraceParserUtils } from 'art-trace';
10+
11+
const filePath = path.join(__dirname, '../traces/MoreOrLess/trace-with-timestamps.art-trace');
12+
13+
const input = fs.createReadStream(filePath, { encoding: 'utf8' });
14+
const rl = readline.createInterface({ input, crlfDelay: Infinity });
15+
try {
16+
let i = 0;
17+
let instanceMap = new Map<string, InstanceDecl>();
18+
19+
let applicationParticipantDeclared = false;
20+
let systemParticipantDeclared = false;
21+
let timerParticipantDeclared = false;
22+
for await (const line of rl) {
23+
let astNode = parseLine(line, i++);
24+
if (astNode instanceof InstanceDecl) {
25+
instanceMap.set(astNode.address.text, astNode);
26+
}
27+
else
28+
if (astNode instanceof MessageOccurrance) {
29+
let senderInst = instanceMap.get(astNode.sender.text);
30+
let receiverInst = instanceMap.get(astNode.receiver.text);
31+
let senderType = senderInst ? senderInst.dynamicType.text : "";
32+
let receiverType = receiverInst ? receiverInst.dynamicType.text : "";
33+
34+
let eventData = typeof astNode.data === 'string' ? astNode.data : JSON.stringify(astNode.data);
35+
console.log(`${astNode.senderName}(${senderType}) -> ${astNode.receiverName}(${receiverType}) : ${astNode.event.text}(${eventData})`);
36+
}
37+
}
38+
}
39+
finally {
40+
rl.close();
41+
input.close();
42+
}

samples/package.json

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,15 @@
1+
{
2+
"name": "art-trace-samples",
3+
"version": "1.0.0",
4+
"author": "Mattias Mohlin",
5+
"type":"module",
6+
"dependencies": {
7+
"typescript": "^5.9.3"
8+
},
9+
"scripts": {
10+
"build": "tsc"
11+
},
12+
"devDependencies": {
13+
"@types/node": "^24.8.1"
14+
}
15+
}

samples/plantUML.ts

Lines changed: 70 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,70 @@
1+
// Sample: translate an .art-trace file to Plant-UML format
2+
import fs from 'fs';
3+
import { fileURLToPath } from 'url';
4+
import path, { dirname } from 'path';
5+
const __filename = fileURLToPath(import.meta.url);
6+
const __dirname = dirname(__filename);
7+
8+
import readline from 'readline';
9+
import { parseLine, InstanceDecl, MessageOccurrance, TraceParserUtils } from 'art-trace';
10+
11+
const filePath = path.join(__dirname, '../traces/MoreOrLess/trace-with-timestamps.art-trace');
12+
13+
const lightGreen = '#37e937ff';
14+
const darkBlue = '#003366';
15+
const lightBlue = '#2e92b4';
16+
17+
const input = fs.createReadStream(filePath, { encoding: 'utf8' });
18+
const rl = readline.createInterface({ input, crlfDelay: Infinity });
19+
try {
20+
let i = 0;
21+
let instanceMap = new Map<string, InstanceDecl>();
22+
console.log("@startuml");
23+
let applicationParticipantDeclared = false;
24+
let systemParticipantDeclared = false;
25+
let timerParticipantDeclared = false;
26+
for await (const line of rl) {
27+
let astNode = parseLine(line, i++);
28+
if (astNode instanceof InstanceDecl) {
29+
instanceMap.set(astNode.address.text, astNode);
30+
}
31+
else if (astNode instanceof MessageOccurrance) {
32+
let senderInst = instanceMap.get(astNode.sender.text);
33+
let receiverInst = instanceMap.get(astNode.receiver.text);
34+
if (senderInst && receiverInst) {
35+
if (!applicationParticipantDeclared && (TraceParserUtils.isTopCapsuleInstance(senderInst) || TraceParserUtils.isTopCapsuleInstance(receiverInst))) {
36+
applicationParticipantDeclared = true;
37+
console.log(`participant application ${lightGreen}`);
38+
}
39+
if (!systemParticipantDeclared && (TraceParserUtils.isSystemInstance(senderInst) || TraceParserUtils.isSystemInstance(receiverInst))) {
40+
systemParticipantDeclared = true;
41+
console.log(`participant "<system>" ${lightBlue}`);
42+
}
43+
if (!timerParticipantDeclared && (TraceParserUtils.isTimerInstance(senderInst) || TraceParserUtils.isTimerInstance(receiverInst))) {
44+
timerParticipantDeclared = true;
45+
console.log(`participant "<timer>" ${lightBlue}`);
46+
}
47+
48+
let senderLifeline = getLifeLineText(senderInst);
49+
let receiverLifeline = getLifeLineText(receiverInst);
50+
51+
let eventData = typeof astNode.data === 'string' ? astNode.data : JSON.stringify(astNode.data);
52+
console.log(`"${senderLifeline}" -> "${receiverLifeline}": ${astNode.event.text}(${eventData})`);
53+
}
54+
}
55+
}
56+
console.log("@enduml");
57+
}
58+
finally {
59+
rl.close();
60+
input.close();
61+
}
62+
63+
function getLifeLineText(participant: InstanceDecl): string {
64+
if (TraceParserUtils.isSystemInstance(participant))
65+
return "<system>";
66+
if (TraceParserUtils.isTimerInstance(participant))
67+
return "<timer>";
68+
69+
return TraceParserUtils.structureExprToString(participant.structureExpr);
70+
}
Lines changed: 101 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,101 @@
1+
// Trace configuration:
2+
// {
3+
// "timestamps": {
4+
// "documentation": {
5+
// "mode": "absolute/relative(default)"
6+
// , "precision": "milli/micro/nano(default)"
7+
// , "time1_send": "true/false(default), time when sender places message into the message queue"
8+
// , "time2_receive": "true/false(default), time when controller delivers the message to the receiver"
9+
// , "time3_handle": "true/false(default), time when message was processed by the receiver"
10+
// }
11+
// , "mode": "relative"
12+
// , "precision": "nano"
13+
// , "time1_send": false
14+
// , "time2_receive": true
15+
// , "time3_handle": true
16+
// }
17+
// , "trace": {
18+
// "start_time": "2025-11-11 12:05:14.586791900"
19+
// }
20+
// }
21+
instance 0x22cc6827c50 Top : RTSuperActor
22+
instance 0x22cc6833550 specials : RTTimerActor
23+
0x22cc6827c50 Top -> 0x22cc6833550 specials : initialize() { "time2_receive": 3216600, "time3_handle": 4998400 }
24+
0x22cc6833550 specials -> 0x22cc6827c50 Top.timer : timeout() { "time2_receive": 3844200, "time3_handle": 13415100 }
25+
instance 0x22cc6833390 guesser[0] : Guesser
26+
instance 0x22cc6833260 application : Top
27+
0x22cc6833390 guesser.guesserP -> 0x22cc6833260 application.guesserP[0] : ready() { "time2_receive": 13418700, "time3_handle": 13617700 }
28+
instance 0x22cc680a130 guesser[1] : Guesser
29+
0x22cc680a130 guesser.guesserP -> 0x22cc6833260 application.guesserP[1] : ready() { "time2_receive": 13618900, "time3_handle": 13777300 }
30+
instance 0x22cc680a230 guesser[2] : Guesser
31+
0x22cc680a230 guesser.guesserP -> 0x22cc6833260 application.guesserP[2] : ready() { "time2_receive": 13779100, "time3_handle": 13929400 }
32+
instance 0x22cc680dca0 guesser[3] : Guesser
33+
0x22cc680dca0 guesser.guesserP -> 0x22cc6833260 application.guesserP[3] : ready() { "time2_receive": 13930500, "time3_handle": 14069800 }
34+
instance 0x22cc680dda0 guesser[4] : Guesser
35+
0x22cc680dda0 guesser.guesserP -> 0x22cc6833260 application.guesserP[4] : ready() { "time2_receive": 14070700, "time3_handle": 14217100 }
36+
instance 0x22cc680dea0 guesser[5] : Guesser
37+
0x22cc680dea0 guesser.guesserP -> 0x22cc6833260 application.guesserP[5] : ready() { "time2_receive": 14218000, "time3_handle": 14362400 }
38+
instance 0x22cc680dfa0 guesser[6] : Guesser
39+
0x22cc680dfa0 guesser.guesserP -> 0x22cc6833260 application.guesserP[6] : ready() { "time2_receive": 14363400, "time3_handle": 14535800 }
40+
instance 0x22cc680e0a0 guesser[7] : Guesser
41+
0x22cc680e0a0 guesser.guesserP -> 0x22cc6833260 application.guesserP[7] : ready() { "time2_receive": 14537600, "time3_handle": 14686600 }
42+
instance 0x22cc680e9b0 guesser[8] : Guesser
43+
0x22cc680e9b0 guesser.guesserP -> 0x22cc6833260 application.guesserP[8] : ready() { "time2_receive": 14687700, "time3_handle": 14836400 }
44+
instance 0x22cc680eab0 guesser[9] : Guesser
45+
0x22cc680eab0 guesser.guesserP -> 0x22cc6833260 application.guesserP[9] : ready() { "time2_receive": 14837500, "time3_handle": 14980700 }
46+
instance 0x22cc680ebb0 number : Number
47+
0x22cc680ebb0 number.cmdP -> 0x22cc6833260 application.cmdP : ready() { "time2_receive": 14981800, "time3_handle": 15677900 }
48+
0x22cc6833550 specials -> 0x22cc6833260 application.timerP : timeout() { "time2_receive": 516534200, "time3_handle": 518649800 }
49+
0x22cc6833260 application.guesserP[0] -> 0x22cc6833390 guesser.guesserP : doConnect(RTActorId 0x22cc680ebb0) { "time2_receive": 518656200, "time3_handle": 521348600 }
50+
0x22cc680ebb0 number.numberP -> 0x22cc6833390 guesser.numberP : rtBound() { "time2_receive": 521352800, "time3_handle": 523571600 }
51+
0x22cc6833390 guesser.numberP -> 0x22cc680ebb0 number.numberP : askHint() { "time2_receive": 523575400, "time3_handle": 524805600 }
52+
0x22cc680ebb0 number.numberP -> 0x22cc6833390 guesser.numberP : sendHint(Hint{current 100,isLess true,max 100,min 0}) { "time2_receive": 524812900, "time3_handle": 525691900 }
53+
0x22cc6833390 guesser.numberP -> 0x22cc680ebb0 number.numberP : guess(unsigned 50) { "time2_receive": 525697500, "time3_handle": 526099600 }
54+
instance 0x0 external : External
55+
0x0 external -> 0x22cc6833390 guesser.numberP : sendAnswer(bool false) { "time2_receive": 526101700, "time3_handle": 526109500 }
56+
0x22cc6833390 guesser.guesserP -> 0x22cc6833260 application.guesserP[0] : notFound() { "time2_receive": 526111000, "time3_handle": 527352400 }
57+
0x0 external -> 0x22cc6833390 guesser.numberP : rtUnbound() { "time2_receive": 527357800, "time3_handle": 527700200 }
58+
0x22cc6833550 specials -> 0x22cc6833260 application.timerP : timeout() { "time2_receive": 1032776700, "time3_handle": 1033875900 }
59+
0x22cc6833260 application.guesserP[1] -> 0x22cc680a130 guesser.guesserP : doConnect(RTActorId 0x22cc680ebb0) { "time2_receive": 1033878400, "time3_handle": 1034852300 }
60+
0x22cc680ebb0 number.numberP -> 0x22cc680a130 guesser.numberP : rtBound() { "time2_receive": 1034853800, "time3_handle": 1035635000 }
61+
0x22cc680a130 guesser.numberP -> 0x22cc680ebb0 number.numberP : askHint() { "time2_receive": 1035642900, "time3_handle": 1036343400 }
62+
0x22cc680ebb0 number.numberP -> 0x22cc680a130 guesser.numberP : sendHint(Hint{current 50,isLess false,max 100,min 50}) { "time2_receive": 1036344900, "time3_handle": 1036813900 }
63+
0x22cc680a130 guesser.numberP -> 0x22cc680ebb0 number.numberP : guess(unsigned 75) { "time2_receive": 1036815300, "time3_handle": 1036920900 }
64+
0x0 external -> 0x22cc680a130 guesser.numberP : sendAnswer(bool false) { "time2_receive": 1036921900, "time3_handle": 1036924900 }
65+
0x22cc680a130 guesser.guesserP -> 0x22cc6833260 application.guesserP[1] : notFound() { "time2_receive": 1036925700, "time3_handle": 1037775000 }
66+
0x0 external -> 0x22cc680a130 guesser.numberP : rtUnbound() { "time2_receive": 1037776200, "time3_handle": 1038418600 }
67+
0x22cc6833550 specials -> 0x22cc6833260 application.timerP : timeout() { "time2_receive": 1546646700, "time3_handle": 1547259400 }
68+
0x22cc6833260 application.guesserP[2] -> 0x22cc680a230 guesser.guesserP : doConnect(RTActorId 0x22cc680ebb0) { "time2_receive": 1547263000, "time3_handle": 1549165200 }
69+
0x22cc680ebb0 number.numberP -> 0x22cc680a230 guesser.numberP : rtBound() { "time2_receive": 1549167100, "time3_handle": 1550061000 }
70+
0x22cc680a230 guesser.numberP -> 0x22cc680ebb0 number.numberP : askHint() { "time2_receive": 1550062400, "time3_handle": 1550585900 }
71+
0x22cc680ebb0 number.numberP -> 0x22cc680a230 guesser.numberP : sendHint(Hint{current 75,isLess true,max 75,min 50}) { "time2_receive": 1550587200, "time3_handle": 1550943600 }
72+
0x22cc680a230 guesser.numberP -> 0x22cc680ebb0 number.numberP : guess(unsigned 63) { "time2_receive": 1550944700, "time3_handle": 1551182900 }
73+
0x0 external -> 0x22cc680a230 guesser.numberP : sendAnswer(bool false) { "time2_receive": 1551184600, "time3_handle": 1551188300 }
74+
0x22cc680a230 guesser.guesserP -> 0x22cc6833260 application.guesserP[2] : notFound() { "time2_receive": 1551189200, "time3_handle": 1552361000 }
75+
0x0 external -> 0x22cc680a230 guesser.numberP : rtUnbound() { "time2_receive": 1552362200, "time3_handle": 1552648300 }
76+
0x22cc6833550 specials -> 0x22cc6833260 application.timerP : timeout() { "time2_receive": 2051576600, "time3_handle": 2052665000 }
77+
0x22cc6833260 application.guesserP[3] -> 0x22cc680dca0 guesser.guesserP : doConnect(RTActorId 0x22cc680ebb0) { "time2_receive": 2052670600, "time3_handle": 2054638900 }
78+
0x22cc680ebb0 number.numberP -> 0x22cc680dca0 guesser.numberP : rtBound() { "time2_receive": 2054642200, "time3_handle": 2056306500 }
79+
0x22cc680dca0 guesser.numberP -> 0x22cc680ebb0 number.numberP : askHint() { "time2_receive": 2056310500, "time3_handle": 2058392700 }
80+
0x22cc680ebb0 number.numberP -> 0x22cc680dca0 guesser.numberP : sendHint(Hint{current 63,isLess true,max 63,min 50}) { "time2_receive": 2058396300, "time3_handle": 2059341100 }
81+
0x22cc680dca0 guesser.numberP -> 0x22cc680ebb0 number.numberP : guess(unsigned 57) { "time2_receive": 2059348500, "time3_handle": 2059758100 }
82+
0x0 external -> 0x22cc680dca0 guesser.numberP : sendAnswer(bool false) { "time2_receive": 2059760900, "time3_handle": 2059767300 }
83+
0x22cc680dca0 guesser.guesserP -> 0x22cc6833260 application.guesserP[3] : notFound() { "time2_receive": 2059769000, "time3_handle": 2061450500 }
84+
0x0 external -> 0x22cc680dca0 guesser.numberP : rtUnbound() { "time2_receive": 2061456600, "time3_handle": 2061956200 }
85+
0x22cc6833550 specials -> 0x22cc6833260 application.timerP : timeout() { "time2_receive": 2571432700, "time3_handle": 2575458800 }
86+
0x22cc6833260 application.guesserP[4] -> 0x22cc680dda0 guesser.guesserP : doConnect(RTActorId 0x22cc680ebb0) { "time2_receive": 2575464600, "time3_handle": 2576667200 }
87+
0x22cc680ebb0 number.numberP -> 0x22cc680dda0 guesser.numberP : rtBound() { "time2_receive": 2576674300, "time3_handle": 2577509400 }
88+
0x22cc680dda0 guesser.numberP -> 0x22cc680ebb0 number.numberP : askHint() { "time2_receive": 2577511000, "time3_handle": 2578011400 }
89+
0x22cc680ebb0 number.numberP -> 0x22cc680dda0 guesser.numberP : sendHint(Hint{current 57,isLess false,max 63,min 57}) { "time2_receive": 2578012900, "time3_handle": 2578412300 }
90+
0x22cc680dda0 guesser.numberP -> 0x22cc680ebb0 number.numberP : guess(unsigned 60) { "time2_receive": 2578413800, "time3_handle": 2578867500 }
91+
0x0 external -> 0x22cc680dda0 guesser.numberP : sendAnswer(bool false) { "time2_receive": 2578869100, "time3_handle": 2578931400 }
92+
0x22cc680dda0 guesser.guesserP -> 0x22cc6833260 application.guesserP[4] : notFound() { "time2_receive": 2578932500, "time3_handle": 2580032100 }
93+
0x0 external -> 0x22cc680dda0 guesser.numberP : rtUnbound() { "time2_receive": 2580033600, "time3_handle": 2580401600 }
94+
0x22cc6833550 specials -> 0x22cc6833260 application.timerP : timeout() { "time2_receive": 3093621500, "time3_handle": 3097145200 }
95+
0x22cc6833260 application.guesserP[5] -> 0x22cc680dea0 guesser.guesserP : doConnect(RTActorId 0x22cc680ebb0) { "time2_receive": 3097153500, "time3_handle": 3099809900 }
96+
0x22cc680ebb0 number.numberP -> 0x22cc680dea0 guesser.numberP : rtBound() { "time2_receive": 3099814800, "time3_handle": 3101654600 }
97+
0x22cc680dea0 guesser.numberP -> 0x22cc680ebb0 number.numberP : askHint() { "time2_receive": 3101659200, "time3_handle": 3102890500 }
98+
0x22cc680ebb0 number.numberP -> 0x22cc680dea0 guesser.numberP : sendHint(Hint{current 60,isLess true,max 60,min 57}) { "time2_receive": 3102894500, "time3_handle": 3104804800 }
99+
0x22cc680dea0 guesser.numberP -> 0x22cc680ebb0 number.numberP : guess(unsigned 59) { "time2_receive": 3104808200, "time3_handle": 3105534100 }
100+
0x0 external -> 0x22cc680dea0 guesser.numberP : sendAnswer(bool true) { "time2_receive": 3105536500, "time3_handle": 3105541900 }
101+
0x22cc680dea0 guesser.guesserP -> 0x22cc6833260 application.guesserP[5] : found(unsigned 59) { "time2_receive": 3105543200, "time3_handle": 3107114300 }

samples/tsconfig.json

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,29 @@
1+
{
2+
"compilerOptions": {
3+
"esModuleInterop": true,
4+
"skipLibCheck": true,
5+
"target": "ES2019",
6+
"allowJs": true,
7+
"resolveJsonModule": true,
8+
"moduleDetection": "force",
9+
"isolatedModules": true,
10+
"moduleResolution": "node",
11+
"baseUrl": "./",
12+
"paths": {
13+
"*": ["node_modules/*"]
14+
},
15+
16+
"noImplicitOverride": true,
17+
18+
"module": "ESNext",
19+
"outDir": "out",
20+
"rootDir": "./",
21+
"sourceMap": true,
22+
23+
"declaration": true,
24+
"declarationMap": true,
25+
26+
"lib": ["ES2019"]
27+
},
28+
"include": ["./*.ts"]
29+
}

0 commit comments

Comments
 (0)