@rws-framework/ai-tools 0.0.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.
Files changed (82) hide show
  1. package/.bin/add-v.sh +10 -0
  2. package/.bin/emerge.sh +11 -0
  3. package/.emerge-vis-output/rws-server/emerge-file_result_dependency_graph.graphml +2067 -0
  4. package/.emerge-vis-output/rws-server/emerge-filesystem_graph.graphml +1505 -0
  5. package/.emerge-vis-output/rws-server/emerge-statistics-and-metrics.json +1 -0
  6. package/.emerge-vis-output/rws-server/emerge-statistics-metrics.txt +1147 -0
  7. package/.emerge-vis-output/rws-server/html/emerge.html +501 -0
  8. package/.emerge-vis-output/rws-server/html/jsconfig.json +9 -0
  9. package/.emerge-vis-output/rws-server/html/resources/css/custom.css +211 -0
  10. package/.emerge-vis-output/rws-server/html/resources/js/emerge_common.js +45 -0
  11. package/.emerge-vis-output/rws-server/html/resources/js/emerge_data.js +13 -0
  12. package/.emerge-vis-output/rws-server/html/resources/js/emerge_git.js +1414 -0
  13. package/.emerge-vis-output/rws-server/html/resources/js/emerge_graph.js +539 -0
  14. package/.emerge-vis-output/rws-server/html/resources/js/emerge_heatmap.js +220 -0
  15. package/.emerge-vis-output/rws-server/html/resources/js/emerge_hull.js +180 -0
  16. package/.emerge-vis-output/rws-server/html/resources/js/emerge_main.js +1003 -0
  17. package/.emerge-vis-output/rws-server/html/resources/js/emerge_search.js +71 -0
  18. package/.emerge-vis-output/rws-server/html/resources/js/emerge_ui.js +199 -0
  19. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-grid.css +4124 -0
  20. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-grid.css.map +1 -0
  21. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-grid.min.css +7 -0
  22. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-grid.min.css.map +1 -0
  23. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-grid.rtl.css +4123 -0
  24. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-grid.rtl.css.map +1 -0
  25. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-grid.rtl.min.css +7 -0
  26. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-grid.rtl.min.css.map +1 -0
  27. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-reboot.css +488 -0
  28. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-reboot.css.map +1 -0
  29. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-reboot.min.css +7 -0
  30. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-reboot.min.css.map +1 -0
  31. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-reboot.rtl.css +485 -0
  32. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-reboot.rtl.css.map +1 -0
  33. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-reboot.rtl.min.css +7 -0
  34. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-reboot.rtl.min.css.map +1 -0
  35. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-utilities.css +4266 -0
  36. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-utilities.css.map +1 -0
  37. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-utilities.min.css +7 -0
  38. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-utilities.min.css.map +1 -0
  39. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-utilities.rtl.css +4257 -0
  40. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-utilities.rtl.css.map +1 -0
  41. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-utilities.rtl.min.css +7 -0
  42. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap-utilities.rtl.min.css.map +1 -0
  43. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap.css +10878 -0
  44. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap.css.map +1 -0
  45. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap.min.css +7 -0
  46. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap.min.css.map +1 -0
  47. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap.rtl.css +10842 -0
  48. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap.rtl.css.map +1 -0
  49. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap.rtl.min.css +7 -0
  50. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/css/bootstrap.rtl.min.css.map +1 -0
  51. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/js/bootstrap.bundle.js +7075 -0
  52. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/js/bootstrap.bundle.js.map +1 -0
  53. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/js/bootstrap.bundle.min.js +7 -0
  54. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/js/bootstrap.bundle.min.js.map +1 -0
  55. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/js/bootstrap.esm.js +5202 -0
  56. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/js/bootstrap.esm.js.map +1 -0
  57. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/js/bootstrap.esm.min.js +7 -0
  58. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/js/bootstrap.esm.min.js.map +1 -0
  59. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/js/bootstrap.js +5249 -0
  60. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/js/bootstrap.js.map +1 -0
  61. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/js/bootstrap.min.js +7 -0
  62. package/.emerge-vis-output/rws-server/html/vendors/bootstrap/js/bootstrap.min.js.map +1 -0
  63. package/.emerge-vis-output/rws-server/html/vendors/d3/d3.v7.8.4.min.js +2 -0
  64. package/.emerge-vis-output/rws-server/html/vendors/d3/d3.v7.min.js +2 -0
  65. package/.emerge-vis-output/rws-server/html/vendors/dark-mode-switch/css/dark-mode.css +148 -0
  66. package/.emerge-vis-output/rws-server/html/vendors/dark-mode-switch/js/dark-mode-switch.min.js +1 -0
  67. package/.emerge-vis-output/rws-server/html/vendors/daterangepicker/daterangepicker.css +410 -0
  68. package/.emerge-vis-output/rws-server/html/vendors/daterangepicker/daterangepicker.min.js +8 -0
  69. package/.emerge-vis-output/rws-server/html/vendors/daterangepicker/moment.min.js +7 -0
  70. package/.emerge-vis-output/rws-server/html/vendors/hull/hull.js +373 -0
  71. package/.emerge-vis-output/rws-server/html/vendors/jquery/jquery-3.6.0.min.js +2 -0
  72. package/.emerge-vis-output/rws-server/html/vendors/popper/popper.min.js +6 -0
  73. package/.emerge-vis-output/rws-server/html/vendors/simpleheat/simpleheat.js +141 -0
  74. package/.eslintrc.json +53 -0
  75. package/README.md +862 -0
  76. package/package.json +49 -0
  77. package/src/index.ts +22 -0
  78. package/src/models/convo/ConvoLoader.ts +415 -0
  79. package/src/models/convo/VectorStore.ts +33 -0
  80. package/src/models/prompts/_prompt.ts +388 -0
  81. package/src/services/VectorStoreService.ts +15 -0
  82. package/tsconfig.json +24 -0
@@ -0,0 +1,539 @@
1
+ /**
2
+ * * MARK: - Drawing on canvas
3
+ */
4
+ function drawEdges(context) {
5
+ currentGraph.links.forEach(function(d) {
6
+
7
+ context.beginPath();
8
+ context.moveTo(d.source.x, d.source.y);
9
+ context.lineTo(d.target.x, d.target.y);
10
+
11
+ if (closeNode == null) { // not hovering over any node
12
+ if (isSearching == false) { // not searching
13
+ context.fillStyle = context.strokeStyle = nodeSourceColor = nodeColorByModularity(d.source, 0.7)
14
+
15
+ } else { // node search is active
16
+
17
+ if (addSemanticSearch == true) {
18
+
19
+ // the edge is between two nodes that are included in the search OR the edge is between two nodes that includes the search in one of their semantic keywords
20
+ if ( edgeBetweenSearchTerms(d.source, d.target) || searchTermsIncludedInNodeTags(d.source, d.target) )
21
+ {
22
+ context.strokeStyle = currentActiveEdgeColor
23
+ context.fillStyle = currentActiveEdgeColor
24
+ } else { // the edge is not connected to a node which is included in the search
25
+ context.fillStyle = context.strokeStyle = currentPassiveEdgeColor
26
+ }
27
+
28
+
29
+ } else { // normal search without semantic
30
+ // the edge is between two nodes that are included in the search
31
+ if (edgeBetweenSearchTerms(d.source, d.target))
32
+ {
33
+ context.strokeStyle = currentActiveEdgeColor
34
+ context.fillStyle = currentActiveEdgeColor
35
+ } else { // the edge is not connected to a node which is included in the search
36
+ context.fillStyle = context.strokeStyle = currentPassiveEdgeColor
37
+ }
38
+ }
39
+
40
+ if (addContributorSearch == true ) {
41
+ // the edge is between two nodes that are included in the search OR the edge is between two nodes that includes the search in one of their semantic keywords
42
+ if ( searchTermsIncludedInNodeContributors(d.source, d.target) )
43
+ {
44
+ context.strokeStyle = currentActiveEdgeColor
45
+ context.fillStyle = currentActiveEdgeColor
46
+ }
47
+ }
48
+
49
+ }
50
+
51
+ } else {
52
+ if ((d.target.id == closeNode.id) || (d.source.id == closeNode.id)) { // there is an edge that contains our hovered node
53
+ context.strokeStyle = currentActiveEdgeColor
54
+ context.fillStyle = currentActiveEdgeColor
55
+
56
+ } else { // node is not included in the edge
57
+ context.fillStyle = context.strokeStyle = nodeColorByModularity(d.source, 0.2)
58
+ }
59
+ }
60
+
61
+ // highlight edge if the corresponding nodes are selected
62
+ if (d.source.id.toLowerCase() in selectedNodesMap && d.target.id.toLowerCase() in selectedNodesMap) {
63
+ context.strokeStyle = activeSelectionColor
64
+ context.fillStyle = currentActiveEdgeColor
65
+ context.lineWidth = 2.0;
66
+ } else {
67
+ if (fadeUnselectedNodes == true || normalHeatmapIsActive() || churnHeatmapIsActive() || hotspotHeatmapIsActive()) { // also fade away non-relevant egdes
68
+ context.fillStyle = context.strokeStyle = nodeColorByModularity(d.source, unselectedNodesOpacity)
69
+ }
70
+ context.lineWidth = 1.0;
71
+ }
72
+
73
+ context.stroke();
74
+
75
+ if (closeNode != null && ((d.target.id == closeNode.id) || (d.source.id == closeNode.id))) { // draw an arrow if there is an edge that contains our hovered node
76
+ drawArrowhead(context, d.source, d.target, 5)
77
+
78
+ } else if (isSearching && ( (searchTermIncludedInNode(d.target) ) && ( searchTermIncludedInNode(d.source)) )) { // draw an arrow if searching is enabled and there's an egde between searched nodes
79
+ drawArrowhead(context, d.source, d.target, 5)
80
+ }
81
+
82
+ else if (d.source.id.toLowerCase() in selectedNodesMap && d.target.id.toLowerCase() in selectedNodesMap) {
83
+ drawArrowhead(context, d.source, d.target, 5)
84
+ }
85
+
86
+ });
87
+ }
88
+
89
+ function drawNodes(context) {
90
+ currentGraph.nodes.forEach(function(d, i) {
91
+
92
+ context.beginPath();
93
+
94
+ //render outer circle if node was selected
95
+ if (d.id.toLowerCase() in selectedNodesMap) {
96
+
97
+ context.arc(d.x, d.y, d.radius + 2.0, 0, TWO_TIMES_PI);
98
+ context.fillStyle = '#FF0000' //activeSelectionColor
99
+ drawNodeLabel(d.id, d.x + 14, d.y - 7)
100
+ context.fill();
101
+ }
102
+
103
+ context.arc(d.x, d.y, d.radius, 0, TWO_TIMES_PI, true);
104
+
105
+ if (fadeUnselectedNodes == true || normalHeatmapIsActive() || churnHeatmapIsActive() || hotspotHeatmapIsActive()) {
106
+ context.strokeStyle = nodeStrokeStyle
107
+ context.fillStyle = hexToRGB(nodeStrokeStyle, unselectedNodesOpacity)
108
+ context.stroke();
109
+
110
+ if (nodeLabelsEnabled) {
111
+ context.fillStyle = currentPassiveNodeLabelColor;
112
+ drawNodeLabel(d.id, d.x + 14, d.y - 7)
113
+ context.fillStyle = nodeColorByModularity(d, unselectedNodesOpacity)
114
+ }
115
+
116
+ } else {
117
+
118
+ if (closeNode == null) { // not hovering over any node
119
+ if (isSearching == false) {
120
+
121
+ context.fillStyle = nodeColorByModularity(d)
122
+ context.strokeStyle = nodeStrokeStyle;
123
+ context.stroke();
124
+
125
+ if (nodeLabelsEnabled) {
126
+ context.fillStyle = currentActiveNodeLabelColor;
127
+ drawNodeLabel(d.id, d.x + 14, d.y - 7)
128
+ context.fillStyle = nodeColorByModularity(d)
129
+ }
130
+
131
+ } else { // searching for nodes
132
+
133
+ // normal (non-semantic) search
134
+ if ( addSemanticSearch == false && normalSearch(d)) {
135
+
136
+ context.fillStyle = nodeColorByModularity(d)
137
+ context.strokeStyle = nodeStrokeStyle;
138
+ context.stroke();
139
+
140
+ context.fillStyle = currentActiveNodeLabelColor;
141
+ drawNodeLabel(d.id, d.x + 14, d.y - 7)
142
+ context.fillStyle = nodeColorByModularity(d)
143
+
144
+ searchResults += 1
145
+
146
+ } else if ( addSemanticSearch == true && (searchTermIncludedInNode(d) || searchTermIncludedInNodeTags(d)) )
147
+ // add semantic search
148
+ // the node is included in the current search OR if the search in included in one of the node's semantic tags
149
+ // draw a highlight circle behind the found node due to semantic search
150
+ {
151
+ if ( searchTermIncludedInNodeTags(d) )
152
+ {
153
+ context.fillStyle = currentActiveNodeLabelColor;
154
+ drawNodeLabel(d.id, d.x + 14, d.y - 7)
155
+
156
+ drawNodeHighlight(d, nodeColorByModularity(d, 1.0))
157
+ context.strokeStyle = nodeStrokeStyle;
158
+ context.stroke();
159
+
160
+ drawNodeHighlight(d, semanticHeaderYellow, 2)
161
+ context.strokeStyle = nodeStrokeStyle;
162
+ context.stroke();
163
+
164
+ searchResults += 1
165
+
166
+ } else {
167
+
168
+ context.fillStyle = nodeColorByModularity(d)
169
+ context.strokeStyle = nodeStrokeStyle;
170
+ context.stroke();
171
+
172
+ context.fillStyle = currentActiveNodeLabelColor;
173
+ drawNodeLabel(d.id, d.x + 14, d.y - 7)
174
+ context.fillStyle = nodeColorByModularity(d)
175
+
176
+ searchResults += 1
177
+ }
178
+
179
+ } else {
180
+ context.fillStyle = nodeColorByModularity(d, 0.2)
181
+ context.strokeStyle = hexToRGB(nodeStrokeStyle, 0.2)
182
+ context.stroke();
183
+
184
+ if (nodeLabelsEnabled) {
185
+ context.fillStyle = currentPassiveNodeLabelColor;
186
+ drawNodeLabel(d.id, d.x + 14, d.y - 7)
187
+ context.fillStyle = nodeColorByModularity(d, 0.2)
188
+ }
189
+ }
190
+ }
191
+
192
+ // contributors search
193
+ if (addContributorSearch == true && searchTermIncludedInNodeContributors(d)) {
194
+
195
+ context.fillStyle = currentActiveNodeLabelColor;
196
+ drawNodeLabel(d.id, d.x + 14, d.y - 7)
197
+
198
+ drawNodeHighlight(d, nodeColorByModularity(d, 1.0))
199
+ context.strokeStyle = nodeStrokeStyle;
200
+ context.stroke();
201
+
202
+ drawNodeHighlight(d, contributorsPurple, 2)
203
+ context.strokeStyle = nodeStrokeStyle;
204
+ context.stroke();
205
+
206
+ searchResults += 1
207
+ }
208
+
209
+ } else { // hovering over a node
210
+ if (isConnected(d, closeNode)) { // node is connected to hovered node
211
+ context.fillStyle = nodeColorByModularity(d)
212
+ context.strokeStyle = nodeStrokeStyle;
213
+ context.stroke();
214
+
215
+ // show/highlight node label of every connected node from the hovered node
216
+ context.fillStyle = currentActiveNodeLabelColor;
217
+ drawNodeLabel(d.id, d.x + 14, d.y - 7)
218
+ context.fillStyle = nodeColorByModularity(d)
219
+
220
+ } else if ( hoverCoupling == true && nodeNamesHaveChangeCoupling(d.id, closeNode.id) ) {
221
+
222
+ context.fillStyle = currentActiveNodeLabelColor;
223
+ drawNodeLabel(d.id, d.x + 14, d.y - 7)
224
+
225
+ drawNodeHighlight(d, nodeColorByModularity(d, 1.0))
226
+ context.strokeStyle = nodeStrokeStyle;
227
+ context.stroke();
228
+
229
+ drawNodeHighlight(d, changeCouplingColor, 2)
230
+ context.strokeStyle = nodeStrokeStyle;
231
+ context.stroke();
232
+
233
+ } else { // node is not connected
234
+
235
+ if (d.id.toLowerCase() in selectedNodesMap) {
236
+ context.strokeStyle = nodeStrokeStyle
237
+ context.fillStyle = nodeColorByModularity(d)
238
+ context.stroke();
239
+ } else {
240
+ context.strokeStyle = hexToRGB(nodeStrokeStyle, 0.2)
241
+ context.fillStyle = nodeColorByModularity(d, 0.2)
242
+ context.stroke();
243
+ }
244
+
245
+ if (nodeLabelsEnabled) {
246
+ context.fillStyle = currentPassiveNodeLabelColor;
247
+ drawNodeLabel(d.id, d.x + 14, d.y - 7)
248
+ context.fillStyle = nodeColorByModularity(d, 0.2)
249
+ }
250
+ }
251
+ }
252
+
253
+ } // else not fade away unselected nodes
254
+
255
+ context.fill();
256
+
257
+ if (i == currentGraph.nodes.length - 1) { // dont call this to often due to performance
258
+
259
+ if (closeNode) {
260
+ context.beginPath();
261
+ drawNode(closeNode)
262
+
263
+ if (closeNode.id.toLowerCase() in selectedNodesMap) {
264
+ context.fillStyle = activeSelectionColor
265
+ } else {
266
+ context.fillStyle = nodeColorByModularity(closeNode)
267
+ }
268
+
269
+ context.fill();
270
+ context.strokeStyle = "#000000";
271
+ context.lineWidth = 1.0;
272
+ context.stroke();
273
+
274
+ drawNodeToolTip(closeNode.id, closeNode.x + 14, closeNode.y - 7, closeNode.metrics)
275
+ }
276
+ }
277
+ });
278
+ }
279
+
280
+ /**
281
+ * * MARK: - Connectivity checks
282
+ */
283
+ let linkedByIndex = {};
284
+
285
+ function isConnected(a, b) {
286
+ return isConnectedAsTarget(a, b) || isConnectedAsSource(a, b) || a.id === b.id;
287
+ }
288
+
289
+ function isConnectedAsSource(a, b) {
290
+ return linkedByIndex[`${a.id},${b.id}`];
291
+ }
292
+
293
+ function isConnectedAsTarget(a, b) {
294
+ return linkedByIndex[`${b.id},${a.id}`];
295
+ }
296
+
297
+
298
+
299
+ function drawLink(d) {
300
+ context.moveTo(d.source.x, d.source.y);
301
+ context.lineTo(d.target.x, d.target.y);
302
+ }
303
+
304
+ function drawNode(d) {
305
+ context.arc(d.x, d.y, d.radius, 0, TWO_TIMES_PI);
306
+ }
307
+
308
+ function drawNodeHighlight(node, color, radiusOffset) {
309
+ context.arc(node.x, node.y, node.radius + radiusOffset, 0, TWO_TIMES_PI);
310
+ context.fillStyle = color
311
+ context.strokeStyle = color;
312
+ context.stroke();
313
+ context.fill();
314
+ }
315
+
316
+ function drawNodeLabel(text, xPos, yPos) {
317
+ const fontSize = 8
318
+ context.font = fontSize + 'px Helvetica';
319
+ context.fillText(text, xPos, yPos);
320
+ }
321
+
322
+ function stringIncludedInNodeTags(string, node) {
323
+ let propertyNames = Object.getOwnPropertyNames(node.metrics)
324
+ let searchedTag = 'metric_tag_' + string
325
+ let found = false
326
+
327
+ let tagProperties = propertyNames.filter(function(property) {
328
+ return property.startsWith('metric_tag_')
329
+ })
330
+
331
+ tagProperties.forEach(function(propertyName) {
332
+ if (propertyName.toLowerCase().includes(string.toLowerCase())) {
333
+ found = true
334
+ }
335
+ })
336
+
337
+ return found
338
+ }
339
+
340
+ function stringIncludedInNodeContributors(string, node) {
341
+ let found = false
342
+ if (node.hasOwnProperty('metrics')) {
343
+ let metrics = node['metrics']
344
+ if ('metric_git_contributors' in metrics) {
345
+ const contributors = metrics['metric_git_contributors']
346
+ contributors.forEach(function(name) {
347
+ if (name.toLowerCase().includes(string.toLowerCase())) {
348
+ found = true
349
+ }
350
+ })
351
+ }
352
+ }
353
+
354
+ return found
355
+ }
356
+
357
+ function drawNodeToolTip(text, xPos, yPos, nodeMetrics) {
358
+
359
+ // $('#overallStatisticsModal').modal('show');
360
+
361
+ const fontSize = 14
362
+ context.font = fontSize + 'px Helvetica';
363
+
364
+ // determine the maximum label width
365
+ let maxLineWidth = 0
366
+ for (metricKey in nodeMetrics) {
367
+ const val = nodeMetrics[metricKey]
368
+ let human_readable_metric_name = metricKey.replace('metric_', '').replace(/_/gi, " ")
369
+ const w = context.measureText(human_readable_metric_name + ": " + val).width;
370
+ if (maxLineWidth < w) {
371
+ maxLineWidth = w
372
+ }
373
+ }
374
+
375
+ // check if actually the title line width if bigger than any metric label line width?
376
+ const nodeTitleLineWidth = context.measureText(text).width
377
+ if (nodeTitleLineWidth > maxLineWidth)
378
+ maxLineWidth = nodeTitleLineWidth
379
+
380
+ // draw the header/title of the toolip
381
+ let lineHeight = fontSize * 1.286;
382
+ context.fillStyle = hexToRGB("#0069d9", 1.0);
383
+ context.fillRect(xPos - 6, (yPos - lineHeight) + 2, maxLineWidth + 10, lineHeight + 4);
384
+ context.strokeStyle = hexToRGB("#333333", 1.0);
385
+ context.strokeRect(xPos - 6, (yPos - lineHeight) + 2, maxLineWidth + 10, lineHeight + 4)
386
+
387
+ context.fillStyle = hexToRGB("#FFFFFF", 0.8);
388
+ context.fillText(text, xPos, yPos);
389
+
390
+ // now draw the second tooltip box with all metric labels
391
+ let metricItem = 1
392
+ const metricFontSize = 14
393
+ const metricLineHeight = (metricFontSize * 1.286);
394
+ let yPosOffset = yPos + 10
395
+ let newYPos = 0
396
+ let renderWithTags = false
397
+
398
+ context.font = metricFontSize + 'px Helvetica';
399
+
400
+ for (metricKey in nodeMetrics) {
401
+
402
+ // do not include any tag/tfidf metric in the primary metric section
403
+ if (metricKey.includes('metric_tag')) {
404
+ renderWithTags = true
405
+ continue
406
+ }
407
+
408
+ let val = nodeMetrics[metricKey]
409
+ let human_readable_metric_name = metricKey.replace('metric_', '').replace(/_/gi, " ")
410
+ let metricItemText = human_readable_metric_name + ": " + val
411
+
412
+ newYPos = yPosOffset + (metricLineHeight * metricItem)
413
+
414
+ // Interesting bug: on Safari it seems to cause random lags if you do fillStyle/fillRect BEFORE strokeStyle/strokeRect
415
+ context.strokeStyle = toolTipMetricItemBoxColor
416
+ context.strokeRect(xPos - 6, (newYPos - metricLineHeight), maxLineWidth + 10, metricLineHeight)
417
+
418
+ context.fillStyle = toolTipMetricItemBoxFillColor
419
+ context.fillRect(xPos - 6, (newYPos - metricLineHeight), maxLineWidth + 10, metricLineHeight);
420
+
421
+ context.fillStyle = toolTipMetricItemTextColor;
422
+ context.fillText(metricItemText, xPos, newYPos - 4);
423
+
424
+ metricItem = metricItem + 1
425
+ }
426
+
427
+ // render tag/tfidf metric section
428
+ if (renderWithTags) {
429
+ let metricItem = 1
430
+ newYPos += 20
431
+
432
+ // draw the header/title of the toolip
433
+ context.fillStyle = hexToRGB("#f5bc42", 1.0);
434
+ context.fillRect(xPos - 6, (newYPos - lineHeight) + 2, maxLineWidth + 10, lineHeight + 4);
435
+ context.strokeStyle = hexToRGB("#333333", 1.0);
436
+ context.strokeRect(xPos - 6, (newYPos - lineHeight) + 2, maxLineWidth + 10, lineHeight + 4)
437
+ context.fillStyle = hexToRGB("#333333", 0.8);
438
+ context.fillText('Semantic keywords', xPos, newYPos);
439
+
440
+ let yTagPosOffset = newYPos + 10
441
+
442
+ // render tag/tfidf metrics
443
+ for (metricKey in nodeMetrics) {
444
+
445
+ // do not include any tag/tfidf metric in the primary metric section
446
+ if (!metricKey.includes('metric_tag')) {
447
+ continue
448
+ }
449
+
450
+ let val = nodeMetrics[metricKey]
451
+ let human_readable_metric_name = metricKey.replace('metric_tag', '').replace(/_/gi, "")
452
+ let metricItemText = human_readable_metric_name // + ": " + val
453
+
454
+ newYPos = yTagPosOffset + (metricLineHeight * metricItem)
455
+
456
+ // Interesting bug: on Safari it seems to cause random lags if you do fillStyle/fillRect BEFORE strokeStyle/strokeRect
457
+ context.strokeStyle = toolTipMetricItemBoxColor
458
+ context.strokeRect(xPos - 6, (newYPos - metricLineHeight), maxLineWidth + 10, metricLineHeight)
459
+
460
+ context.fillStyle = toolTipMetricItemBoxFillColor
461
+ context.fillRect(xPos - 6, (newYPos - metricLineHeight), maxLineWidth + 10, metricLineHeight);
462
+
463
+ context.fillStyle = toolTipMetricItemTextColor;
464
+ context.fillText(metricItemText, xPos, newYPos - 4);
465
+
466
+ metricItem = metricItem + 1
467
+ }
468
+ }
469
+ }
470
+
471
+ // borrowed from Scott Johnson / https://gist.github.com/jwir3/d797037d2e1bf78a9b04838d73436197 with minor adjustments
472
+ function drawArrowhead(context, from, to, radius) {
473
+ const x_center = 0.5 * (from.x + to.x)
474
+ const y_center = 0.5 * (from.y + to.y)
475
+
476
+ let angle;
477
+ let x;
478
+ let y;
479
+
480
+ context.beginPath();
481
+
482
+ angle = Math.atan2(to.y - from.y, to.x - from.x)
483
+ x = radius * Math.cos(angle) + x_center;
484
+ y = radius * Math.sin(angle) + y_center;
485
+
486
+ context.moveTo(x, y);
487
+
488
+ angle += ONE_THIRD_TWO_TIMES_PI
489
+ x = radius * Math.cos(angle) + x_center;
490
+ y = radius * Math.sin(angle) + y_center;
491
+
492
+ context.lineTo(x, y);
493
+
494
+ angle += ONE_THIRD_TWO_TIMES_PI
495
+ x = radius * Math.cos(angle) + x_center;
496
+ y = radius * Math.sin(angle) + y_center;
497
+
498
+ context.lineTo(x, y);
499
+ context.closePath();
500
+ context.fill();
501
+ }
502
+
503
+ function initNodeColorMap() {
504
+ currentGraph.nodes.forEach(function(node, i) {
505
+ nodeColorMap[node.id] = hexToRGB(color(node.metric_file_result_dependency_graph_louvain_modularity_in_file), 1.0)
506
+ })
507
+ }
508
+
509
+ function nodeColorByModularity(node, alpha = 1.0) {
510
+ if (currentGraphType.includes('file_result') || currentGraphType.includes('filesystem')) {
511
+ if ('metric_file_result_dependency_graph_louvain_modularity_in_file' in node) {
512
+ return hexToRGB(color(node.metric_file_result_dependency_graph_louvain_modularity_in_file), alpha)
513
+ } else if ('directory' in node) {
514
+ if (node.directory == true) {
515
+ return hexToRGB(directoryNodeColor)
516
+ }
517
+ }
518
+ } else {
519
+ if (currentGraphType.includes('entity_result_dependency_graph')) {
520
+ if ('metric_entity_result_dependency_graph_louvain_modularity_in_entity' in node) {
521
+ return hexToRGB(color(node.metric_entity_result_dependency_graph_louvain_modularity_in_entity), alpha)
522
+ }
523
+ }
524
+ if (currentGraphType.includes('entity_result_inheritance_graph')) {
525
+ if ('metric_entity_result_inheritance_graph_louvain_modularity_in_entity' in node) {
526
+ return hexToRGB(color(node.metric_entity_result_inheritance_graph_louvain_modularity_in_entity), alpha)
527
+ }
528
+ }
529
+
530
+ if (currentGraphType.includes('entity_result_complete_graph')) {
531
+ if ('metric_entity_result_complete_graph_louvain_modularity_in_entity' in node) {
532
+ return hexToRGB(color(node.metric_entity_result_complete_graph_louvain_modularity_in_entity), alpha)
533
+ }
534
+ }
535
+ }
536
+
537
+ return hexToRGB(defaultNodeColor)
538
+ }
539
+