mocktail 1.2.3 → 2.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (183) hide show
  1. checksums.yaml +4 -4
  2. data/.github/workflows/main.yml +6 -5
  3. data/.gitignore +3 -0
  4. data/.standard.yml +8 -0
  5. data/CHANGELOG.md +14 -0
  6. data/Gemfile +6 -1
  7. data/Gemfile.lock +98 -25
  8. data/README.md +18 -922
  9. data/Rakefile +0 -1
  10. data/bin/console +1 -2
  11. data/bin/tapioca +29 -0
  12. data/lib/mocktail/collects_calls.rb +2 -0
  13. data/lib/mocktail/debug.rb +13 -10
  14. data/lib/mocktail/dsl.rb +2 -0
  15. data/lib/mocktail/errors.rb +2 -0
  16. data/lib/mocktail/explains_nils.rb +2 -0
  17. data/lib/mocktail/explains_thing.rb +7 -4
  18. data/lib/mocktail/grabs_original_method_parameters.rb +30 -0
  19. data/lib/mocktail/handles_dry_call/fulfills_stubbing/describes_unsatisfied_stubbing.rb +3 -1
  20. data/lib/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb +5 -1
  21. data/lib/mocktail/handles_dry_call/fulfills_stubbing.rb +2 -0
  22. data/lib/mocktail/handles_dry_call/logs_call.rb +2 -0
  23. data/lib/mocktail/handles_dry_call/validates_arguments.rb +6 -4
  24. data/lib/mocktail/handles_dry_call.rb +2 -0
  25. data/lib/mocktail/handles_dry_new_call.rb +2 -0
  26. data/lib/mocktail/imitates_type/ensures_imitation_support.rb +2 -0
  27. data/lib/mocktail/imitates_type/makes_double/declares_dry_class/reconstructs_call.rb +4 -1
  28. data/lib/mocktail/imitates_type/makes_double/declares_dry_class.rb +32 -20
  29. data/lib/mocktail/imitates_type/makes_double/gathers_fakeable_instance_methods.rb +2 -0
  30. data/lib/mocktail/imitates_type/makes_double.rb +3 -0
  31. data/lib/mocktail/imitates_type.rb +3 -1
  32. data/lib/mocktail/initialize_based_on_type_system_mode_switching.rb +9 -0
  33. data/lib/mocktail/initializes_mocktail.rb +5 -0
  34. data/lib/mocktail/matcher_presentation.rb +4 -2
  35. data/lib/mocktail/matchers/any.rb +4 -3
  36. data/lib/mocktail/matchers/base.rb +10 -2
  37. data/lib/mocktail/matchers/captor.rb +9 -0
  38. data/lib/mocktail/matchers/includes.rb +2 -0
  39. data/lib/mocktail/matchers/includes_hash.rb +9 -0
  40. data/lib/mocktail/matchers/includes_key.rb +9 -0
  41. data/lib/mocktail/matchers/includes_string.rb +9 -0
  42. data/lib/mocktail/matchers/is_a.rb +2 -0
  43. data/lib/mocktail/matchers/matches.rb +2 -0
  44. data/lib/mocktail/matchers/not.rb +2 -0
  45. data/lib/mocktail/matchers/numeric.rb +5 -4
  46. data/lib/mocktail/matchers/that.rb +2 -0
  47. data/lib/mocktail/matchers.rb +3 -0
  48. data/lib/mocktail/raises_neato_no_method_error.rb +2 -0
  49. data/lib/mocktail/records_demonstration.rb +2 -0
  50. data/lib/mocktail/registers_matcher.rb +8 -3
  51. data/lib/mocktail/registers_stubbing.rb +2 -0
  52. data/lib/mocktail/replaces_next.rb +7 -1
  53. data/lib/mocktail/replaces_type/redefines_new.rb +3 -1
  54. data/lib/mocktail/replaces_type/redefines_singleton_methods.rb +14 -2
  55. data/lib/mocktail/replaces_type/runs_sorbet_sig_blocks_before_replacement.rb +37 -0
  56. data/lib/mocktail/replaces_type.rb +6 -0
  57. data/lib/mocktail/resets_state.rb +2 -0
  58. data/lib/mocktail/share/bind.rb +7 -5
  59. data/lib/mocktail/share/cleans_backtrace.rb +3 -5
  60. data/lib/mocktail/share/creates_identifier.rb +16 -9
  61. data/lib/mocktail/share/determines_matching_calls.rb +4 -2
  62. data/lib/mocktail/share/stringifies_call.rb +6 -2
  63. data/lib/mocktail/share/stringifies_method_name.rb +3 -1
  64. data/lib/mocktail/simulates_argument_error/reconciles_args_with_params.rb +2 -0
  65. data/lib/mocktail/simulates_argument_error/recreates_message.rb +2 -0
  66. data/lib/mocktail/simulates_argument_error/transforms_params.rb +15 -8
  67. data/lib/mocktail/simulates_argument_error.rb +2 -0
  68. data/lib/mocktail/sorbet/mocktail/collects_calls.rb +18 -0
  69. data/lib/mocktail/sorbet/mocktail/debug.rb +54 -0
  70. data/lib/mocktail/sorbet/mocktail/dsl.rb +46 -0
  71. data/lib/mocktail/sorbet/mocktail/errors.rb +19 -0
  72. data/lib/mocktail/sorbet/mocktail/explains_nils.rb +41 -0
  73. data/lib/mocktail/sorbet/mocktail/explains_thing.rb +137 -0
  74. data/lib/mocktail/sorbet/mocktail/grabs_original_method_parameters.rb +33 -0
  75. data/lib/mocktail/sorbet/mocktail/handles_dry_call/fulfills_stubbing/describes_unsatisfied_stubbing.rb +27 -0
  76. data/lib/mocktail/sorbet/mocktail/handles_dry_call/fulfills_stubbing/finds_satisfaction.rb +24 -0
  77. data/lib/mocktail/sorbet/mocktail/handles_dry_call/fulfills_stubbing.rb +45 -0
  78. data/lib/mocktail/sorbet/mocktail/handles_dry_call/logs_call.rb +12 -0
  79. data/lib/mocktail/sorbet/mocktail/handles_dry_call/validates_arguments.rb +45 -0
  80. data/lib/mocktail/sorbet/mocktail/handles_dry_call.rb +25 -0
  81. data/lib/mocktail/sorbet/mocktail/handles_dry_new_call.rb +42 -0
  82. data/lib/mocktail/sorbet/mocktail/imitates_type/ensures_imitation_support.rb +16 -0
  83. data/lib/mocktail/sorbet/mocktail/imitates_type/makes_double/declares_dry_class/reconstructs_call.rb +73 -0
  84. data/lib/mocktail/sorbet/mocktail/imitates_type/makes_double/declares_dry_class.rb +136 -0
  85. data/lib/mocktail/sorbet/mocktail/imitates_type/makes_double/gathers_fakeable_instance_methods.rb +28 -0
  86. data/lib/mocktail/sorbet/mocktail/imitates_type/makes_double.rb +29 -0
  87. data/lib/mocktail/sorbet/mocktail/imitates_type.rb +29 -0
  88. data/lib/mocktail/sorbet/mocktail/initialize_based_on_type_system_mode_switching.rb +11 -0
  89. data/lib/mocktail/sorbet/mocktail/initializes_mocktail.rb +25 -0
  90. data/lib/mocktail/sorbet/mocktail/matcher_presentation.rb +21 -0
  91. data/lib/mocktail/sorbet/mocktail/matchers/any.rb +27 -0
  92. data/lib/mocktail/sorbet/mocktail/matchers/base.rb +39 -0
  93. data/lib/mocktail/sorbet/mocktail/matchers/captor.rb +76 -0
  94. data/lib/mocktail/sorbet/mocktail/matchers/includes.rb +32 -0
  95. data/lib/mocktail/sorbet/mocktail/matchers/includes_hash.rb +12 -0
  96. data/lib/mocktail/sorbet/mocktail/matchers/includes_key.rb +12 -0
  97. data/lib/mocktail/sorbet/mocktail/matchers/includes_string.rb +12 -0
  98. data/lib/mocktail/sorbet/mocktail/matchers/is_a.rb +17 -0
  99. data/lib/mocktail/sorbet/mocktail/matchers/matches.rb +19 -0
  100. data/lib/mocktail/sorbet/mocktail/matchers/not.rb +17 -0
  101. data/lib/mocktail/sorbet/mocktail/matchers/numeric.rb +27 -0
  102. data/lib/mocktail/sorbet/mocktail/matchers/that.rb +32 -0
  103. data/lib/mocktail/sorbet/mocktail/matchers.rb +19 -0
  104. data/lib/mocktail/sorbet/mocktail/raises_neato_no_method_error.rb +93 -0
  105. data/lib/mocktail/sorbet/mocktail/records_demonstration.rb +43 -0
  106. data/lib/mocktail/sorbet/mocktail/registers_matcher.rb +65 -0
  107. data/lib/mocktail/sorbet/mocktail/registers_stubbing.rb +31 -0
  108. data/lib/mocktail/sorbet/mocktail/replaces_next.rb +55 -0
  109. data/lib/mocktail/sorbet/mocktail/replaces_type/redefines_new.rb +32 -0
  110. data/lib/mocktail/sorbet/mocktail/replaces_type/redefines_singleton_methods.rb +80 -0
  111. data/lib/mocktail/sorbet/mocktail/replaces_type/runs_sorbet_sig_blocks_before_replacement.rb +39 -0
  112. data/lib/mocktail/sorbet/mocktail/replaces_type.rb +36 -0
  113. data/lib/mocktail/sorbet/mocktail/resets_state.rb +14 -0
  114. data/lib/mocktail/sorbet/mocktail/share/bind.rb +18 -0
  115. data/lib/mocktail/sorbet/mocktail/share/cleans_backtrace.rb +22 -0
  116. data/lib/mocktail/sorbet/mocktail/share/creates_identifier.rb +39 -0
  117. data/lib/mocktail/sorbet/mocktail/share/determines_matching_calls.rb +72 -0
  118. data/lib/mocktail/sorbet/mocktail/share/stringifies_call.rb +85 -0
  119. data/lib/mocktail/sorbet/mocktail/share/stringifies_method_name.rb +16 -0
  120. data/lib/mocktail/sorbet/mocktail/simulates_argument_error/reconciles_args_with_params.rb +27 -0
  121. data/lib/mocktail/sorbet/mocktail/simulates_argument_error/recreates_message.rb +34 -0
  122. data/lib/mocktail/sorbet/mocktail/simulates_argument_error/transforms_params.rb +58 -0
  123. data/lib/mocktail/sorbet/mocktail/simulates_argument_error.rb +36 -0
  124. data/lib/mocktail/sorbet/mocktail/sorbet.rb +3 -0
  125. data/lib/mocktail/sorbet/mocktail/stringifies_method_signature.rb +53 -0
  126. data/lib/mocktail/sorbet/mocktail/typed.rb +5 -0
  127. data/lib/mocktail/sorbet/mocktail/value/cabinet.rb +91 -0
  128. data/lib/mocktail/sorbet/mocktail/value/call.rb +51 -0
  129. data/lib/mocktail/sorbet/mocktail/value/demo_config.rb +10 -0
  130. data/lib/mocktail/sorbet/mocktail/value/double.rb +10 -0
  131. data/lib/mocktail/sorbet/mocktail/value/double_data.rb +15 -0
  132. data/lib/mocktail/sorbet/mocktail/value/explanation.rb +68 -0
  133. data/lib/mocktail/sorbet/mocktail/value/explanation_data.rb +19 -0
  134. data/lib/mocktail/sorbet/mocktail/value/fake_method_data.rb +11 -0
  135. data/lib/mocktail/sorbet/mocktail/value/matcher_registry.rb +27 -0
  136. data/lib/mocktail/sorbet/mocktail/value/no_explanation_data.rb +20 -0
  137. data/lib/mocktail/sorbet/mocktail/value/signature.rb +35 -0
  138. data/lib/mocktail/sorbet/mocktail/value/stubbing.rb +26 -0
  139. data/lib/mocktail/sorbet/mocktail/value/top_shelf.rb +79 -0
  140. data/lib/mocktail/sorbet/mocktail/value/type_replacement.rb +11 -0
  141. data/lib/mocktail/sorbet/mocktail/value/type_replacement_data.rb +19 -0
  142. data/lib/mocktail/sorbet/mocktail/value/unsatisfying_call.rb +9 -0
  143. data/lib/mocktail/sorbet/mocktail/value/unsatisfying_call_explanation.rb +24 -0
  144. data/lib/mocktail/sorbet/mocktail/value.rb +19 -0
  145. data/lib/mocktail/sorbet/mocktail/verifies_call/finds_verifiable_calls.rb +21 -0
  146. data/lib/mocktail/sorbet/mocktail/verifies_call/raises_verification_error/gathers_calls_of_method.rb +15 -0
  147. data/lib/mocktail/sorbet/mocktail/verifies_call/raises_verification_error.rb +74 -0
  148. data/lib/mocktail/sorbet/mocktail/verifies_call.rb +37 -0
  149. data/lib/mocktail/sorbet/mocktail/version.rb +12 -0
  150. data/lib/mocktail/sorbet/mocktail.rb +154 -0
  151. data/lib/mocktail/sorbet.rb +1 -0
  152. data/lib/mocktail/stringifies_method_signature.rb +2 -0
  153. data/lib/mocktail/typed.rb +3 -0
  154. data/lib/mocktail/value/cabinet.rb +8 -1
  155. data/lib/mocktail/value/call.rb +44 -12
  156. data/lib/mocktail/value/demo_config.rb +6 -7
  157. data/lib/mocktail/value/double.rb +6 -7
  158. data/lib/mocktail/value/double_data.rb +11 -7
  159. data/lib/mocktail/value/explanation.rb +28 -3
  160. data/lib/mocktail/value/explanation_data.rb +14 -0
  161. data/lib/mocktail/value/fake_method_data.rb +7 -6
  162. data/lib/mocktail/value/matcher_registry.rb +2 -0
  163. data/lib/mocktail/value/no_explanation_data.rb +16 -0
  164. data/lib/mocktail/value/signature.rb +19 -27
  165. data/lib/mocktail/value/stubbing.rb +11 -12
  166. data/lib/mocktail/value/top_shelf.rb +5 -0
  167. data/lib/mocktail/value/type_replacement.rb +7 -8
  168. data/lib/mocktail/value/type_replacement_data.rb +10 -7
  169. data/lib/mocktail/value/unsatisfying_call.rb +5 -6
  170. data/lib/mocktail/value/unsatisfying_call_explanation.rb +18 -0
  171. data/lib/mocktail/value.rb +5 -2
  172. data/lib/mocktail/verifies_call/finds_verifiable_calls.rb +2 -0
  173. data/lib/mocktail/verifies_call/raises_verification_error/gathers_calls_of_method.rb +2 -0
  174. data/lib/mocktail/verifies_call/raises_verification_error.rb +2 -0
  175. data/lib/mocktail/verifies_call.rb +3 -0
  176. data/lib/mocktail/version.rb +8 -1
  177. data/lib/mocktail.rb +46 -5
  178. data/mocktail.gemspec +8 -4
  179. data/rbi/mocktail-pregenerated.rbi +1865 -0
  180. data/rbi/mocktail.rbi +77 -0
  181. data/rbi/sorbet-runtime.rbi +29 -0
  182. data/spoom_report.html +1248 -0
  183. metadata +130 -3
data/spoom_report.html ADDED
@@ -0,0 +1,1248 @@
1
+ <!DOCTYPE html>
2
+ <html lang="en">
3
+ <head>
4
+ <meta charset="utf-8" />
5
+ <meta http-equiv="x-ua-compatible" content="ie=edge" />
6
+ <meta name="viewport" content="width=device-width, initial-scale=1" />
7
+
8
+ <title>mocktail</title>
9
+ <link rel="stylesheet" href="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/css/bootstrap.min.css">
10
+
11
+ <style>
12
+ .card {
13
+ margin: 30px 0 0 0;
14
+ }
15
+
16
+ .footer {
17
+ color: #6c757d;
18
+ text-align: center;
19
+ margin: 30px 0 0 0;
20
+ }
21
+
22
+ svg {
23
+ width: 100%;
24
+ height: 100%;
25
+ }
26
+
27
+ .tooltip {
28
+ font: 12px Arial, sans-serif;
29
+ color: #fff;
30
+ text-align: center;
31
+ background: rgba(0, 0, 0, 0.6);
32
+ padding: 5px;
33
+ border: 0px;
34
+ border-radius: 4px;
35
+ position: absolute;
36
+ top: 0;
37
+ left: 0;
38
+ opacity: 0;
39
+ }
40
+
41
+ .label {
42
+ font: 14px Arial, sans-serif;
43
+ font-weight: bold;
44
+ fill: #fff;
45
+ text-anchor: middle;
46
+ pointer-events: none;
47
+ }
48
+
49
+ .label .small {
50
+ font-size: 10px;
51
+ }
52
+
53
+ .pie .title {
54
+ font: 18px Arial, sans-serif;
55
+ font-weight: bold;
56
+ fill: #212529;
57
+ text-anchor: middle;
58
+ pointer-events: none;
59
+ }
60
+
61
+ .pie .arc {
62
+ stroke: #fff;
63
+ stroke-width: 2px;
64
+ }
65
+
66
+ .node {
67
+ cursor: pointer;
68
+ }
69
+
70
+ .node:hover {
71
+ stroke: #333;
72
+ stroke-width: 1px;
73
+ }
74
+
75
+ .label.dir {
76
+ fill: #333;
77
+ }
78
+
79
+ .label.file {
80
+ font: 12px Arial, sans-serif;
81
+ }
82
+
83
+ .node.root, .node.file {
84
+ pointer-events: none;
85
+ }
86
+
87
+ .domain {
88
+ stroke: transparent;
89
+ }
90
+
91
+ .grid line {
92
+ stroke: #ccc;
93
+ }
94
+
95
+ .axis text {
96
+ font: 12px Arial, sans-serif;
97
+ fill: #333;
98
+ text-anchor: right;
99
+ pointer-events: none;
100
+ }
101
+
102
+ .area {
103
+ fill-opacity: 0.5;
104
+ }
105
+
106
+ .line {
107
+ stroke-width: 2;
108
+ fill: transparent;
109
+ }
110
+
111
+ .dot {
112
+ r: 2;
113
+ fill: #888;
114
+ }
115
+
116
+ .inverted .grid line {
117
+ stroke: #777;
118
+ }
119
+
120
+ .inverted .area {
121
+ fill-opacity: 0.9;
122
+ }
123
+
124
+ .inverted .axis text {
125
+ fill: #fff;
126
+ }
127
+
128
+ .inverted .axis line {
129
+ stroke: #fff;
130
+ }
131
+
132
+ .inverted .dot {
133
+ fill: #fff;
134
+ }
135
+
136
+
137
+ </style>
138
+ </head>
139
+ <body>
140
+ <script src="https://code.jquery.com/jquery-3.5.1.slim.min.js"></script>
141
+ <script src="https://stackpath.bootstrapcdn.com/bootstrap/4.5.0/js/bootstrap.min.js"></script>
142
+ <script src="https://d3js.org/d3.v4.min.js"></script>
143
+
144
+ <script>
145
+ var parseDate = d3.timeParse("%s");
146
+
147
+ function strictnessColor(strictness) {
148
+ switch(strictness) {
149
+ case "ignore":
150
+ return "#999";
151
+ case "false":
152
+ return "#db4437";
153
+ case "true":
154
+ return "#0f9d58";
155
+ case "strict":
156
+ return "#0a7340";
157
+ case "strong":
158
+ return "#064828";
159
+ }
160
+ return "#db4437";
161
+ }
162
+
163
+ function toPercent(value, sum) {
164
+ return value ? Math.round(value * 100 / sum) : 0;
165
+ }
166
+
167
+ var tooltip = d3.select("body")
168
+ .append("div")
169
+ .append("div")
170
+ .attr("class", "tooltip");
171
+
172
+ function moveTooltip(d) {
173
+ return tooltip
174
+ .style("left", (d3.event.pageX + 20) + "px")
175
+ .style("top", (d3.event.pageY) + "px")
176
+ }
177
+
178
+ function tooltipPie(d, title, kind, sum) {
179
+ moveTooltip(d)
180
+ .html("<b>" + title + "</b><br><br>"
181
+ + "<b>" + d.data.value + "</b> " + kind + "<br>"
182
+ + "<b>" + toPercent(d.data.value, sum) + "</b>%")
183
+ }
184
+
185
+ function treeHeight(root, height = 0) {
186
+ height += 1;
187
+ if (root.children && root.children.length > 0)
188
+ return Math.max(...root.children.map(child => treeHeight(child, height)));
189
+ else
190
+ return height;
191
+ }
192
+
193
+ function tooltipMap(d) {
194
+ moveTooltip(d)
195
+ .html("<b>" + d.data.name + "</b>")
196
+ }
197
+
198
+ var parseVersion = function(version) {
199
+ if (!version) {
200
+ return null;
201
+ }
202
+ return parseFloat(version.replaceAll("0.", ""));
203
+ }
204
+
205
+ function tooltipTimeline(d, kind) {
206
+ moveTooltip(d)
207
+ .html("commit <b>" + d.data.commit + "</b><br>"
208
+ + d3.timeFormat("%y/%m/%d")(parseDate(d.data.timestamp)) + "<br><br>"
209
+ + "<b>typed: " + d.key + "</b><br><br>"
210
+ + "<b>" + (d.data.values[d.key] ? d.data.values[d.key] : 0) + "</b> " + kind +"<br>"
211
+ + "<b>" + toPercent(d.data.values[d.key] ? d.data.values[d.key] : 0, d.data.total) + "%")
212
+ }
213
+
214
+
215
+ </script>
216
+
217
+ <div class="px-5 py-4 container-fluid">
218
+ <div class="row justify-content-center">
219
+ <div class="col-xs-12 col-md-12 col-lg-9 col-xl-8">
220
+ <div class="header">
221
+ <h1 class="display-3">
222
+ mocktail
223
+ <span class="badge badge-pill badge-dark" style="font-size: 20%;">bef51ca</span>
224
+ </h1>
225
+
226
+ </div>
227
+ <div class="body">
228
+ <div class="card">
229
+
230
+ <h5 class="card-header">Snapshot</h5>
231
+
232
+ <div class="card-body">
233
+ <div class="container-fluid">
234
+ <div class="row justify-content-md-center">
235
+ <div class="col-12 col-sm-4 col-xl-3">
236
+ <svg id="pie_sigils"></svg>
237
+ <script>function tooltip_pie_sigils(d) {
238
+ tooltipPie(d, "typed: " + d.data.key, "files excluding RBIs", sum_pie_sigils);
239
+ }
240
+
241
+
242
+ var json_pie_sigils = {"false":1,"true":6,"strict":113};
243
+ var pie_pie_sigils = d3.pie().value((d) => d.value);
244
+ var data_pie_sigils = pie_pie_sigils(d3.entries(json_pie_sigils));
245
+ var sum_pie_sigils = d3.sum(data_pie_sigils, (d) => d.data.value);
246
+ var title_pie_sigils = "Sigils";
247
+
248
+ function draw_pie_sigils() {
249
+ var pieSize_pie_sigils = document.getElementById("pie_sigils").clientWidth - 10;
250
+
251
+ var arcGenerator_pie_sigils = d3.arc()
252
+ .innerRadius(pieSize_pie_sigils / 4)
253
+ .outerRadius(pieSize_pie_sigils / 2);
254
+
255
+ d3.select("#pie_sigils").selectAll("*").remove()
256
+
257
+ var svg_pie_sigils = d3.select("#pie_sigils")
258
+ .attr("width", pieSize_pie_sigils)
259
+ .attr("height", pieSize_pie_sigils)
260
+ .attr("class", "pie")
261
+ .append("g")
262
+ .attr("transform", "translate(" + pieSize_pie_sigils / 2 + "," + pieSize_pie_sigils / 2 + ")");
263
+
264
+ svg_pie_sigils.selectAll("arcs")
265
+ .data(data_pie_sigils)
266
+ .enter()
267
+ .append('path')
268
+ .attr("class", "arc")
269
+ .attr('fill', (d) => strictnessColor(d.data.key))
270
+ .attr('d', arcGenerator_pie_sigils)
271
+ .on("mouseover", (d) => tooltip.style("opacity", 1))
272
+ .on("mousemove", tooltip_pie_sigils)
273
+ .on("mouseleave", (d) => tooltip.style("opacity", 0));
274
+
275
+ svg_pie_sigils.selectAll("labels")
276
+ .data(data_pie_sigils)
277
+ .enter()
278
+ .append('text')
279
+ .attr("class", "label")
280
+ .attr("transform", (d) => "translate(" + arcGenerator_pie_sigils.centroid(d) + ")")
281
+ .filter(d => (d.endAngle - d.startAngle) > 0.25)
282
+ .append("tspan")
283
+ .attr("x", 0)
284
+ .attr("y", -3)
285
+ .text((d) => d.data.value)
286
+ .append("tspan")
287
+ .attr("class", "small")
288
+ .attr("x", 0)
289
+ .attr("y", 13)
290
+ .text((d) => toPercent(d.data.value, sum_pie_sigils) + "%");
291
+
292
+ svg_pie_sigils
293
+ .append("text")
294
+ .attr("class", "title")
295
+ .append("tspan")
296
+ .attr("y", 7)
297
+ .text(title_pie_sigils);
298
+ }
299
+
300
+ draw_pie_sigils();
301
+ window.addEventListener("resize", draw_pie_sigils);
302
+ </script>
303
+
304
+ </div>
305
+ <div class="d-none d-xl-block col-xl-1"></div>
306
+ <div class="col-12 col-sm-4 col-xl-3">
307
+ <svg id="pie_calls"></svg>
308
+ <script>function tooltip_pie_calls(d) {
309
+ tooltipPie(d, d.data.key == "true" ? " checked" : " unchecked", "calls", sum_pie_calls)
310
+ }
311
+
312
+
313
+ var json_pie_calls = {"true":5722,"false":1087};
314
+ var pie_pie_calls = d3.pie().value((d) => d.value);
315
+ var data_pie_calls = pie_pie_calls(d3.entries(json_pie_calls));
316
+ var sum_pie_calls = d3.sum(data_pie_calls, (d) => d.data.value);
317
+ var title_pie_calls = "Calls";
318
+
319
+ function draw_pie_calls() {
320
+ var pieSize_pie_calls = document.getElementById("pie_calls").clientWidth - 10;
321
+
322
+ var arcGenerator_pie_calls = d3.arc()
323
+ .innerRadius(pieSize_pie_calls / 4)
324
+ .outerRadius(pieSize_pie_calls / 2);
325
+
326
+ d3.select("#pie_calls").selectAll("*").remove()
327
+
328
+ var svg_pie_calls = d3.select("#pie_calls")
329
+ .attr("width", pieSize_pie_calls)
330
+ .attr("height", pieSize_pie_calls)
331
+ .attr("class", "pie")
332
+ .append("g")
333
+ .attr("transform", "translate(" + pieSize_pie_calls / 2 + "," + pieSize_pie_calls / 2 + ")");
334
+
335
+ svg_pie_calls.selectAll("arcs")
336
+ .data(data_pie_calls)
337
+ .enter()
338
+ .append('path')
339
+ .attr("class", "arc")
340
+ .attr('fill', (d) => strictnessColor(d.data.key))
341
+ .attr('d', arcGenerator_pie_calls)
342
+ .on("mouseover", (d) => tooltip.style("opacity", 1))
343
+ .on("mousemove", tooltip_pie_calls)
344
+ .on("mouseleave", (d) => tooltip.style("opacity", 0));
345
+
346
+ svg_pie_calls.selectAll("labels")
347
+ .data(data_pie_calls)
348
+ .enter()
349
+ .append('text')
350
+ .attr("class", "label")
351
+ .attr("transform", (d) => "translate(" + arcGenerator_pie_calls.centroid(d) + ")")
352
+ .filter(d => (d.endAngle - d.startAngle) > 0.25)
353
+ .append("tspan")
354
+ .attr("x", 0)
355
+ .attr("y", -3)
356
+ .text((d) => d.data.value)
357
+ .append("tspan")
358
+ .attr("class", "small")
359
+ .attr("x", 0)
360
+ .attr("y", 13)
361
+ .text((d) => toPercent(d.data.value, sum_pie_calls) + "%");
362
+
363
+ svg_pie_calls
364
+ .append("text")
365
+ .attr("class", "title")
366
+ .append("tspan")
367
+ .attr("y", 7)
368
+ .text(title_pie_calls);
369
+ }
370
+
371
+ draw_pie_calls();
372
+ window.addEventListener("resize", draw_pie_calls);
373
+ </script>
374
+
375
+ </div>
376
+ <div class="d-none d-xl-block col-xl-1"></div>
377
+ <div class="col-12 col-sm-4 col-xl-3">
378
+ <svg id="pie_sigs"></svg>
379
+ <script>function tooltip_pie_sigs(d) {
380
+ tooltipPie(
381
+ d,
382
+ (d.data.key == "true" ? " with" : " without") + " a signature", "methods excluding RBIs", sum_pie_sigs
383
+ )
384
+ }
385
+
386
+
387
+ var json_pie_sigs = {"true":905,"false":24};
388
+ var pie_pie_sigs = d3.pie().value((d) => d.value);
389
+ var data_pie_sigs = pie_pie_sigs(d3.entries(json_pie_sigs));
390
+ var sum_pie_sigs = d3.sum(data_pie_sigs, (d) => d.data.value);
391
+ var title_pie_sigs = "Sigs";
392
+
393
+ function draw_pie_sigs() {
394
+ var pieSize_pie_sigs = document.getElementById("pie_sigs").clientWidth - 10;
395
+
396
+ var arcGenerator_pie_sigs = d3.arc()
397
+ .innerRadius(pieSize_pie_sigs / 4)
398
+ .outerRadius(pieSize_pie_sigs / 2);
399
+
400
+ d3.select("#pie_sigs").selectAll("*").remove()
401
+
402
+ var svg_pie_sigs = d3.select("#pie_sigs")
403
+ .attr("width", pieSize_pie_sigs)
404
+ .attr("height", pieSize_pie_sigs)
405
+ .attr("class", "pie")
406
+ .append("g")
407
+ .attr("transform", "translate(" + pieSize_pie_sigs / 2 + "," + pieSize_pie_sigs / 2 + ")");
408
+
409
+ svg_pie_sigs.selectAll("arcs")
410
+ .data(data_pie_sigs)
411
+ .enter()
412
+ .append('path')
413
+ .attr("class", "arc")
414
+ .attr('fill', (d) => strictnessColor(d.data.key))
415
+ .attr('d', arcGenerator_pie_sigs)
416
+ .on("mouseover", (d) => tooltip.style("opacity", 1))
417
+ .on("mousemove", tooltip_pie_sigs)
418
+ .on("mouseleave", (d) => tooltip.style("opacity", 0));
419
+
420
+ svg_pie_sigs.selectAll("labels")
421
+ .data(data_pie_sigs)
422
+ .enter()
423
+ .append('text')
424
+ .attr("class", "label")
425
+ .attr("transform", (d) => "translate(" + arcGenerator_pie_sigs.centroid(d) + ")")
426
+ .filter(d => (d.endAngle - d.startAngle) > 0.25)
427
+ .append("tspan")
428
+ .attr("x", 0)
429
+ .attr("y", -3)
430
+ .text((d) => d.data.value)
431
+ .append("tspan")
432
+ .attr("class", "small")
433
+ .attr("x", 0)
434
+ .attr("y", 13)
435
+ .text((d) => toPercent(d.data.value, sum_pie_sigs) + "%");
436
+
437
+ svg_pie_sigs
438
+ .append("text")
439
+ .attr("class", "title")
440
+ .append("tspan")
441
+ .attr("y", 7)
442
+ .text(title_pie_sigs);
443
+ }
444
+
445
+ draw_pie_sigs();
446
+ window.addEventListener("resize", draw_pie_sigs);
447
+ </script>
448
+
449
+ </div>
450
+ </div>
451
+ </div>
452
+ </div>
453
+ </div>
454
+
455
+ <div class="card">
456
+
457
+ <h5 class="card-header">Strictness Map</h5>
458
+
459
+ <div class="card-body">
460
+ <svg id="map_sigils"></svg>
461
+ <script>var root = {children: [{"name":"sorbet","children":[{"name":"tapioca","children":[{"name":"require.rb","strictness":"true"}],"score":1.0}],"score":1.0},{"name":"src","children":[{"name":"mocktail.rb","strictness":"strict"},{"name":"mocktail","children":[{"name":"collects_calls.rb","strictness":"strict"},{"name":"debug.rb","strictness":"strict"},{"name":"dsl.rb","strictness":"strict"},{"name":"errors.rb","strictness":"strict"},{"name":"explains_nils.rb","strictness":"strict"},{"name":"explains_thing.rb","strictness":"strict"},{"name":"grabs_original_method_parameters.rb","strictness":"strict"},{"name":"handles_dry_call.rb","strictness":"strict"},{"name":"handles_dry_call","children":[{"name":"fulfills_stubbing.rb","strictness":"strict"},{"name":"fulfills_stubbing","children":[{"name":"describes_unsatisfied_stubbing.rb","strictness":"strict"},{"name":"finds_satisfaction.rb","strictness":"strict"}],"score":1.0},{"name":"logs_call.rb","strictness":"strict"},{"name":"validates_arguments.rb","strictness":"strict"}],"score":1.0},{"name":"handles_dry_new_call.rb","strictness":"strict"},{"name":"imitates_type.rb","strictness":"strict"},{"name":"imitates_type","children":[{"name":"ensures_imitation_support.rb","strictness":"strict"},{"name":"makes_double.rb","strictness":"strict"},{"name":"makes_double","children":[{"name":"declares_dry_class.rb","strictness":"strict"},{"name":"declares_dry_class","children":[{"name":"reconstructs_call.rb","strictness":"strict"}],"score":1.0},{"name":"gathers_fakeable_instance_methods.rb","strictness":"strict"}],"score":1.0}],"score":1.0},{"name":"initialize_based_on_type_system_mode_switching.rb","strictness":"false"},{"name":"initializes_mocktail.rb","strictness":"strict"},{"name":"matcher_presentation.rb","strictness":"strict"},{"name":"matchers.rb","strictness":"strict"},{"name":"matchers","children":[{"name":"any.rb","strictness":"strict"},{"name":"base.rb","strictness":"strict"},{"name":"captor.rb","strictness":"strict"},{"name":"includes.rb","strictness":"strict"},{"name":"includes_hash.rb","strictness":"strict"},{"name":"includes_key.rb","strictness":"strict"},{"name":"includes_string.rb","strictness":"strict"},{"name":"is_a.rb","strictness":"strict"},{"name":"matches.rb","strictness":"strict"},{"name":"not.rb","strictness":"strict"},{"name":"numeric.rb","strictness":"strict"},{"name":"that.rb","strictness":"strict"}],"score":1.0},{"name":"raises_neato_no_method_error.rb","strictness":"strict"},{"name":"records_demonstration.rb","strictness":"strict"},{"name":"registers_matcher.rb","strictness":"strict"},{"name":"registers_stubbing.rb","strictness":"strict"},{"name":"replaces_next.rb","strictness":"strict"},{"name":"replaces_type.rb","strictness":"strict"},{"name":"replaces_type","children":[{"name":"redefines_new.rb","strictness":"strict"},{"name":"redefines_singleton_methods.rb","strictness":"strict"},{"name":"runs_sorbet_sig_blocks_before_replacement.rb","strictness":"strict"}],"score":1.0},{"name":"resets_state.rb","strictness":"strict"},{"name":"share","children":[{"name":"bind.rb","strictness":"true"},{"name":"cleans_backtrace.rb","strictness":"strict"},{"name":"creates_identifier.rb","strictness":"strict"},{"name":"determines_matching_calls.rb","strictness":"strict"},{"name":"stringifies_call.rb","strictness":"strict"},{"name":"stringifies_method_name.rb","strictness":"strict"}],"score":1.0},{"name":"simulates_argument_error.rb","strictness":"strict"},{"name":"simulates_argument_error","children":[{"name":"reconciles_args_with_params.rb","strictness":"strict"},{"name":"recreates_message.rb","strictness":"strict"},{"name":"transforms_params.rb","strictness":"strict"}],"score":1.0},{"name":"sorbet.rb","strictness":"strict"},{"name":"stringifies_method_signature.rb","strictness":"strict"},{"name":"typed.rb","strictness":"strict"},{"name":"value.rb","strictness":"strict"},{"name":"value","children":[{"name":"cabinet.rb","strictness":"strict"},{"name":"call.rb","strictness":"strict"},{"name":"demo_config.rb","strictness":"strict"},{"name":"double.rb","strictness":"strict"},{"name":"double_data.rb","strictness":"strict"},{"name":"explanation.rb","strictness":"strict"},{"name":"explanation_data.rb","strictness":"strict"},{"name":"fake_method_data.rb","strictness":"strict"},{"name":"matcher_registry.rb","strictness":"strict"},{"name":"no_explanation_data.rb","strictness":"strict"},{"name":"signature.rb","strictness":"strict"},{"name":"stubbing.rb","strictness":"strict"},{"name":"top_shelf.rb","strictness":"strict"},{"name":"type_replacement.rb","strictness":"strict"},{"name":"type_replacement_data.rb","strictness":"strict"},{"name":"unsatisfying_call.rb","strictness":"strict"},{"name":"unsatisfying_call_explanation.rb","strictness":"strict"}],"score":1.0},{"name":"verifies_call.rb","strictness":"strict"},{"name":"verifies_call","children":[{"name":"finds_verifiable_calls.rb","strictness":"strict"},{"name":"raises_verification_error.rb","strictness":"strict"},{"name":"raises_verification_error","children":[{"name":"gathers_calls_of_method.rb","strictness":"strict"}],"score":1.0}],"score":1.0},{"name":"version.rb","strictness":"strict"}],"score":0.9722222222222222}],"score":0.9861111111111112}]}
462
+ var dataHeight = treeHeight(root)
463
+
464
+ var opacity = d3.scaleLinear()
465
+ .domain([0, dataHeight])
466
+ .range([0, 0.2])
467
+
468
+ root = d3.hierarchy(root)
469
+ .sum((d) => d.children ? d.children.length : 1)
470
+ .sort((a, b) => b.value - a.value);
471
+
472
+ var dirColor = d3.scaleLinear()
473
+ .domain([1, 0])
474
+ .range([strictnessColor("true"), strictnessColor("false")])
475
+ .interpolate(d3.interpolateRgb);
476
+
477
+ function redraw() {
478
+ var diameter = document.getElementById("map_sigils").clientWidth - 20;
479
+ d3.select("#map_sigils").selectAll("*").remove()
480
+
481
+ var svg_map_sigils = d3.select("#map_sigils")
482
+ .attr("width", diameter)
483
+ .attr("height", diameter)
484
+ .append("g")
485
+ .attr("transform", "translate(" + diameter / 2 + "," + diameter / 2 + ")");
486
+
487
+ var pack = d3.pack()
488
+ .size([diameter, diameter])
489
+ .padding(2);
490
+
491
+ var focus = root,
492
+ nodes = pack(root).descendants(),
493
+ view;
494
+
495
+ var circle = svg_map_sigils.selectAll("circle")
496
+ .data(nodes)
497
+ .enter().append("circle")
498
+ .attr("class", (d) => d.parent ? d.children ? "node" : "node file" : "node root")
499
+ .attr("fill", (d) => d.children ? dirColor(d.data.score) : strictnessColor(d.data.strictness))
500
+ .attr("fill-opacity", (d) => d.children ? opacity(d.depth) : 1)
501
+ .on("click", function(d) { if (focus !== d) zoom(d), d3.event.stopPropagation(); })
502
+ .on("mouseover", (d) => tooltip.style("opacity", 1))
503
+ .on("mousemove", tooltipMap)
504
+ .on("mouseleave", (d) => tooltip.style("opacity", 0));
505
+
506
+ var text = svg_map_sigils.selectAll("text")
507
+ .data(nodes)
508
+ .enter().append("text")
509
+ .attr("class", (d) => d.children ? "label dir" : "label file")
510
+ .attr("fill-opacity", (d) => d.depth <= 1 ? 1 : 0)
511
+ .attr("display", (d) => d.depth <= 1 ? "inline" : "none")
512
+ .text((d) => d.data.name);
513
+
514
+ var node = svg_map_sigils.selectAll("circle,text");
515
+
516
+ function zoom(d) {
517
+ var focus0 = focus; focus = d;
518
+
519
+ var transition = d3.transition()
520
+ .duration(d3.event.altKey ? 7500 : 750)
521
+ .tween("zoom", function(d) {
522
+ var i = d3.interpolateZoom(view, [focus.x, focus.y, focus.r * 2]);
523
+ return (t) => zoomTo(i(t));
524
+ });
525
+
526
+ transition.selectAll("text")
527
+ .filter(function(d) { return d && d.parent === focus || this.style.display === "inline"; })
528
+ .attr("fill-opacity", function(d) { return d.parent === focus ? 1 : 0; })
529
+ .on("start", function(d) { if (d.parent === focus) this.style.display = "inline"; })
530
+ .on("end", function(d) { if (d.parent !== focus) this.style.display = "none"; });
531
+ }
532
+
533
+ function zoomTo(v) {
534
+ var k = diameter / v[2]; view = v;
535
+ node.attr("transform", (d) => "translate(" + (d.x - v[0]) * k + "," + (d.y - v[1]) * k + ")");
536
+ circle.attr("r", (d) => d.r * k);
537
+ }
538
+
539
+ zoomTo([root.x, root.y, root.r * 2]);
540
+ d3.select("#map_sigils").on("click", () => zoom(root));
541
+ }
542
+
543
+ redraw();
544
+ window.addEventListener("resize", redraw);
545
+ </script>
546
+
547
+ </div>
548
+ </div>
549
+
550
+ <div class="card">
551
+
552
+ <h5 class="card-header">Sigils Timeline</h5>
553
+
554
+ <div class="card-body">
555
+ <svg id="timeline_sigils"></svg>
556
+ <script>function tooltip_timeline_sigils(d) {
557
+ tooltipTimeline(d, "files excluding RBIs");
558
+ }
559
+
560
+
561
+ var data_timeline_sigils = [{"timestamp":1684959835,"commit":"93f8153","total":103,"values":{"true":103}},{"timestamp":1687348946,"commit":"5d093b9","total":113,"values":{"false":64,"true":38,"strict":13}},{"timestamp":1687349568,"commit":"24b1c92","total":113,"values":{"false":57,"true":45,"strict":13}},{"timestamp":1687351457,"commit":"97f4c09","total":113,"values":{"false":39,"true":63,"strict":13}},{"timestamp":1687351457,"commit":"74c83c2","total":113,"values":{"false":52,"true":50,"strict":13}},{"timestamp":1687351517,"commit":"4b1edef","total":113,"values":{"false":37,"true":65,"strict":13}},{"timestamp":1687351538,"commit":"f72b67c","total":113,"values":{"false":32,"true":70,"strict":13}},{"timestamp":1687351561,"commit":"305ec0b","total":113,"values":{"false":28,"true":74,"strict":13}},{"timestamp":1687351600,"commit":"6891312","total":113,"values":{"false":24,"true":78,"strict":13}},{"timestamp":1687351618,"commit":"4de157f","total":113,"values":{"false":20,"true":82,"strict":13}},{"timestamp":1687351639,"commit":"f5a1e40","total":113,"values":{"false":8,"true":94,"strict":13}},{"timestamp":1687351658,"commit":"6b0fef4","total":113,"values":{"false":1,"true":101,"strict":13}},{"timestamp":1687353030,"commit":"30e9528","total":113,"values":{"false":1,"true":101,"strict":13}},{"timestamp":1687355717,"commit":"814e515","total":113,"values":{"false":1,"true":96,"strict":18}},{"timestamp":1687357731,"commit":"5db3b43","total":113,"values":{"false":1,"true":95,"strict":19}},{"timestamp":1687361189,"commit":"1d0ba5b","total":113,"values":{"false":1,"true":95,"strict":19}},{"timestamp":1687361189,"commit":"2129b3d","total":113,"values":{"false":1,"true":94,"strict":20}},{"timestamp":1687365976,"commit":"167434b","total":113,"values":{"false":1,"true":93,"strict":21}},{"timestamp":1687366226,"commit":"dbb595a","total":113,"values":{"false":1,"true":92,"strict":22}},{"timestamp":1687366591,"commit":"526e7db","total":113,"values":{"false":1,"true":78,"strict":36}},{"timestamp":1687368803,"commit":"79054db","total":113,"values":{"false":1,"true":75,"strict":39}},{"timestamp":1687369230,"commit":"95242fe","total":113,"values":{"false":1,"true":72,"strict":42}},{"timestamp":1687370982,"commit":"f6d6431","total":113,"values":{"false":1,"true":67,"strict":47}},{"timestamp":1687378443,"commit":"2c46aee","total":113,"values":{"false":1,"true":63,"strict":51}},{"timestamp":1687378443,"commit":"fc2f231","total":113,"values":{"false":1,"true":66,"strict":48}},{"timestamp":1687382464,"commit":"a13d150","total":113,"values":{"false":1,"true":60,"strict":54}},{"timestamp":1687383706,"commit":"e8fab92","total":113,"values":{"false":1,"true":56,"strict":58}},{"timestamp":1687393452,"commit":"05f0c49","total":113,"values":{"false":1,"true":54,"strict":60}},{"timestamp":1687395190,"commit":"6b83d12","total":113,"values":{"false":1,"true":50,"strict":64}},{"timestamp":1687397513,"commit":"b705a9d","total":113,"values":{"false":1,"true":47,"strict":67}},{"timestamp":1687398430,"commit":"8bd4b6e","total":113,"values":{"false":1,"true":45,"strict":69}},{"timestamp":1687400347,"commit":"f166c87","total":113,"values":{"false":1,"true":43,"strict":71}},{"timestamp":1687439603,"commit":"5fe2a65","total":113,"values":{"false":1,"true":37,"strict":77}},{"timestamp":1687451837,"commit":"4638cd5","total":113,"values":{"false":1,"true":35,"strict":79}},{"timestamp":1687460258,"commit":"7644ff4","total":113,"values":{"false":1,"true":35,"strict":79}},{"timestamp":1687465345,"commit":"ba19195","total":113,"values":{"false":1,"true":35,"strict":79}},{"timestamp":1687473251,"commit":"a17f215","total":113,"values":{"false":1,"true":34,"strict":80}},{"timestamp":1687483861,"commit":"1657012","total":113,"values":{"false":1,"true":32,"strict":82}},{"timestamp":1687484487,"commit":"47c7dad","total":113,"values":{"false":1,"true":25,"strict":89}},{"timestamp":1687486065,"commit":"1ffa724","total":113,"values":{"false":1,"true":24,"strict":90}},{"timestamp":1687568962,"commit":"f57992d","total":114,"values":{"true":8,"strict":108}},{"timestamp":1687569798,"commit":"88c3b60","total":114,"values":{"true":5,"strict":111}},{"timestamp":1687969999,"commit":"bef51ca","total":117,"values":{"false":1,"true":6,"strict":113}}];
562
+ var keys_timeline_sigils = ["ignore","false","true","strict","strong","stdlib"];
563
+
564
+ var stack_timeline_sigils = d3.stack()
565
+ .keys(keys_timeline_sigils)
566
+ .value((d, key) => toPercent(d.values[key], d.total));
567
+
568
+ var layers_timeline_sigils = stack_timeline_sigils(data_timeline_sigils);
569
+
570
+ var points_timeline_sigils = []
571
+ layers_timeline_sigils.forEach(function(d) {
572
+ d.forEach(function(p) {
573
+ p.key = d.key
574
+ points_timeline_sigils.push(p);
575
+ });
576
+ })
577
+
578
+ function draw_timeline_sigils() {
579
+ var width_timeline_sigils = document.getElementById("timeline_sigils").clientWidth;
580
+ var height_timeline_sigils = 200;
581
+
582
+ d3.select("#timeline_sigils").selectAll("*").remove()
583
+
584
+ var svg_timeline_sigils = d3.select("#timeline_sigils")
585
+ .attr("class", "inverted")
586
+ .attr("width", width_timeline_sigils)
587
+ .attr("height", height_timeline_sigils);
588
+
589
+ var xScale_timeline_sigils = d3.scaleTime()
590
+ .range([0, width_timeline_sigils])
591
+ .domain(d3.extent(data_timeline_sigils, (d) => parseDate(d.timestamp)));
592
+
593
+ svg_timeline_sigils.append("g")
594
+ .attr("class", "grid")
595
+ .attr("transform", "translate(0," + height_timeline_sigils + ")")
596
+ .call(d3.axisBottom(xScale_timeline_sigils)
597
+ .tickFormat("")
598
+ .tickSize(-height_timeline_sigils))
599
+
600
+ var yScale_timeline_sigils = d3.scaleLinear()
601
+ .range([height_timeline_sigils, 0])
602
+ .domain([0, 100]);
603
+
604
+ svg_timeline_sigils.append("g")
605
+ .attr("class", "grid")
606
+ .call(d3.axisLeft(yScale_timeline_sigils)
607
+ .tickValues([0, 25, 50, 75, 100])
608
+ .tickFormat("")
609
+ .tickSize(-width_timeline_sigils))
610
+
611
+ var area_timeline_sigils = d3.area()
612
+ .x((d) => xScale_timeline_sigils(parseDate(d.data.timestamp)))
613
+ .y0((d) => yScale_timeline_sigils(d[0]))
614
+ .y1((d) => yScale_timeline_sigils(d[1]))
615
+ .curve(d3.curveCatmullRom.alpha(1));
616
+
617
+ var layer = svg_timeline_sigils.selectAll(".layer")
618
+ .data(layers_timeline_sigils)
619
+ .enter().append("g")
620
+ .attr("class", "layer")
621
+ .attr("fill", (d, i) => strictnessColor(d.key))
622
+
623
+ layer.append("path")
624
+ .attr("class", "area")
625
+ .attr("d", area_timeline_sigils)
626
+ .attr("fill", (d) => strictnessColor(d.key))
627
+
628
+ svg_timeline_sigils.selectAll("circle")
629
+ .data(points_timeline_sigils)
630
+ .enter()
631
+ .append("circle")
632
+ .attr("class", "dot")
633
+ .attr("cx", (d) => xScale_timeline_sigils(parseDate(d.data.timestamp)))
634
+ .attr("cy", (d, i) => yScale_timeline_sigils(d[1]))
635
+ .on("mouseover", (d) => tooltip.style("opacity", 1))
636
+ .on("mousemove", tooltip_timeline_sigils)
637
+ .on("mouseleave", (d) => tooltip.style("opacity", 0));
638
+
639
+ svg_timeline_sigils.append("g")
640
+ .attr("class", "axis x")
641
+ .attr("transform", "translate(0," + height_timeline_sigils + ")")
642
+ .call(d3.axisBottom(xScale_timeline_sigils)
643
+ .tickFormat(d3.timeFormat("%y/%m/%d"))
644
+ .tickPadding(-15)
645
+ .tickSize(-3));
646
+
647
+ svg_timeline_sigils.append("g")
648
+ .attr("class", "axis y")
649
+ .call(d3.axisLeft(yScale_timeline_sigils)
650
+ .tickValues([25, 50, 75])
651
+ .tickSize(-3)
652
+ .tickFormat((d) => d + '%')
653
+ .tickPadding(-30))
654
+
655
+
656
+ }
657
+
658
+ draw_timeline_sigils();
659
+ window.addEventListener("resize", draw_timeline_sigils);
660
+ </script>
661
+
662
+ </div>
663
+ </div>
664
+
665
+ <div class="card">
666
+
667
+ <h5 class="card-header">Calls Timeline</h5>
668
+
669
+ <div class="card-body">
670
+ <svg id="timeline_calls"></svg>
671
+ <script>function tooltip_timeline_calls(d) {
672
+ tooltipTimeline(d, "calls");
673
+ }
674
+
675
+
676
+ var data_timeline_calls = [{"timestamp":1684959835,"commit":"93f8153","total":4082,"values":{"true":1884,"false":2198}},{"timestamp":1687348946,"commit":"5d093b9","total":3389,"values":{"true":2214,"false":1175}},{"timestamp":1687349568,"commit":"24b1c92","total":3496,"values":{"true":2265,"false":1231}},{"timestamp":1687351457,"commit":"97f4c09","total":3675,"values":{"true":2375,"false":1300}},{"timestamp":1687351457,"commit":"74c83c2","total":3582,"values":{"true":2305,"false":1277}},{"timestamp":1687351517,"commit":"4b1edef","total":3737,"values":{"true":2399,"false":1338}},{"timestamp":1687351538,"commit":"f72b67c","total":3894,"values":{"true":2456,"false":1438}},{"timestamp":1687351561,"commit":"305ec0b","total":4055,"values":{"true":2525,"false":1530}},{"timestamp":1687351600,"commit":"6891312","total":4208,"values":{"true":2600,"false":1608}},{"timestamp":1687351618,"commit":"4de157f","total":4298,"values":{"true":2640,"false":1658}},{"timestamp":1687351639,"commit":"f5a1e40","total":4592,"values":{"true":2789,"false":1803}},{"timestamp":1687351658,"commit":"6b0fef4","total":4789,"values":{"true":2918,"false":1871}},{"timestamp":1687353030,"commit":"30e9528","total":4844,"values":{"true":2984,"false":1860}},{"timestamp":1687355717,"commit":"814e515","total":4848,"values":{"true":2990,"false":1858}},{"timestamp":1687357731,"commit":"5db3b43","total":4887,"values":{"true":3044,"false":1843}},{"timestamp":1687361189,"commit":"1d0ba5b","total":4932,"values":{"true":3150,"false":1782}},{"timestamp":1687361189,"commit":"2129b3d","total":5014,"values":{"true":3272,"false":1742}},{"timestamp":1687365976,"commit":"167434b","total":5048,"values":{"true":3328,"false":1720}},{"timestamp":1687366226,"commit":"dbb595a","total":5065,"values":{"true":3353,"false":1712}},{"timestamp":1687366591,"commit":"526e7db","total":5223,"values":{"true":3567,"false":1656}},{"timestamp":1687368803,"commit":"79054db","total":5255,"values":{"true":3618,"false":1637}},{"timestamp":1687369230,"commit":"95242fe","total":5275,"values":{"true":3689,"false":1586}},{"timestamp":1687370982,"commit":"f6d6431","total":5346,"values":{"true":3868,"false":1478}},{"timestamp":1687378443,"commit":"2c46aee","total":5432,"values":{"true":3989,"false":1443}},{"timestamp":1687378443,"commit":"fc2f231","total":5375,"values":{"true":3911,"false":1464}},{"timestamp":1687382464,"commit":"a13d150","total":5464,"values":{"true":4053,"false":1411}},{"timestamp":1687383706,"commit":"e8fab92","total":5477,"values":{"true":4069,"false":1408}},{"timestamp":1687393452,"commit":"05f0c49","total":5509,"values":{"true":4174,"false":1335}},{"timestamp":1687395190,"commit":"6b83d12","total":5546,"values":{"true":4227,"false":1319}},{"timestamp":1687397513,"commit":"b705a9d","total":5597,"values":{"true":4310,"false":1287}},{"timestamp":1687398430,"commit":"8bd4b6e","total":5636,"values":{"true":4368,"false":1268}},{"timestamp":1687400347,"commit":"f166c87","total":5691,"values":{"true":4416,"false":1275}},{"timestamp":1687439603,"commit":"5fe2a65","total":5750,"values":{"true":4530,"false":1220}},{"timestamp":1687451837,"commit":"4638cd5","total":5758,"values":{"true":4626,"false":1132}},{"timestamp":1687460258,"commit":"7644ff4","total":5758,"values":{"true":4626,"false":1132}},{"timestamp":1687465345,"commit":"ba19195","total":5763,"values":{"true":4620,"false":1143}},{"timestamp":1687473251,"commit":"a17f215","total":5822,"values":{"true":4676,"false":1146}},{"timestamp":1687483861,"commit":"1657012","total":5866,"values":{"true":4724,"false":1142}},{"timestamp":1687484487,"commit":"47c7dad","total":6203,"values":{"true":5062,"false":1141}},{"timestamp":1687486065,"commit":"1ffa724","total":6262,"values":{"true":5117,"false":1145}},{"timestamp":1687568962,"commit":"f57992d","total":6736,"values":{"true":5624,"false":1112}},{"timestamp":1687569798,"commit":"88c3b60","total":6784,"values":{"true":5706,"false":1078}},{"timestamp":1687969999,"commit":"bef51ca","total":6809,"values":{"true":5722,"false":1087}}];
677
+ var keys_timeline_calls = ["false","true"];
678
+
679
+ var stack_timeline_calls = d3.stack()
680
+ .keys(keys_timeline_calls)
681
+ .value((d, key) => toPercent(d.values[key], d.total));
682
+
683
+ var layers_timeline_calls = stack_timeline_calls(data_timeline_calls);
684
+
685
+ var points_timeline_calls = []
686
+ layers_timeline_calls.forEach(function(d) {
687
+ d.forEach(function(p) {
688
+ p.key = d.key
689
+ points_timeline_calls.push(p);
690
+ });
691
+ })
692
+
693
+ function draw_timeline_calls() {
694
+ var width_timeline_calls = document.getElementById("timeline_calls").clientWidth;
695
+ var height_timeline_calls = 200;
696
+
697
+ d3.select("#timeline_calls").selectAll("*").remove()
698
+
699
+ var svg_timeline_calls = d3.select("#timeline_calls")
700
+ .attr("class", "inverted")
701
+ .attr("width", width_timeline_calls)
702
+ .attr("height", height_timeline_calls);
703
+
704
+ var xScale_timeline_calls = d3.scaleTime()
705
+ .range([0, width_timeline_calls])
706
+ .domain(d3.extent(data_timeline_calls, (d) => parseDate(d.timestamp)));
707
+
708
+ svg_timeline_calls.append("g")
709
+ .attr("class", "grid")
710
+ .attr("transform", "translate(0," + height_timeline_calls + ")")
711
+ .call(d3.axisBottom(xScale_timeline_calls)
712
+ .tickFormat("")
713
+ .tickSize(-height_timeline_calls))
714
+
715
+ var yScale_timeline_calls = d3.scaleLinear()
716
+ .range([height_timeline_calls, 0])
717
+ .domain([0, 100]);
718
+
719
+ svg_timeline_calls.append("g")
720
+ .attr("class", "grid")
721
+ .call(d3.axisLeft(yScale_timeline_calls)
722
+ .tickValues([0, 25, 50, 75, 100])
723
+ .tickFormat("")
724
+ .tickSize(-width_timeline_calls))
725
+
726
+ var area_timeline_calls = d3.area()
727
+ .x((d) => xScale_timeline_calls(parseDate(d.data.timestamp)))
728
+ .y0((d) => yScale_timeline_calls(d[0]))
729
+ .y1((d) => yScale_timeline_calls(d[1]))
730
+ .curve(d3.curveCatmullRom.alpha(1));
731
+
732
+ var layer = svg_timeline_calls.selectAll(".layer")
733
+ .data(layers_timeline_calls)
734
+ .enter().append("g")
735
+ .attr("class", "layer")
736
+ .attr("fill", (d, i) => strictnessColor(d.key))
737
+
738
+ layer.append("path")
739
+ .attr("class", "area")
740
+ .attr("d", area_timeline_calls)
741
+ .attr("fill", (d) => strictnessColor(d.key))
742
+
743
+ svg_timeline_calls.selectAll("circle")
744
+ .data(points_timeline_calls)
745
+ .enter()
746
+ .append("circle")
747
+ .attr("class", "dot")
748
+ .attr("cx", (d) => xScale_timeline_calls(parseDate(d.data.timestamp)))
749
+ .attr("cy", (d, i) => yScale_timeline_calls(d[1]))
750
+ .on("mouseover", (d) => tooltip.style("opacity", 1))
751
+ .on("mousemove", tooltip_timeline_calls)
752
+ .on("mouseleave", (d) => tooltip.style("opacity", 0));
753
+
754
+ svg_timeline_calls.append("g")
755
+ .attr("class", "axis x")
756
+ .attr("transform", "translate(0," + height_timeline_calls + ")")
757
+ .call(d3.axisBottom(xScale_timeline_calls)
758
+ .tickFormat(d3.timeFormat("%y/%m/%d"))
759
+ .tickPadding(-15)
760
+ .tickSize(-3));
761
+
762
+ svg_timeline_calls.append("g")
763
+ .attr("class", "axis y")
764
+ .call(d3.axisLeft(yScale_timeline_calls)
765
+ .tickValues([25, 50, 75])
766
+ .tickSize(-3)
767
+ .tickFormat((d) => d + '%')
768
+ .tickPadding(-30))
769
+
770
+
771
+ }
772
+
773
+ draw_timeline_calls();
774
+ window.addEventListener("resize", draw_timeline_calls);
775
+ </script>
776
+
777
+ </div>
778
+ </div>
779
+
780
+ <div class="card">
781
+
782
+ <h5 class="card-header">Signatures Timeline</h5>
783
+
784
+ <div class="card-body">
785
+ <svg id="timeline_sigs"></svg>
786
+ <script>function tooltip_timeline_sigs(d) {
787
+ tooltipTimeline(d, "methods excluding RBIs");
788
+ }
789
+
790
+
791
+ var data_timeline_sigs = [{"timestamp":1684959835,"commit":"93f8153","total":816,"values":{"true":9,"false":807}},{"timestamp":1687348946,"commit":"5d093b9","total":872,"values":{"true":118,"false":754}},{"timestamp":1687349568,"commit":"24b1c92","total":872,"values":{"true":118,"false":754}},{"timestamp":1687351457,"commit":"97f4c09","total":872,"values":{"true":118,"false":754}},{"timestamp":1687351457,"commit":"74c83c2","total":872,"values":{"true":118,"false":754}},{"timestamp":1687351517,"commit":"4b1edef","total":872,"values":{"true":118,"false":754}},{"timestamp":1687351538,"commit":"f72b67c","total":872,"values":{"true":118,"false":754}},{"timestamp":1687351561,"commit":"305ec0b","total":872,"values":{"true":118,"false":754}},{"timestamp":1687351600,"commit":"6891312","total":872,"values":{"true":118,"false":754}},{"timestamp":1687351618,"commit":"4de157f","total":872,"values":{"true":118,"false":754}},{"timestamp":1687351639,"commit":"f5a1e40","total":872,"values":{"true":118,"false":754}},{"timestamp":1687351658,"commit":"6b0fef4","total":871,"values":{"true":118,"false":753}},{"timestamp":1687353030,"commit":"30e9528","total":871,"values":{"true":132,"false":739}},{"timestamp":1687355717,"commit":"814e515","total":871,"values":{"true":133,"false":738}},{"timestamp":1687357731,"commit":"5db3b43","total":871,"values":{"true":137,"false":734}},{"timestamp":1687361189,"commit":"1d0ba5b","total":865,"values":{"true":154,"false":711}},{"timestamp":1687361189,"commit":"2129b3d","total":865,"values":{"true":166,"false":699}},{"timestamp":1687365976,"commit":"167434b","total":865,"values":{"true":171,"false":694}},{"timestamp":1687366226,"commit":"dbb595a","total":865,"values":{"true":174,"false":691}},{"timestamp":1687366591,"commit":"526e7db","total":866,"values":{"true":217,"false":649}},{"timestamp":1687368803,"commit":"79054db","total":866,"values":{"true":223,"false":643}},{"timestamp":1687369230,"commit":"95242fe","total":866,"values":{"true":231,"false":635}},{"timestamp":1687370982,"commit":"f6d6431","total":866,"values":{"true":247,"false":619}},{"timestamp":1687378443,"commit":"2c46aee","total":867,"values":{"true":268,"false":599}},{"timestamp":1687378443,"commit":"fc2f231","total":868,"values":{"true":251,"false":617}},{"timestamp":1687382464,"commit":"a13d150","total":867,"values":{"true":276,"false":591}},{"timestamp":1687383706,"commit":"e8fab92","total":867,"values":{"true":278,"false":589}},{"timestamp":1687393452,"commit":"05f0c49","total":867,"values":{"true":289,"false":578}},{"timestamp":1687395190,"commit":"6b83d12","total":867,"values":{"true":296,"false":571}},{"timestamp":1687397513,"commit":"b705a9d","total":867,"values":{"true":306,"false":561}},{"timestamp":1687398430,"commit":"8bd4b6e","total":868,"values":{"true":313,"false":555}},{"timestamp":1687400347,"commit":"f166c87","total":871,"values":{"true":318,"false":553}},{"timestamp":1687439603,"commit":"5fe2a65","total":871,"values":{"true":330,"false":541}},{"timestamp":1687451837,"commit":"4638cd5","total":871,"values":{"true":331,"false":540}},{"timestamp":1687460258,"commit":"7644ff4","total":871,"values":{"true":331,"false":540}},{"timestamp":1687465345,"commit":"ba19195","total":871,"values":{"true":331,"false":540}},{"timestamp":1687473251,"commit":"a17f215","total":874,"values":{"true":340,"false":534}},{"timestamp":1687483861,"commit":"1657012","total":875,"values":{"true":354,"false":521}},{"timestamp":1687484487,"commit":"47c7dad","total":874,"values":{"true":449,"false":425}},{"timestamp":1687486065,"commit":"1ffa724","total":874,"values":{"true":465,"false":409}},{"timestamp":1687568962,"commit":"f57992d","total":883,"values":{"true":562,"false":321}},{"timestamp":1687569798,"commit":"88c3b60","total":883,"values":{"true":580,"false":303}},{"timestamp":1687969999,"commit":"bef51ca","total":929,"values":{"true":905,"false":24}}];
792
+ var keys_timeline_sigs = ["false","true"];
793
+
794
+ var stack_timeline_sigs = d3.stack()
795
+ .keys(keys_timeline_sigs)
796
+ .value((d, key) => toPercent(d.values[key], d.total));
797
+
798
+ var layers_timeline_sigs = stack_timeline_sigs(data_timeline_sigs);
799
+
800
+ var points_timeline_sigs = []
801
+ layers_timeline_sigs.forEach(function(d) {
802
+ d.forEach(function(p) {
803
+ p.key = d.key
804
+ points_timeline_sigs.push(p);
805
+ });
806
+ })
807
+
808
+ function draw_timeline_sigs() {
809
+ var width_timeline_sigs = document.getElementById("timeline_sigs").clientWidth;
810
+ var height_timeline_sigs = 200;
811
+
812
+ d3.select("#timeline_sigs").selectAll("*").remove()
813
+
814
+ var svg_timeline_sigs = d3.select("#timeline_sigs")
815
+ .attr("class", "inverted")
816
+ .attr("width", width_timeline_sigs)
817
+ .attr("height", height_timeline_sigs);
818
+
819
+ var xScale_timeline_sigs = d3.scaleTime()
820
+ .range([0, width_timeline_sigs])
821
+ .domain(d3.extent(data_timeline_sigs, (d) => parseDate(d.timestamp)));
822
+
823
+ svg_timeline_sigs.append("g")
824
+ .attr("class", "grid")
825
+ .attr("transform", "translate(0," + height_timeline_sigs + ")")
826
+ .call(d3.axisBottom(xScale_timeline_sigs)
827
+ .tickFormat("")
828
+ .tickSize(-height_timeline_sigs))
829
+
830
+ var yScale_timeline_sigs = d3.scaleLinear()
831
+ .range([height_timeline_sigs, 0])
832
+ .domain([0, 100]);
833
+
834
+ svg_timeline_sigs.append("g")
835
+ .attr("class", "grid")
836
+ .call(d3.axisLeft(yScale_timeline_sigs)
837
+ .tickValues([0, 25, 50, 75, 100])
838
+ .tickFormat("")
839
+ .tickSize(-width_timeline_sigs))
840
+
841
+ var area_timeline_sigs = d3.area()
842
+ .x((d) => xScale_timeline_sigs(parseDate(d.data.timestamp)))
843
+ .y0((d) => yScale_timeline_sigs(d[0]))
844
+ .y1((d) => yScale_timeline_sigs(d[1]))
845
+ .curve(d3.curveCatmullRom.alpha(1));
846
+
847
+ var layer = svg_timeline_sigs.selectAll(".layer")
848
+ .data(layers_timeline_sigs)
849
+ .enter().append("g")
850
+ .attr("class", "layer")
851
+ .attr("fill", (d, i) => strictnessColor(d.key))
852
+
853
+ layer.append("path")
854
+ .attr("class", "area")
855
+ .attr("d", area_timeline_sigs)
856
+ .attr("fill", (d) => strictnessColor(d.key))
857
+
858
+ svg_timeline_sigs.selectAll("circle")
859
+ .data(points_timeline_sigs)
860
+ .enter()
861
+ .append("circle")
862
+ .attr("class", "dot")
863
+ .attr("cx", (d) => xScale_timeline_sigs(parseDate(d.data.timestamp)))
864
+ .attr("cy", (d, i) => yScale_timeline_sigs(d[1]))
865
+ .on("mouseover", (d) => tooltip.style("opacity", 1))
866
+ .on("mousemove", tooltip_timeline_sigs)
867
+ .on("mouseleave", (d) => tooltip.style("opacity", 0));
868
+
869
+ svg_timeline_sigs.append("g")
870
+ .attr("class", "axis x")
871
+ .attr("transform", "translate(0," + height_timeline_sigs + ")")
872
+ .call(d3.axisBottom(xScale_timeline_sigs)
873
+ .tickFormat(d3.timeFormat("%y/%m/%d"))
874
+ .tickPadding(-15)
875
+ .tickSize(-3));
876
+
877
+ svg_timeline_sigs.append("g")
878
+ .attr("class", "axis y")
879
+ .call(d3.axisLeft(yScale_timeline_sigs)
880
+ .tickValues([25, 50, 75])
881
+ .tickSize(-3)
882
+ .tickFormat((d) => d + '%')
883
+ .tickPadding(-30))
884
+
885
+
886
+ }
887
+
888
+ draw_timeline_sigs();
889
+ window.addEventListener("resize", draw_timeline_sigs);
890
+ </script>
891
+
892
+ </div>
893
+ </div>
894
+
895
+ <div class="card">
896
+
897
+ <h5 class="card-header">RBIs Timeline</h5>
898
+
899
+ <div class="card-body">
900
+ <svg id="timeline_rbis"></svg>
901
+ <script>function tooltip_timeline_rbis(d) {
902
+ moveTooltip(d)
903
+ .html("commit <b>" + d.data.commit + "</b><br>"
904
+ + d3.timeFormat("%y/%m/%d")(parseDate(d.data.timestamp)) + "<br><br>"
905
+ + "Files: <b>" + d.data.values.files + "</b><br>"
906
+ + "RBIs: <b>" + d.data.values.rbis + "</b><br><br>"
907
+ + "Total: <b>" + d.data.total + "</b>")
908
+ }
909
+
910
+
911
+ var data_timeline_rbis = [{"timestamp":1684959835,"commit":"93f8153","total":141,"values":{"files":103,"rbis":38}},{"timestamp":1687348946,"commit":"5d093b9","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687349568,"commit":"24b1c92","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687351457,"commit":"97f4c09","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687351457,"commit":"74c83c2","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687351517,"commit":"4b1edef","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687351538,"commit":"f72b67c","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687351561,"commit":"305ec0b","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687351600,"commit":"6891312","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687351618,"commit":"4de157f","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687351639,"commit":"f5a1e40","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687351658,"commit":"6b0fef4","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687353030,"commit":"30e9528","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687355717,"commit":"814e515","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687357731,"commit":"5db3b43","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687361189,"commit":"1d0ba5b","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687361189,"commit":"2129b3d","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687365976,"commit":"167434b","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687366226,"commit":"dbb595a","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687366591,"commit":"526e7db","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687368803,"commit":"79054db","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687369230,"commit":"95242fe","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687370982,"commit":"f6d6431","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687378443,"commit":"2c46aee","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687378443,"commit":"fc2f231","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687382464,"commit":"a13d150","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687383706,"commit":"e8fab92","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687393452,"commit":"05f0c49","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687395190,"commit":"6b83d12","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687397513,"commit":"b705a9d","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687398430,"commit":"8bd4b6e","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687400347,"commit":"f166c87","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687439603,"commit":"5fe2a65","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687451837,"commit":"4638cd5","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687460258,"commit":"7644ff4","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687465345,"commit":"ba19195","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687473251,"commit":"a17f215","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687483861,"commit":"1657012","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687484487,"commit":"47c7dad","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687486065,"commit":"1ffa724","total":151,"values":{"files":113,"rbis":38}},{"timestamp":1687568962,"commit":"f57992d","total":152,"values":{"files":114,"rbis":38}},{"timestamp":1687569798,"commit":"88c3b60","total":152,"values":{"files":114,"rbis":38}},{"timestamp":1687969999,"commit":"bef51ca","total":157,"values":{"files":117,"rbis":40}}];
912
+ var keys_timeline_rbis = ["rbis","files"];
913
+
914
+ var stack_timeline_rbis = d3.stack()
915
+ .keys(keys_timeline_rbis)
916
+ .value((d, key) => d.values[key]);
917
+
918
+ var layers_timeline_rbis = stack_timeline_rbis(data_timeline_rbis);
919
+
920
+ var points_timeline_rbis = []
921
+ layers_timeline_rbis.forEach(function(d) {
922
+ d.forEach(function(p) {
923
+ p.key = d.key
924
+ points_timeline_rbis.push(p);
925
+ });
926
+ })
927
+
928
+ function draw_timeline_rbis() {
929
+ var width_timeline_rbis = document.getElementById("timeline_rbis").clientWidth;
930
+ var height_timeline_rbis = 200;
931
+
932
+ d3.select("#timeline_rbis").selectAll("*").remove()
933
+
934
+ var svg_timeline_rbis = d3.select("#timeline_rbis")
935
+ .attr("width", width_timeline_rbis)
936
+ .attr("height", height_timeline_rbis);
937
+
938
+ var xScale_timeline_rbis = d3.scaleTime()
939
+ .range([0, width_timeline_rbis])
940
+ .domain(d3.extent(data_timeline_rbis, (d) => parseDate(d.timestamp)));
941
+
942
+ svg_timeline_rbis.append("g")
943
+ .attr("class", "grid")
944
+ .attr("transform", "translate(0," + height_timeline_rbis + ")")
945
+ .call(d3.axisBottom(xScale_timeline_rbis)
946
+ .tickFormat("")
947
+ .tickSize(-height_timeline_rbis))
948
+
949
+ var yScale_timeline_rbis = d3.scaleLinear()
950
+ .range([height_timeline_rbis, 0])
951
+ .domain([0, d3.max(data_timeline_rbis, (d) => d.total + 10)]);
952
+
953
+ svg_timeline_rbis.append("g")
954
+ .attr("class", "grid")
955
+ .call(d3.axisLeft(yScale_timeline_rbis)
956
+ .tickValues([0, 25, 50, 75, 100])
957
+ .tickFormat("")
958
+ .tickSize(-width_timeline_rbis))
959
+
960
+ var area_timeline_rbis = d3.area()
961
+ .x((d) => xScale_timeline_rbis(parseDate(d.data.timestamp)))
962
+ .y0((d) => yScale_timeline_rbis(d[0]))
963
+ .y1((d) => yScale_timeline_rbis(d[1]))
964
+ .curve(d3.curveCatmullRom.alpha(1));
965
+
966
+ var layer = svg_timeline_rbis.selectAll(".layer")
967
+ .data(layers_timeline_rbis)
968
+ .enter().append("g")
969
+ .attr("class", "layer")
970
+
971
+ layer.append("path")
972
+ .attr("class", "area")
973
+ .attr("d", area_timeline_rbis)
974
+ .attr("fill", (d) => d.key == 'rbis' ? '#8673ff' : '#007bff')
975
+
976
+ layer.append("path")
977
+ .attr("class", "line")
978
+ .attr("d", d3.line()
979
+ .x((d) => xScale_timeline_rbis(parseDate(d.data.timestamp)))
980
+ .y((d, i) => yScale_timeline_rbis(d[1]))
981
+ .curve(d3.curveCatmullRom.alpha(1)))
982
+ .attr("stroke", (d) => d.key == 'rbis' ? '#8673ff' : '#007bff')
983
+
984
+ svg_timeline_rbis.selectAll("circle")
985
+ .data(points_timeline_rbis)
986
+ .enter()
987
+ .append("circle")
988
+ .attr("class", "dot")
989
+ .attr("cx", (d) => xScale_timeline_rbis(parseDate(d.data.timestamp)))
990
+ .attr("cy", (d, i) => yScale_timeline_rbis(d[1]))
991
+ .on("mouseover", (d) => tooltip.style("opacity", 1))
992
+ .on("mousemove", tooltip_timeline_rbis)
993
+ .on("mouseleave", (d) => tooltip.style("opacity", 0));
994
+
995
+ svg_timeline_rbis.append("g")
996
+ .attr("class", "axis x")
997
+ .attr("transform", "translate(0," + height_timeline_rbis + ")")
998
+ .call(d3.axisBottom(xScale_timeline_rbis)
999
+ .tickFormat(d3.timeFormat("%y/%m/%d"))
1000
+ .tickPadding(-15)
1001
+ .tickSize(-3));
1002
+
1003
+ svg_timeline_rbis.append("g")
1004
+ .attr("class", "axis y")
1005
+ .call(d3.axisLeft(yScale_timeline_rbis)
1006
+ .tickValues([25, 50, 75])
1007
+ .tickSize(-3)
1008
+ .tickFormat((d) => d)
1009
+ .tickPadding(-20))
1010
+
1011
+
1012
+ }
1013
+
1014
+ draw_timeline_rbis();
1015
+ window.addEventListener("resize", draw_timeline_rbis);
1016
+ </script>
1017
+
1018
+ </div>
1019
+ </div>
1020
+
1021
+ <div class="card">
1022
+
1023
+ <h5 class="card-header">Sorbet Versions Timeline</h5>
1024
+
1025
+ <div class="card-body">
1026
+ <svg id="timeline_versions"></svg>
1027
+ <script>function tooltip_timeline_versions(d) {
1028
+ moveTooltip(d)
1029
+ .html("commit <b>" + d.commit + "</b><br>"
1030
+ + d3.timeFormat("%y/%m/%d")(parseDate(d.timestamp)) + "<br><br>"
1031
+ + "static: v<b>" + d.static + "</b><br>"
1032
+ + "runtime: v<b>" + d.runtime + "</b><br><br>"
1033
+ + "versions from<br>Gemfile.lock")
1034
+ }
1035
+
1036
+
1037
+ var data_timeline_versions = [{"timestamp":1684959835,"commit":"93f8153","static":"0.5.10837","runtime":"0.5.10837"},{"timestamp":1687348946,"commit":"5d093b9","static":"0.5.10880","runtime":"0.5.10880"},{"timestamp":1687349568,"commit":"24b1c92","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687351457,"commit":"97f4c09","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687351457,"commit":"74c83c2","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687351517,"commit":"4b1edef","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687351538,"commit":"f72b67c","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687351561,"commit":"305ec0b","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687351600,"commit":"6891312","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687351618,"commit":"4de157f","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687351639,"commit":"f5a1e40","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687351658,"commit":"6b0fef4","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687353030,"commit":"30e9528","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687355717,"commit":"814e515","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687357731,"commit":"5db3b43","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687361189,"commit":"1d0ba5b","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687361189,"commit":"2129b3d","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687365976,"commit":"167434b","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687366226,"commit":"dbb595a","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687366591,"commit":"526e7db","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687368803,"commit":"79054db","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687369230,"commit":"95242fe","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687370982,"commit":"f6d6431","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687378443,"commit":"2c46aee","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687378443,"commit":"fc2f231","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687382464,"commit":"a13d150","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687383706,"commit":"e8fab92","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687393452,"commit":"05f0c49","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687395190,"commit":"6b83d12","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687397513,"commit":"b705a9d","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687398430,"commit":"8bd4b6e","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687400347,"commit":"f166c87","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687439603,"commit":"5fe2a65","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687451837,"commit":"4638cd5","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687460258,"commit":"7644ff4","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687465345,"commit":"ba19195","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687473251,"commit":"a17f215","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687483861,"commit":"1657012","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687484487,"commit":"47c7dad","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687486065,"commit":"1ffa724","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687568962,"commit":"f57992d","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687569798,"commit":"88c3b60","static":"0.5.10884","runtime":"0.5.10884"},{"timestamp":1687969999,"commit":"bef51ca","static":"0.5.10885","runtime":"0.5.10885"}];
1038
+
1039
+ function draw_timeline_versions() {
1040
+ var width_timeline_versions = document.getElementById("timeline_versions").clientWidth;
1041
+ var height_timeline_versions = 200;
1042
+
1043
+ d3.select("#timeline_versions").selectAll("*").remove()
1044
+
1045
+ var svg_timeline_versions = d3.select("#timeline_versions")
1046
+ .attr("width", width_timeline_versions)
1047
+ .attr("height", height_timeline_versions)
1048
+
1049
+ var xScale_timeline_versions = d3.scaleTime()
1050
+ .range([0, width_timeline_versions])
1051
+ .domain(d3.extent(data_timeline_versions, (d) => parseDate(d.timestamp)));
1052
+
1053
+ svg_timeline_versions.append("g")
1054
+ .attr("class", "grid")
1055
+ .attr("transform", "translate(0," + height_timeline_versions + ")")
1056
+ .call(d3.axisBottom(xScale_timeline_versions)
1057
+ .tickFormat("")
1058
+ .tickSize(-height_timeline_versions))
1059
+
1060
+ var yScale_timeline_versions = d3.scaleLinear()
1061
+ .range([height_timeline_versions, 0])
1062
+ .domain([d3.min([d3.min(data_timeline_versions, (d) => parseVersion(d.static)),
1063
+ d3.min(data_timeline_versions, (d) => parseVersion(d.runtime))]) - 0.01, d3.max([d3.max(data_timeline_versions, (d) => parseVersion(d.static)),
1064
+ d3.max(data_timeline_versions, (d) => parseVersion(d.runtime))]) + 0.01]);
1065
+
1066
+ svg_timeline_versions.append("g")
1067
+ .attr("class", "grid")
1068
+ .call(d3.axisLeft(yScale_timeline_versions)
1069
+ .ticks(8)
1070
+ .tickFormat("")
1071
+ .tickSize(-width_timeline_versions))
1072
+
1073
+ svg_timeline_versions.append("path")
1074
+ .datum(data_timeline_versions.filter((d) => parseVersion(d.runtime)))
1075
+ .attr("class", "line")
1076
+ .attr("d", d3.line()
1077
+ .x((d) => xScale_timeline_versions(parseDate(d.timestamp)))
1078
+ .y((d) => yScale_timeline_versions(parseVersion(d.runtime)))
1079
+ .curve(d3.curveStepAfter))
1080
+ .attr("stroke", "#e83e8c")
1081
+
1082
+ svg_timeline_versions.append("path")
1083
+ .datum(data_timeline_versions.filter((d) => parseVersion(d.static)))
1084
+ .attr("class", "line")
1085
+ .attr("d", d3.line()
1086
+ .x((d) => xScale_timeline_versions(parseDate(d.timestamp)))
1087
+ .y((d) => yScale_timeline_versions(parseVersion(d.static)))
1088
+ .curve(d3.curveStepAfter))
1089
+ .attr("stroke", "#007bff")
1090
+
1091
+ svg_timeline_versions.selectAll("circle")
1092
+ .data(data_timeline_versions)
1093
+ .enter()
1094
+ .append("circle")
1095
+ .attr("class", "dot")
1096
+ .attr("cx", (d) => xScale_timeline_versions(parseDate(d.timestamp)))
1097
+ .attr("cy", (d, i) => yScale_timeline_versions(parseVersion(d.static)))
1098
+ .on("mouseover", (d) => tooltip.style("opacity", 1))
1099
+ .on("mousemove", tooltip_timeline_versions)
1100
+ .on("mouseleave", (d) => tooltip.style("opacity", 0));
1101
+
1102
+ svg_timeline_versions.append("g")
1103
+ .attr("class", "axis x")
1104
+ .attr("transform", "translate(0," + height_timeline_versions + ")")
1105
+ .call(d3.axisBottom(xScale_timeline_versions)
1106
+ .tickFormat(d3.timeFormat("%y/%m/%d"))
1107
+ .tickPadding(-15)
1108
+ .tickSize(-3));
1109
+
1110
+ svg_timeline_versions.append("g")
1111
+ .attr("class", "axis y")
1112
+ .call(d3.axisLeft(yScale_timeline_versions)
1113
+ .ticks(4)
1114
+ .tickSize(-3)
1115
+ .tickFormat((d) => 'v0.' + d.toFixed(2))
1116
+ .tickPadding(-50))
1117
+
1118
+
1119
+ }
1120
+
1121
+ draw_timeline_versions();
1122
+ window.addEventListener("resize", draw_timeline_versions);
1123
+ </script>
1124
+
1125
+ </div>
1126
+ </div>
1127
+
1128
+ <div class="card">
1129
+
1130
+ <h5 class="card-header">Sorbet Typechecking Time</h5>
1131
+
1132
+ <div class="card-body">
1133
+ <svg id="timeline_runtimes"></svg>
1134
+ <script>function tooltip_timeline_runtimes(d) {
1135
+ moveTooltip(d)
1136
+ .html("commit <b>" + d.commit + "</b><br>"
1137
+ + d3.timeFormat("%y/%m/%d")(parseDate(d.timestamp)) + "<br><br>"
1138
+ + "<b>" + d.runtime + "</b>s<br><br>"
1139
+ + "(sorbet user + system time)")
1140
+ }
1141
+
1142
+
1143
+ var data_timeline_runtimes = [{"timestamp":1684959835,"commit":"93f8153","runtime":1.287636},{"timestamp":1687348946,"commit":"5d093b9","runtime":0.7352580000000001},{"timestamp":1687349568,"commit":"24b1c92","runtime":0.807698},{"timestamp":1687351457,"commit":"97f4c09","runtime":0.72845},{"timestamp":1687351457,"commit":"74c83c2","runtime":1.106142},{"timestamp":1687351517,"commit":"4b1edef","runtime":0.783385},{"timestamp":1687351538,"commit":"f72b67c","runtime":0.754455},{"timestamp":1687351561,"commit":"305ec0b","runtime":0.841583},{"timestamp":1687351600,"commit":"6891312","runtime":0.816443},{"timestamp":1687351618,"commit":"4de157f","runtime":0.801064},{"timestamp":1687351639,"commit":"f5a1e40","runtime":0.744268},{"timestamp":1687351658,"commit":"6b0fef4","runtime":0.7227870000000001},{"timestamp":1687353030,"commit":"30e9528","runtime":0.8186509999999999},{"timestamp":1687355717,"commit":"814e515","runtime":0.8571989999999999},{"timestamp":1687357731,"commit":"5db3b43","runtime":0.764678},{"timestamp":1687361189,"commit":"1d0ba5b","runtime":0.831677},{"timestamp":1687361189,"commit":"2129b3d","runtime":0.767087},{"timestamp":1687365976,"commit":"167434b","runtime":0.860074},{"timestamp":1687366226,"commit":"dbb595a","runtime":0.960253},{"timestamp":1687366591,"commit":"526e7db","runtime":0.861951},{"timestamp":1687368803,"commit":"79054db","runtime":0.8683719999999999},{"timestamp":1687369230,"commit":"95242fe","runtime":0.9232509999999999},{"timestamp":1687370982,"commit":"f6d6431","runtime":0.689648},{"timestamp":1687378443,"commit":"2c46aee","runtime":0.747771},{"timestamp":1687378443,"commit":"fc2f231","runtime":0.8729750000000001},{"timestamp":1687382464,"commit":"a13d150","runtime":0.32517399999999996},{"timestamp":1687383706,"commit":"e8fab92","runtime":0.334583},{"timestamp":1687393452,"commit":"05f0c49","runtime":0.331818},{"timestamp":1687395190,"commit":"6b83d12","runtime":0.328052},{"timestamp":1687397513,"commit":"b705a9d","runtime":0.328786},{"timestamp":1687398430,"commit":"8bd4b6e","runtime":0.333951},{"timestamp":1687400347,"commit":"f166c87","runtime":0.72973},{"timestamp":1687439603,"commit":"5fe2a65","runtime":0.7191069999999999},{"timestamp":1687451837,"commit":"4638cd5","runtime":0.836744},{"timestamp":1687460258,"commit":"7644ff4","runtime":0.49328},{"timestamp":1687465345,"commit":"ba19195","runtime":0.817055},{"timestamp":1687473251,"commit":"a17f215","runtime":0.8111499999999999},{"timestamp":1687483861,"commit":"1657012","runtime":0.88721},{"timestamp":1687484487,"commit":"47c7dad","runtime":0.5937530000000001},{"timestamp":1687486065,"commit":"1ffa724","runtime":0.812087},{"timestamp":1687568962,"commit":"f57992d","runtime":0.780592},{"timestamp":1687569798,"commit":"88c3b60","runtime":0.6738460000000001},{"timestamp":1687969999,"commit":"bef51ca","runtime":0.35927}];
1144
+
1145
+ function draw_timeline_runtimes() {
1146
+ var width_timeline_runtimes = document.getElementById("timeline_runtimes").clientWidth;
1147
+ var height_timeline_runtimes = 200;
1148
+
1149
+ d3.select("#timeline_runtimes").selectAll("*").remove()
1150
+
1151
+ var svg_timeline_runtimes = d3.select("#timeline_runtimes")
1152
+ .attr("width", width_timeline_runtimes)
1153
+ .attr("height", height_timeline_runtimes)
1154
+
1155
+ var xScale_timeline_runtimes = d3.scaleTime()
1156
+ .range([0, width_timeline_runtimes])
1157
+ .domain(d3.extent(data_timeline_runtimes, (d) => parseDate(d.timestamp)));
1158
+
1159
+ svg_timeline_runtimes.append("g")
1160
+ .attr("class", "grid")
1161
+ .attr("transform", "translate(0," + height_timeline_runtimes + ")")
1162
+ .call(d3.axisBottom(xScale_timeline_runtimes)
1163
+ .tickFormat("")
1164
+ .tickSize(-height_timeline_runtimes))
1165
+
1166
+ var yScale_timeline_runtimes = d3.scaleLinear()
1167
+ .range([height_timeline_runtimes, 0])
1168
+ .domain([0, d3.max(data_timeline_runtimes, (d) => d.runtime)]);
1169
+
1170
+ svg_timeline_runtimes.append("g")
1171
+ .attr("class", "grid")
1172
+ .call(d3.axisLeft(yScale_timeline_runtimes)
1173
+ .ticks(10)
1174
+ .tickFormat("")
1175
+ .tickSize(-width_timeline_runtimes))
1176
+
1177
+ svg_timeline_runtimes.append("path")
1178
+ .datum(data_timeline_runtimes.filter((d) => d.runtime))
1179
+ .attr("class", "area")
1180
+ .attr("d", d3.area()
1181
+ .defined((d) => d.runtime)
1182
+ .x((d) => xScale_timeline_runtimes(parseDate(d.timestamp)))
1183
+ .y0(yScale_timeline_runtimes(0))
1184
+ .y1((d) => yScale_timeline_runtimes(d.runtime))
1185
+ .curve(d3.curveCatmullRom.alpha(1)))
1186
+ .attr("fill", "#ccc")
1187
+
1188
+ svg_timeline_runtimes.append("path")
1189
+ .datum(data_timeline_runtimes.filter((d) => d.runtime))
1190
+ .attr("class", "line")
1191
+ .attr("d", d3.line()
1192
+ .x((d) => xScale_timeline_runtimes(parseDate(d.timestamp)))
1193
+ .y((d) => yScale_timeline_runtimes(d.runtime))
1194
+ .curve(d3.curveCatmullRom.alpha(1)))
1195
+ .attr("stroke", "#ccc")
1196
+
1197
+ svg_timeline_runtimes.selectAll("circle")
1198
+ .data(data_timeline_runtimes)
1199
+ .enter()
1200
+ .append("circle")
1201
+ .attr("class", "dot")
1202
+ .attr("cx", (d) => xScale_timeline_runtimes(parseDate(d.timestamp)))
1203
+ .attr("cy", (d, i) => yScale_timeline_runtimes(d.runtime))
1204
+ .on("mouseover", (d) => tooltip.style("opacity", 1))
1205
+ .on("mousemove", tooltip_timeline_runtimes)
1206
+ .on("mouseleave", (d) => tooltip.style("opacity", 0));
1207
+
1208
+ svg_timeline_runtimes.append("g")
1209
+ .attr("class", "axis x")
1210
+ .attr("transform", "translate(0," + height_timeline_runtimes + ")")
1211
+ .call(d3.axisBottom(xScale_timeline_runtimes)
1212
+ .tickFormat(d3.timeFormat("%y/%m/%d"))
1213
+ .tickPadding(-15)
1214
+ .tickSize(-3));
1215
+
1216
+ svg_timeline_runtimes.append("g")
1217
+ .attr("class", "axis y")
1218
+ .call(d3.axisLeft(yScale_timeline_runtimes)
1219
+ .ticks(5)
1220
+ .tickSize(-3)
1221
+ .tickFormat((d) => d.toFixed(2) + "s")
1222
+ .tickPadding(-40))
1223
+
1224
+ .call(g => g.selectAll(".tick:first-of-type text").remove())
1225
+
1226
+ }
1227
+
1228
+ draw_timeline_runtimes();
1229
+ window.addEventListener("resize", draw_timeline_runtimes);
1230
+ </script>
1231
+
1232
+ </div>
1233
+ </div>
1234
+
1235
+ <div class="text-center" style="margin-top: 30px">
1236
+ Typchecked by Sorbet since <b>2023-05-20</b>
1237
+ (commit <b>8bed1cd</b>).
1238
+ </div>
1239
+
1240
+ </div>
1241
+ <div class="footer">
1242
+ Generated by <a href='https://github.com/Shopify/spoom'>spoom</a> on 2023-06-28 16:37:17 UTC.
1243
+ </div>
1244
+ </div>
1245
+ </div>
1246
+ </div>
1247
+ </body>
1248
+ </html>