energy-visualization-sankey 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/README.md +497 -0
- package/babel.config.cjs +28 -0
- package/coverage/clover.xml +6 -0
- package/coverage/coverage-final.json +1 -0
- package/coverage/lcov-report/base.css +224 -0
- package/coverage/lcov-report/block-navigation.js +87 -0
- package/coverage/lcov-report/favicon.png +0 -0
- package/coverage/lcov-report/index.html +101 -0
- package/coverage/lcov-report/prettify.css +1 -0
- package/coverage/lcov-report/prettify.js +2 -0
- package/coverage/lcov-report/sort-arrow-sprite.png +0 -0
- package/coverage/lcov-report/sorter.js +210 -0
- package/coverage/lcov.info +0 -0
- package/demo-caching.js +68 -0
- package/dist/core/Sankey.d.ts +294 -0
- package/dist/core/Sankey.d.ts.map +1 -0
- package/dist/core/events/EventBus.d.ts +195 -0
- package/dist/core/events/EventBus.d.ts.map +1 -0
- package/dist/core/types/events.d.ts +42 -0
- package/dist/core/types/events.d.ts.map +1 -0
- package/dist/index.d.ts +19 -0
- package/dist/index.d.ts.map +1 -0
- package/dist/sankey.esm.js +5212 -0
- package/dist/sankey.esm.js.map +1 -0
- package/dist/sankey.standalone.esm.js +9111 -0
- package/dist/sankey.standalone.esm.js.map +1 -0
- package/dist/sankey.standalone.min.js +2 -0
- package/dist/sankey.standalone.min.js.map +1 -0
- package/dist/sankey.standalone.umd.js +9119 -0
- package/dist/sankey.standalone.umd.js.map +1 -0
- package/dist/sankey.umd.js +5237 -0
- package/dist/sankey.umd.js.map +1 -0
- package/dist/sankey.umd.min.js +2 -0
- package/dist/sankey.umd.min.js.map +1 -0
- package/dist/services/AnimationService.d.ts +229 -0
- package/dist/services/AnimationService.d.ts.map +1 -0
- package/dist/services/ConfigurationService.d.ts +173 -0
- package/dist/services/ConfigurationService.d.ts.map +1 -0
- package/dist/services/InteractionService.d.ts +377 -0
- package/dist/services/InteractionService.d.ts.map +1 -0
- package/dist/services/RenderingService.d.ts +152 -0
- package/dist/services/RenderingService.d.ts.map +1 -0
- package/dist/services/calculation/GraphService.d.ts +111 -0
- package/dist/services/calculation/GraphService.d.ts.map +1 -0
- package/dist/services/calculation/SummaryService.d.ts +149 -0
- package/dist/services/calculation/SummaryService.d.ts.map +1 -0
- package/dist/services/data/DataService.d.ts +167 -0
- package/dist/services/data/DataService.d.ts.map +1 -0
- package/dist/services/data/DataValidationService.d.ts +48 -0
- package/dist/services/data/DataValidationService.d.ts.map +1 -0
- package/dist/types/index.d.ts +189 -0
- package/dist/types/index.d.ts.map +1 -0
- package/dist/utils/Logger.d.ts +88 -0
- package/dist/utils/Logger.d.ts.map +1 -0
- package/jest.config.cjs +20 -0
- package/package.json +68 -0
- package/rollup.config.js +131 -0
- package/scripts/performance-validation-real.js +411 -0
- package/scripts/validate-optimization.sh +147 -0
- package/scripts/visual-validation-real-data.js +374 -0
- package/src/core/Sankey.ts +1039 -0
- package/src/core/events/EventBus.ts +488 -0
- package/src/core/types/events.ts +80 -0
- package/src/index.ts +35 -0
- package/src/services/AnimationService.ts +983 -0
- package/src/services/ConfigurationService.ts +497 -0
- package/src/services/InteractionService.ts +920 -0
- package/src/services/RenderingService.ts +484 -0
- package/src/services/calculation/GraphService.ts +616 -0
- package/src/services/calculation/SummaryService.ts +394 -0
- package/src/services/data/DataService.ts +380 -0
- package/src/services/data/DataValidationService.ts +155 -0
- package/src/styles/controls.css +184 -0
- package/src/styles/sankey.css +211 -0
- package/src/types/index.ts +220 -0
- package/src/utils/Logger.ts +105 -0
- package/tests/numerical-validation.test.js +575 -0
- package/tests/setup.js +53 -0
- package/tsconfig.json +54 -0
|
@@ -0,0 +1,184 @@
|
|
|
1
|
+
/* US Energy Sankey - Controls Styles */
|
|
2
|
+
|
|
3
|
+
/* Range Slider */
|
|
4
|
+
.range-slider {
|
|
5
|
+
width: 100%;
|
|
6
|
+
margin-top: 5px;
|
|
7
|
+
position: relative;
|
|
8
|
+
overflow: visible;
|
|
9
|
+
padding-top: 40px;
|
|
10
|
+
}
|
|
11
|
+
|
|
12
|
+
.range-slider__range {
|
|
13
|
+
-webkit-appearance: none;
|
|
14
|
+
width: 100%;
|
|
15
|
+
border-radius: 5px;
|
|
16
|
+
outline: none;
|
|
17
|
+
padding: 0;
|
|
18
|
+
margin: 0;
|
|
19
|
+
}
|
|
20
|
+
|
|
21
|
+
.range-slider__range:first-child {
|
|
22
|
+
background: #d7dcdf;
|
|
23
|
+
}
|
|
24
|
+
|
|
25
|
+
.range-slider__range::-webkit-slider-thumb {
|
|
26
|
+
-webkit-appearance: none;
|
|
27
|
+
appearance: none;
|
|
28
|
+
width: 11px;
|
|
29
|
+
height: 11px;
|
|
30
|
+
border-radius: 50%;
|
|
31
|
+
background: #fff;
|
|
32
|
+
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 1);
|
|
33
|
+
cursor: pointer;
|
|
34
|
+
transition: background 0.15s ease-in-out;
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
.range-slider__range::-moz-range-thumb {
|
|
38
|
+
width: 11px;
|
|
39
|
+
height: 11px;
|
|
40
|
+
border: 0;
|
|
41
|
+
border-radius: 50%;
|
|
42
|
+
background: #fff;
|
|
43
|
+
box-shadow: 0 0 4px 0 rgba(0, 0, 0, 1);
|
|
44
|
+
cursor: pointer;
|
|
45
|
+
transition: background 0.15s ease-in-out;
|
|
46
|
+
}
|
|
47
|
+
|
|
48
|
+
/* Dynamic Year Display */
|
|
49
|
+
#dynamicYear {
|
|
50
|
+
color: black;
|
|
51
|
+
position: absolute;
|
|
52
|
+
height: 25px;
|
|
53
|
+
width: 50px;
|
|
54
|
+
text-align: center;
|
|
55
|
+
border: 1px solid black;
|
|
56
|
+
border-radius: 3px;
|
|
57
|
+
display: block;
|
|
58
|
+
font-size: 16px;
|
|
59
|
+
top: 40%;
|
|
60
|
+
/*bottom: 100%;*/
|
|
61
|
+
background: white;
|
|
62
|
+
padding: 3px 5px;
|
|
63
|
+
box-shadow: 0 2px 4px rgba(0, 0, 0, 0.2);
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/* Add downward arrow pointing to slider */
|
|
67
|
+
#dynamicYear::after {
|
|
68
|
+
content: '';
|
|
69
|
+
position: absolute;
|
|
70
|
+
top: 100%;
|
|
71
|
+
left: 50%;
|
|
72
|
+
margin-left: -4px;
|
|
73
|
+
width: 0;
|
|
74
|
+
height: 0;
|
|
75
|
+
border-left: 4px solid transparent;
|
|
76
|
+
border-right: 4px solid transparent;
|
|
77
|
+
border-top: 6px solid black;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
/* Play/Pause Button */
|
|
81
|
+
#play-button {
|
|
82
|
+
border-radius: 0;
|
|
83
|
+
display: block;
|
|
84
|
+
height: 0;
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
#play-button:hover {
|
|
88
|
+
background: transparent !important;
|
|
89
|
+
}
|
|
90
|
+
|
|
91
|
+
#play-button.playbutton {
|
|
92
|
+
outline: 0;
|
|
93
|
+
background: transparent;
|
|
94
|
+
border-color: transparent transparent transparent #202020;
|
|
95
|
+
transition: 100ms all ease;
|
|
96
|
+
cursor: pointer;
|
|
97
|
+
border-style: solid;
|
|
98
|
+
border-width: 13px 0 13px 20px;
|
|
99
|
+
}
|
|
100
|
+
|
|
101
|
+
#play-button.playpaused {
|
|
102
|
+
outline: 0;
|
|
103
|
+
background: transparent;
|
|
104
|
+
height: 26px;
|
|
105
|
+
border-color: transparent transparent transparent #202020;
|
|
106
|
+
transition: 100ms all ease;
|
|
107
|
+
cursor: pointer;
|
|
108
|
+
border-style: double;
|
|
109
|
+
border-width: 0px 0 0px 20px;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
#play-button.playbutton:hover {
|
|
113
|
+
border-color: transparent transparent transparent #404040;
|
|
114
|
+
}
|
|
115
|
+
|
|
116
|
+
/* Waste Heat Toggle Switch */
|
|
117
|
+
.switch_box {
|
|
118
|
+
display: -webkit-box;
|
|
119
|
+
display: -ms-flexbox;
|
|
120
|
+
display: flex;
|
|
121
|
+
min-width: 200px;
|
|
122
|
+
-webkit-box-pack: center;
|
|
123
|
+
-ms-flex-pack: center;
|
|
124
|
+
justify-content: center;
|
|
125
|
+
-webkit-box-align: center;
|
|
126
|
+
-ms-flex-align: center;
|
|
127
|
+
align-items: center;
|
|
128
|
+
-webkit-box-flex: 1;
|
|
129
|
+
-ms-flex: 1;
|
|
130
|
+
flex: 1;
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
.box_1 {
|
|
134
|
+
background: #ffffff;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
input[type="checkbox"].switch_1 {
|
|
138
|
+
-webkit-appearance: none;
|
|
139
|
+
-moz-appearance: none;
|
|
140
|
+
appearance: none;
|
|
141
|
+
width: 3.5em;
|
|
142
|
+
height: 1.5em;
|
|
143
|
+
background: black;
|
|
144
|
+
border-radius: 3em;
|
|
145
|
+
position: relative;
|
|
146
|
+
cursor: pointer;
|
|
147
|
+
outline: none;
|
|
148
|
+
-webkit-transition: all .2s ease-in-out;
|
|
149
|
+
transition: all .2s ease-in-out;
|
|
150
|
+
}
|
|
151
|
+
|
|
152
|
+
input[type="checkbox"].switch_1:checked {
|
|
153
|
+
background: black;
|
|
154
|
+
}
|
|
155
|
+
|
|
156
|
+
input[type="checkbox"].switch_1:after {
|
|
157
|
+
position: absolute;
|
|
158
|
+
content: "";
|
|
159
|
+
width: 1.5em;
|
|
160
|
+
height: 1.5em;
|
|
161
|
+
border-radius: 50%;
|
|
162
|
+
background: #fff;
|
|
163
|
+
-webkit-box-shadow: 0 0 .25em rgba(0, 0, 0, .3);
|
|
164
|
+
box-shadow: 0 0 .25em rgba(0, 0, 0, .3);
|
|
165
|
+
-webkit-transform: scale(.7);
|
|
166
|
+
transform: scale(.7);
|
|
167
|
+
left: 0;
|
|
168
|
+
-webkit-transition: all .2s ease-in-out;
|
|
169
|
+
transition: all .2s ease-in-out;
|
|
170
|
+
}
|
|
171
|
+
|
|
172
|
+
input[type="checkbox"].switch_1:checked:after {
|
|
173
|
+
left: calc(100% - 1.5em);
|
|
174
|
+
}
|
|
175
|
+
|
|
176
|
+
/* Milestone Tick Markers */
|
|
177
|
+
#testTick .tick text {
|
|
178
|
+
cursor: pointer;
|
|
179
|
+
}
|
|
180
|
+
|
|
181
|
+
#testTick .tick text:hover {
|
|
182
|
+
color: grey;
|
|
183
|
+
transition: color 250ms;
|
|
184
|
+
}
|
|
@@ -0,0 +1,211 @@
|
|
|
1
|
+
/* US Energy Sankey - Core Styles */
|
|
2
|
+
|
|
3
|
+
/* Typography */
|
|
4
|
+
text, tspan {
|
|
5
|
+
font-family: Fieldwork, Futura, sans-serif;
|
|
6
|
+
font-size: 16px;
|
|
7
|
+
}
|
|
8
|
+
|
|
9
|
+
/* Flow Styles */
|
|
10
|
+
.flow {
|
|
11
|
+
fill: none;
|
|
12
|
+
}
|
|
13
|
+
|
|
14
|
+
.flow.heat {
|
|
15
|
+
stroke: #98002e;
|
|
16
|
+
}
|
|
17
|
+
|
|
18
|
+
.flow.elec, .flow.waste.heat {
|
|
19
|
+
stroke: #e49942;
|
|
20
|
+
}
|
|
21
|
+
|
|
22
|
+
.flow.waste {
|
|
23
|
+
stroke: #e49942;
|
|
24
|
+
opacity: 0.4;
|
|
25
|
+
}
|
|
26
|
+
|
|
27
|
+
.flow.solar {
|
|
28
|
+
stroke: #fed530;
|
|
29
|
+
}
|
|
30
|
+
|
|
31
|
+
.flow.nuclear {
|
|
32
|
+
stroke: #ca0813;
|
|
33
|
+
}
|
|
34
|
+
|
|
35
|
+
.flow.hydro {
|
|
36
|
+
stroke: #0b24fb;
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
.flow.wind {
|
|
40
|
+
stroke: #901d8f;
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
.flow.geo {
|
|
44
|
+
stroke: #905a1c;
|
|
45
|
+
}
|
|
46
|
+
|
|
47
|
+
.flow.gas {
|
|
48
|
+
stroke: #4cabf2;
|
|
49
|
+
}
|
|
50
|
+
|
|
51
|
+
.flow.coal {
|
|
52
|
+
stroke: #000000;
|
|
53
|
+
}
|
|
54
|
+
|
|
55
|
+
.flow.bio {
|
|
56
|
+
stroke: #46be48;
|
|
57
|
+
}
|
|
58
|
+
|
|
59
|
+
.flow.petro {
|
|
60
|
+
stroke: #095f0b;
|
|
61
|
+
}
|
|
62
|
+
|
|
63
|
+
/* Box Styles */
|
|
64
|
+
.box.sector {
|
|
65
|
+
fill: #cccccc;
|
|
66
|
+
}
|
|
67
|
+
|
|
68
|
+
.box.solar {
|
|
69
|
+
fill: #fed530;
|
|
70
|
+
}
|
|
71
|
+
|
|
72
|
+
.box.nuclear {
|
|
73
|
+
fill: #ca0813;
|
|
74
|
+
}
|
|
75
|
+
|
|
76
|
+
.box.hydro {
|
|
77
|
+
fill: #0b24fb;
|
|
78
|
+
}
|
|
79
|
+
|
|
80
|
+
.box.wind {
|
|
81
|
+
fill: #901d8f;
|
|
82
|
+
}
|
|
83
|
+
|
|
84
|
+
.box.geo {
|
|
85
|
+
fill: #905a1c;
|
|
86
|
+
}
|
|
87
|
+
|
|
88
|
+
.box.gas {
|
|
89
|
+
fill: #4cabf2;
|
|
90
|
+
}
|
|
91
|
+
|
|
92
|
+
.box.coal {
|
|
93
|
+
fill: #000000;
|
|
94
|
+
}
|
|
95
|
+
|
|
96
|
+
.box.bio {
|
|
97
|
+
fill: #46be48;
|
|
98
|
+
}
|
|
99
|
+
|
|
100
|
+
.box.petro {
|
|
101
|
+
fill: #095f0b;
|
|
102
|
+
}
|
|
103
|
+
|
|
104
|
+
/* Other Elements */
|
|
105
|
+
.maxline {
|
|
106
|
+
stroke: #cccccc;
|
|
107
|
+
stroke-width: 1px;
|
|
108
|
+
}
|
|
109
|
+
|
|
110
|
+
.bkgd {
|
|
111
|
+
fill: #000000;
|
|
112
|
+
}
|
|
113
|
+
|
|
114
|
+
/* Title Container */
|
|
115
|
+
.title_container {
|
|
116
|
+
border-top: 2px solid #000000;
|
|
117
|
+
border-bottom: 1px solid #000000;
|
|
118
|
+
position: relative;
|
|
119
|
+
}
|
|
120
|
+
|
|
121
|
+
.title_container img {
|
|
122
|
+
max-height: 40px;
|
|
123
|
+
position: absolute;
|
|
124
|
+
top: 5px;
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
.title_container svg {
|
|
128
|
+
position: absolute;
|
|
129
|
+
font-size: 15px;
|
|
130
|
+
}
|
|
131
|
+
|
|
132
|
+
.title_container .title {
|
|
133
|
+
font-size: 1em;
|
|
134
|
+
fill: black;
|
|
135
|
+
}
|
|
136
|
+
|
|
137
|
+
.title_container .title .unit {
|
|
138
|
+
font-size: .9em;
|
|
139
|
+
font-weight: bold;
|
|
140
|
+
}
|
|
141
|
+
|
|
142
|
+
.title_container .title .year {
|
|
143
|
+
font-size: 3.1em;
|
|
144
|
+
font-weight: bold;
|
|
145
|
+
clear: left;
|
|
146
|
+
letter-spacing: .05em;
|
|
147
|
+
font-variant-numeric: tabular-nums;
|
|
148
|
+
}
|
|
149
|
+
|
|
150
|
+
.title_container .citation, .title_container .affiliation {
|
|
151
|
+
font-family: Fieldwork-HumThin, Futura, sans-serif;
|
|
152
|
+
font-size: 1em;
|
|
153
|
+
fill: #000000;
|
|
154
|
+
font-weight: bolder;
|
|
155
|
+
}
|
|
156
|
+
|
|
157
|
+
.title_container .title-bottom, .title_container .affiliation-bottom {
|
|
158
|
+
font-family: Fieldwork-HumThin, Futura, sans-serif;
|
|
159
|
+
font-size: 1em;
|
|
160
|
+
fill: #000000;
|
|
161
|
+
font-weight: bolder;
|
|
162
|
+
}
|
|
163
|
+
|
|
164
|
+
/* Totals */
|
|
165
|
+
.total.sector {
|
|
166
|
+
font-size: 0.7em;
|
|
167
|
+
font-weight: bold;
|
|
168
|
+
}
|
|
169
|
+
|
|
170
|
+
.total.waste-level {
|
|
171
|
+
fill: #e49942;
|
|
172
|
+
opacity: 0.4;
|
|
173
|
+
}
|
|
174
|
+
|
|
175
|
+
/* Visibility */
|
|
176
|
+
.hidden {
|
|
177
|
+
visibility: hidden;
|
|
178
|
+
}
|
|
179
|
+
|
|
180
|
+
/* Tooltip */
|
|
181
|
+
.tooltip {
|
|
182
|
+
color: #000000;
|
|
183
|
+
position: absolute;
|
|
184
|
+
text-align: justify;
|
|
185
|
+
width: auto;
|
|
186
|
+
padding: 5px;
|
|
187
|
+
background: #efefef;
|
|
188
|
+
border: 1px solid black;
|
|
189
|
+
pointer-events: none;
|
|
190
|
+
z-index: 3;
|
|
191
|
+
}
|
|
192
|
+
|
|
193
|
+
.fuel_value {
|
|
194
|
+
text-align: center;
|
|
195
|
+
vertical-align: middle;
|
|
196
|
+
}
|
|
197
|
+
|
|
198
|
+
/* Waste Heat Visibility Control */
|
|
199
|
+
.waste-heat-hidden .flow.waste {
|
|
200
|
+
display: none !important;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
.waste-heat-hidden .total.waste-level {
|
|
204
|
+
display: none !important;
|
|
205
|
+
}
|
|
206
|
+
|
|
207
|
+
/* Smooth transition for waste heat toggle (optional) */
|
|
208
|
+
.flow.waste,
|
|
209
|
+
.total.waste-level {
|
|
210
|
+
transition: opacity 0.3s ease;
|
|
211
|
+
}
|
|
@@ -0,0 +1,220 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Type Definitions for Energy Sankey Library
|
|
3
|
+
*
|
|
4
|
+
* Comprehensive TypeScript type definitions for energy visualization data structures,
|
|
5
|
+
* configuration options, service interfaces, and mathematical computation types.
|
|
6
|
+
*
|
|
7
|
+
* Key Type Categories:
|
|
8
|
+
* - Error types: Custom error classes with detailed context
|
|
9
|
+
* - Data structures: Energy data points, summaries, and flow calculations
|
|
10
|
+
* - Configuration: Visual constants, fuel definitions, and styling
|
|
11
|
+
* - Mathematical types: Graph data, positioning, and computational results
|
|
12
|
+
* - Service interfaces: D3 selections, render data, and layout structures
|
|
13
|
+
*
|
|
14
|
+
* Type Safety Features:
|
|
15
|
+
* - Immutable readonly properties for data integrity
|
|
16
|
+
* - Strict type constraints for fuel and sector names
|
|
17
|
+
* - Comprehensive interface coverage for all service operations
|
|
18
|
+
* - Generic types for flexible service composition
|
|
19
|
+
*
|
|
20
|
+
*/
|
|
21
|
+
|
|
22
|
+
// Error types
|
|
23
|
+
export class SankeyError extends Error {
|
|
24
|
+
constructor(message: string, public code?: string) {
|
|
25
|
+
super(message);
|
|
26
|
+
this.name = 'SankeyError';
|
|
27
|
+
}
|
|
28
|
+
}
|
|
29
|
+
|
|
30
|
+
export class DataValidationError extends SankeyError {
|
|
31
|
+
constructor(message: string, public field?: string) {
|
|
32
|
+
super(message, 'DATA_VALIDATION');
|
|
33
|
+
this.name = 'DataValidationError';
|
|
34
|
+
}
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
// Energy sector breakdown interface
|
|
38
|
+
export interface EnergySectorBreakdown {
|
|
39
|
+
readonly elec: number;
|
|
40
|
+
readonly res: number;
|
|
41
|
+
readonly ag: number;
|
|
42
|
+
readonly indus: number;
|
|
43
|
+
readonly trans: number;
|
|
44
|
+
readonly heat: number;
|
|
45
|
+
|
|
46
|
+
[key: string]: number; // Allow dynamic access
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
// Core data structures
|
|
50
|
+
export interface EnergyDataPoint {
|
|
51
|
+
readonly year: number;
|
|
52
|
+
readonly milestone?: string;
|
|
53
|
+
readonly elec: EnergySectorBreakdown;
|
|
54
|
+
readonly waste: EnergySectorBreakdown;
|
|
55
|
+
readonly solar: EnergySectorBreakdown;
|
|
56
|
+
readonly nuclear: EnergySectorBreakdown;
|
|
57
|
+
readonly hydro: EnergySectorBreakdown;
|
|
58
|
+
readonly wind: EnergySectorBreakdown;
|
|
59
|
+
readonly geo: EnergySectorBreakdown;
|
|
60
|
+
readonly gas: EnergySectorBreakdown;
|
|
61
|
+
readonly coal: EnergySectorBreakdown;
|
|
62
|
+
readonly bio: EnergySectorBreakdown;
|
|
63
|
+
readonly petro: EnergySectorBreakdown;
|
|
64
|
+
readonly heat: EnergySectorBreakdown;
|
|
65
|
+
}
|
|
66
|
+
|
|
67
|
+
// Options interface
|
|
68
|
+
export interface SankeyOptions {
|
|
69
|
+
readonly data: EnergyDataPoint[];
|
|
70
|
+
readonly country: string;
|
|
71
|
+
readonly includeControls?: boolean;
|
|
72
|
+
readonly includeTimeline?: boolean;
|
|
73
|
+
readonly includeWasteToggle?: boolean;
|
|
74
|
+
readonly autoPlay?: boolean;
|
|
75
|
+
readonly showWasteHeat?: boolean;
|
|
76
|
+
readonly animationSpeed?: number;
|
|
77
|
+
readonly width?: number | null;
|
|
78
|
+
readonly height?: number;
|
|
79
|
+
readonly loopAnimation?: boolean;
|
|
80
|
+
readonly debugLogging?: boolean;
|
|
81
|
+
}
|
|
82
|
+
|
|
83
|
+
export interface RequiredSankeyOptions extends Required<SankeyOptions> {
|
|
84
|
+
// All optional properties are now required with defaults
|
|
85
|
+
}
|
|
86
|
+
|
|
87
|
+
// Mathematical structures
|
|
88
|
+
export interface GraphPoint {
|
|
89
|
+
x: number;
|
|
90
|
+
y: number;
|
|
91
|
+
}
|
|
92
|
+
|
|
93
|
+
export interface GraphStroke {
|
|
94
|
+
fuel: string;
|
|
95
|
+
box: string;
|
|
96
|
+
value: number;
|
|
97
|
+
stroke: number;
|
|
98
|
+
a: GraphPoint;
|
|
99
|
+
b: GraphPoint;
|
|
100
|
+
c: GraphPoint;
|
|
101
|
+
d: GraphPoint;
|
|
102
|
+
cc: GraphPoint;
|
|
103
|
+
}
|
|
104
|
+
|
|
105
|
+
export interface GraphData {
|
|
106
|
+
year: number;
|
|
107
|
+
graph: GraphStroke[];
|
|
108
|
+
totals: { [key: string]: number };
|
|
109
|
+
offsets: Offest;
|
|
110
|
+
}
|
|
111
|
+
|
|
112
|
+
interface OffestX {
|
|
113
|
+
solar: number,
|
|
114
|
+
nuclear: number,
|
|
115
|
+
hydro: number,
|
|
116
|
+
wind: number,
|
|
117
|
+
geo: number,
|
|
118
|
+
gas: number,
|
|
119
|
+
coal: number,
|
|
120
|
+
bio: number,
|
|
121
|
+
petro: number
|
|
122
|
+
}
|
|
123
|
+
|
|
124
|
+
interface OffestY {
|
|
125
|
+
elec: number,
|
|
126
|
+
res: number, // Electricity and residential
|
|
127
|
+
ag: number,
|
|
128
|
+
indus: number,
|
|
129
|
+
trans: number,
|
|
130
|
+
heat?: number | undefined,
|
|
131
|
+
}
|
|
132
|
+
|
|
133
|
+
export interface Offest {
|
|
134
|
+
x: OffestX;
|
|
135
|
+
y: OffestY;
|
|
136
|
+
}
|
|
137
|
+
|
|
138
|
+
// Summary data structures
|
|
139
|
+
export interface YearTotals {
|
|
140
|
+
year: number;
|
|
141
|
+
elec: number;
|
|
142
|
+
res: number;
|
|
143
|
+
ag: number;
|
|
144
|
+
indus: number;
|
|
145
|
+
trans: number;
|
|
146
|
+
solar: number;
|
|
147
|
+
nuclear: number;
|
|
148
|
+
hydro: number;
|
|
149
|
+
wind: number;
|
|
150
|
+
geo: number;
|
|
151
|
+
gas: number;
|
|
152
|
+
coal: number;
|
|
153
|
+
bio: number;
|
|
154
|
+
petro: number;
|
|
155
|
+
fuel_height: number;
|
|
156
|
+
waste: number;
|
|
157
|
+
heat?: number | undefined;
|
|
158
|
+
milestone?: any;
|
|
159
|
+
|
|
160
|
+
[key: string]: any;
|
|
161
|
+
}
|
|
162
|
+
|
|
163
|
+
export interface YearFlows {
|
|
164
|
+
year: number;
|
|
165
|
+
elec: number;
|
|
166
|
+
res: number;
|
|
167
|
+
ag: number;
|
|
168
|
+
indus: number;
|
|
169
|
+
trans: number;
|
|
170
|
+
heat?: number | undefined;
|
|
171
|
+
}
|
|
172
|
+
|
|
173
|
+
export interface YearLabels {
|
|
174
|
+
year: number;
|
|
175
|
+
elec: number;
|
|
176
|
+
res: number;
|
|
177
|
+
ag: number;
|
|
178
|
+
indus: number;
|
|
179
|
+
trans: number;
|
|
180
|
+
solar: number;
|
|
181
|
+
nuclear: number;
|
|
182
|
+
hydro: number;
|
|
183
|
+
wind: number;
|
|
184
|
+
geo: number;
|
|
185
|
+
gas: number;
|
|
186
|
+
coal: number;
|
|
187
|
+
bio: number;
|
|
188
|
+
petro: number;
|
|
189
|
+
heat?: number | undefined;
|
|
190
|
+
}
|
|
191
|
+
|
|
192
|
+
export interface BoxMaxes {
|
|
193
|
+
[boxName: string]: number;
|
|
194
|
+
}
|
|
195
|
+
|
|
196
|
+
export interface BoxTops {
|
|
197
|
+
[key: string]: number;
|
|
198
|
+
|
|
199
|
+
res: number;
|
|
200
|
+
ag: number;
|
|
201
|
+
indus: number;
|
|
202
|
+
trans: number;
|
|
203
|
+
}
|
|
204
|
+
|
|
205
|
+
export interface YearSums {
|
|
206
|
+
[year: number]: number;
|
|
207
|
+
}
|
|
208
|
+
|
|
209
|
+
export interface SummaryData {
|
|
210
|
+
totals: YearTotals[];
|
|
211
|
+
flows: YearFlows[];
|
|
212
|
+
labels: YearLabels[];
|
|
213
|
+
maxes: BoxMaxes;
|
|
214
|
+
boxTops: BoxTops;
|
|
215
|
+
yearSums: YearSums;
|
|
216
|
+
}
|
|
217
|
+
|
|
218
|
+
// D3 Selection types
|
|
219
|
+
export type D3SVGSelection = d3.Selection<SVGSVGElement, unknown, HTMLElement, any>;
|
|
220
|
+
export type D3DivSelection = d3.Selection<HTMLDivElement, unknown, HTMLElement, any>;
|
|
@@ -0,0 +1,105 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Performance Monitoring and Debug Logging Utility
|
|
3
|
+
*
|
|
4
|
+
* **Performance Monitoring Responsibility:**
|
|
5
|
+
* - Provides configurable debug logging for performance analysis
|
|
6
|
+
* - Tracks service initialization, calculation timing, and system events
|
|
7
|
+
* - Enables production performance monitoring without overhead
|
|
8
|
+
* - Supports performance regression detection and optimization efforts
|
|
9
|
+
*
|
|
10
|
+
* **Debug Logging Architecture:**
|
|
11
|
+
* - Configuration-controlled logging (debugLogging option)
|
|
12
|
+
* - Zero performance overhead when disabled (early returns)
|
|
13
|
+
* - Structured logging levels: log, debug, warn for different diagnostic needs
|
|
14
|
+
* - Console API integration for browser dev tools compatibility
|
|
15
|
+
*
|
|
16
|
+
* **Performance Analysis Features:**
|
|
17
|
+
* - Timing information: Service initialization, calculation duration
|
|
18
|
+
* - Cache statistics: Hit rates, cache efficiency metrics
|
|
19
|
+
* - System events: Service lifecycle, error conditions
|
|
20
|
+
* - Performance warnings: Threshold-based alerting for slow operations
|
|
21
|
+
*
|
|
22
|
+
* **Production Considerations:**
|
|
23
|
+
* - Logging disabled by default (performance-first approach)
|
|
24
|
+
* - Minimal memory footprint when disabled
|
|
25
|
+
* - No sensitive data logging (energy data values excluded)
|
|
26
|
+
* - Development-friendly: Rich diagnostic information when enabled
|
|
27
|
+
*/
|
|
28
|
+
|
|
29
|
+
import {SankeyOptions} from "@/types";
|
|
30
|
+
|
|
31
|
+
/**
|
|
32
|
+
* Logger Implementation
|
|
33
|
+
*
|
|
34
|
+
* **Performance-Optimized Logging Service:**
|
|
35
|
+
* - Configuration-controlled output (respects debugLogging option)
|
|
36
|
+
* - Early return pattern for zero overhead when disabled
|
|
37
|
+
* - Console API delegation for browser dev tools integration
|
|
38
|
+
* - Structured message formatting for diagnostic clarity
|
|
39
|
+
*/
|
|
40
|
+
export class Logger {
|
|
41
|
+
|
|
42
|
+
constructor(private options: SankeyOptions) {
|
|
43
|
+
}
|
|
44
|
+
|
|
45
|
+
/**
|
|
46
|
+
* General information logging
|
|
47
|
+
*
|
|
48
|
+
* **Usage Patterns:**
|
|
49
|
+
* - Service initialization completion and timing
|
|
50
|
+
* - Major system milestones (data loaded, services ready)
|
|
51
|
+
* - Performance metrics (calculation times, cache statistics)
|
|
52
|
+
* - User interaction events (animation start, year changes)
|
|
53
|
+
*
|
|
54
|
+
* **Performance Impact:**
|
|
55
|
+
* - Zero overhead when debugLogging disabled (early return)
|
|
56
|
+
* - Minimal string formatting cost when enabled
|
|
57
|
+
* - Console.log delegation for browser optimization
|
|
58
|
+
*/
|
|
59
|
+
public log(message: string, ...args: any[]): void {
|
|
60
|
+
if (this.options.debugLogging) {
|
|
61
|
+
console.log(message, ...args);
|
|
62
|
+
}
|
|
63
|
+
}
|
|
64
|
+
|
|
65
|
+
/**
|
|
66
|
+
* Detailed debug information logging
|
|
67
|
+
*
|
|
68
|
+
* **Usage Patterns:**
|
|
69
|
+
* - Algorithm step-by-step tracing
|
|
70
|
+
* - Cache hit/miss detailed reporting
|
|
71
|
+
* - Data transformation pipeline debugging
|
|
72
|
+
* - Complex calculation intermediate results
|
|
73
|
+
*
|
|
74
|
+
* **Development Benefits:**
|
|
75
|
+
* - Granular system behavior visibility
|
|
76
|
+
* - Algorithm verification and debugging
|
|
77
|
+
* - Performance bottleneck identification
|
|
78
|
+
*/
|
|
79
|
+
public debug(message: string, ...args: any[]): void {
|
|
80
|
+
if (this.options.debugLogging) {
|
|
81
|
+
console.debug(message, ...args);
|
|
82
|
+
}
|
|
83
|
+
}
|
|
84
|
+
|
|
85
|
+
/**
|
|
86
|
+
* Warning and performance issue logging
|
|
87
|
+
*
|
|
88
|
+
* **Usage Patterns:**
|
|
89
|
+
* - Performance threshold violations (slow initialization)
|
|
90
|
+
* - Potential optimization opportunities
|
|
91
|
+
* - Data quality warnings (unusual values)
|
|
92
|
+
* - System resource constraints
|
|
93
|
+
*
|
|
94
|
+
* **Performance Monitoring Integration:**
|
|
95
|
+
* - Automatic alerting for performance degradation
|
|
96
|
+
* - Actionable optimization recommendations
|
|
97
|
+
* - System health status reporting
|
|
98
|
+
* - Production performance monitoring
|
|
99
|
+
*/
|
|
100
|
+
public warn(message: string, ...args: any[]): void {
|
|
101
|
+
if (this.options.debugLogging) {
|
|
102
|
+
console.warn(message, ...args);
|
|
103
|
+
}
|
|
104
|
+
}
|
|
105
|
+
}
|