added c3 charts; added easyPieChart to default dashboard
Costa Tsaousis (ktsaou) committed
Jan 6, 2016 at 01:57 UTC
152067489cf032e16a2d9845f448c55d112285f0
15 files changed
+529
-8583
LICENSE.md
+20
-6
@@ -73,6 +73,18 @@ connectivity is not available.
73
Released under GNU General Public License (GPL) version 2
74
75
76
+- [FontAwesome](https://fortawesome.github.io/Font-Awesome/)
77
+
78
+ Created by Dave Gandy
79
+ Font license: [SIL OFL 1.1](http://scripts.sil.org/OFL)
80
+ CSS license: [MIT License](http://opensource.org/licenses/mit-license.html)
81
+
82
+
83
+- [IconsDB.com Icons](http://www.iconsdb.com/soylent-red-icons/seo-performance-icon.html)
84
+
85
+ Icons provided as CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
86
+
87
+
88
- [morris.js](http://morrisjs.github.io/morris.js/)
89
90
Copyright 2013, Olly Smith
@@ -85,13 +97,15 @@ connectivity is not available.
97
[MIT License](http://raphaeljs.com/license.html)
98
99
88
-- [FontAwesome](https://fortawesome.github.io/Font-Awesome/)
100
+- [C3](http://c3js.org/)
101
90
- Created by Dave Gandy
91
- Font license: [SIL OFL 1.1](http://scripts.sil.org/OFL)
92
- CSS license: [MIT License](http://opensource.org/licenses/mit-license.html)
102
+ Copyright 2013, Masayuki Tanaka
103
+ [MIT License](https://github.com/masayuki0812/c3/blob/master/LICENSE)
104
+
105
94
-- [IconsDB.com Icons](http://www.iconsdb.com/soylent-red-icons/seo-performance-icon.html)
106
+- [D3](http://d3js.org/)
107
96
- Icons provided as CC0 1.0 Universal (CC0 1.0) Public Domain Dedication
108
+ Copyright 2015, Mike Bostock
109
+ [BSD License](http://opensource.org/licenses/BSD-3-Clause)
110
+
111
src/old-and-tests/benchmark.c
deleted
-140
@@ -1,140 +0,0 @@
1
-#define _GNU_SOURCE
2
-
3
-#include <stdio.h>
4
-#include <stdlib.h>
5
-#include <unistd.h>
6
-#include <errno.h>
7
-#include <fcntl.h>
8
-#include <string.h>
9
-#include <malloc.h>
10
-#include <inttypes.h>
11
-
12
-#include <sys/types.h>
13
-#include <sys/stat.h>
14
-#include <sys/mman.h>
15
-
16
-#define FASTFILE_NORMAL 1
17
-
18
-#ifdef FASTFILE_NORMAL
19
-#define FASTFILE_BUFFER 65536
20
-#define FASTFILE_MAX_LINE_LENGTH 4096
21
-#endif
22
-
23
-typedef struct {
24
- int fd;
25
-
26
- ssize_t cursor;
27
-
28
- char buffer[FASTFILE_BUFFER + 1];
29
- ssize_t size;
30
- int eof;
31
-} fastfile;
32
-
33
-fastfile *fastfile_open(const char *filename) {
34
- fastfile *ff = malloc(sizeof(fastfile));
35
- if(!ff) goto cleanup;
36
-
37
- ff->fd = open(filename, O_RDONLY|O_NOATIME, 0666);
38
- if(ff->fd == -1) goto cleanup;
39
-
40
- ff->cursor = ff->size = ff->eof = 0;
41
- ff->buffer[0] = '\0';
42
-
43
- ssize_t r = read(ff->fd, &ff->buffer[ff->size], FASTFILE_BUFFER);
44
- if(r != -1) {
45
- ff->buffer[r + 1] = '\0';
46
- ff->size = r;
47
- if(r < FASTFILE_BUFFER) ff->eof = 1;
48
- }
49
- else goto cleanup;
50
-
51
- return ff;
52
-
53
-cleanup:
54
- if(ff) {
55
- if(ff->fd != -1) close(ff->fd);
56
- free(ff);
57
- }
58
- return NULL;
59
-}
60
-
61
-void fastfile_close(fastfile *ff) {
62
- if(ff->fd != -1) close(ff->fd);
63
- free(ff);
64
-}
65
-
66
-char *fastfile_getline(fastfile *ff) {
67
- if( !ff->eof && ff->size == FASTFILE_BUFFER && ( ff->cursor + FASTFILE_MAX_LINE_LENGTH ) > ff->size ) {
68
- // if(ff->size) fprintf(stderr, "Read more\n");
69
-
70
- memmove(ff->buffer, &ff->buffer[ff->cursor], ff->size - ff->cursor + 1);
71
- ff->size -= ff->cursor;
72
- ff->cursor = 0;
73
-
74
- ssize_t remaining = FASTFILE_BUFFER - ff->size;
75
- // fprintf(stderr, "Reading up to %ld bytes\n", remaining);
76
- ssize_t r = read(ff->fd, &ff->buffer[ff->size], remaining);
77
- if(r != -1) {
78
- ff->buffer[r + 1] = '\0';
79
- ff->size = r;
80
- // fprintf(stderr, "Read %ld bytes\n", r);
81
- }
82
-
83
- if(!r || r < remaining) {
84
- // fprintf(stderr, "Read EOF\n");
85
- ff->eof = 1;
86
- }
87
- }
88
-
89
- //fprintf(stderr, "Line starts at %ld\n", ff->cursor);
90
- if(ff->cursor >= ff->size) return NULL;
91
-
92
- char *start = &ff->buffer[ff->cursor];
93
- char *s = start;
94
-
95
- while(*s != '\n' && *s != '\0') s++;
96
- *s = '\0';
97
- ff->cursor += ( s - start + 1 );
98
- //fprintf(stderr, "Line ends at %ld\n", ff->cursor);
99
-
100
- return start;
101
-}
102
-
103
-const char *filenames[] = {
104
- "/proc/net/dev",
105
- "/proc/diskstats",
106
- "/proc/net/snmp",
107
- "/proc/net/netstat",
108
-// "/proc/net/stat/nf_conntrack",
109
-// "/proc/net/ip_vs_stats",
110
- "/proc/stat",
111
- "/proc/meminfo",
112
- "/proc/vmstat",
113
- "/proc/self/mountstats",
114
-// "/var/log/messages",
115
- NULL
116
-};
117
-
118
-int main(int argc, char **argv)
119
-{
120
- int i, k = 0;
121
- fastfile *ff;
122
- char *s;
123
-
124
- for(i = 0; i < 400000 ;i++, k++) {
125
- if(filenames[k] == NULL) k = 0;
126
-
127
- //fprintf(stderr, "\nOpening file '%s'\n", filenames[k]);
128
- ff = fastfile_open(filenames[k]);
129
- if(!ff) {
130
- fprintf(stderr, "Cannot open file '%s', reason: %s\n", filenames[k], strerror(errno));
131
- exit(1);
132
- }
133
-
134
- while((s = fastfile_getline(ff))) ;
135
- // fprintf(stderr, "%s\n", s);
136
-
137
- fastfile_close(ff);
138
- }
139
- return 0;
140
-}
src/old-and-tests/benchmark2.c
deleted
-597
@@ -1,597 +0,0 @@
1
-#define _GNU_SOURCE
2
-
3
-#include <stdio.h>
4
-#include <stdlib.h>
5
-#include <unistd.h>
6
-#include <errno.h>
7
-#include <fcntl.h>
8
-#include <string.h>
9
-#include <malloc.h>
10
-#include <inttypes.h>
11
-#include <ctype.h>
12
-#include <time.h>
13
-#include <sys/time.h>
14
-#include <sys/wait.h>
15
-
16
-#include <sys/types.h>
17
-#include <sys/stat.h>
18
-#include <sys/mman.h>
19
-
20
-/*
21
- * This is a library for reading kernel files from /proc
22
- *
23
- * The idea is this:
24
- *
25
- * - every file is opened once.
26
- * - to read updated contents, we rewind it (lseek() to 0) and read again.
27
- * - for every file, we use a buffer that is adjusted to fit its entire
28
- * contents in memory. This allows us to read it with a single read() call.
29
- * (this provides atomicity / consistency on the data read from the kernel)
30
- * - once the data are read, we update two arrays of pointers:
31
- * - a words array, pointing to each word in the data read
32
- * - a lines array, pointing to the first word for each line
33
- * This is highly optimized. Both arrays are automatically adjusted to
34
- * fit all contents and they are updated in a single pass on the data:
35
- * - a raspberry Pi can process 5.000+ files / sec.
36
- * - a J1900 celeron processor can process 23.000+ files / sec.
37
-*/
38
-
39
-#define PLUGIN_NAME "proc.plugin"
40
-
41
-int debug = 0;
42
-int update_every = 1;
43
-
44
-unsigned long long usecdiff(struct timeval *now, struct timeval *last) {
45
- return ((((now->tv_sec * 1000000ULL) + now->tv_usec) - ((last->tv_sec * 1000000ULL) + last->tv_usec)));
46
-}
47
-
48
-// ----------------------------------------------------------------------------
49
-// An array of words
50
-
51
-typedef struct {
52
- uint32_t len; // used entries
53
- uint32_t size; // capacity
54
- char *words[]; // array of pointers
55
-} ffwords;
56
-
57
-#define FFWORDS_INCREASE_STEP 200
58
-#define ffwords_get(fw, i) ((i < fw->size)?fw->words[i]:NULL)
59
-
60
-ffwords *ffwords_add(ffwords *fw, char *str) {
61
- if(debug) fprintf(stderr, PLUGIN_NAME ": adding word No %d: '%s'\n", fw->len, str);
62
-
63
- if(fw->len == fw->size) {
64
- if(debug) fprintf(stderr, PLUGIN_NAME ": expanding words\n");
65
-
66
- ffwords *new = realloc(fw, sizeof(ffwords) + (fw->size + FFWORDS_INCREASE_STEP) * sizeof(char *));
67
- if(!new) {
68
- fprintf(stderr, PLUGIN_NAME ": failed to expand words\n");
69
- free(fw);
70
- return NULL;
71
- }
72
- fw = new;
73
- fw->size += FFWORDS_INCREASE_STEP;
74
- }
75
-
76
- fw->words[fw->len++] = str;
77
-
78
- return fw;
79
-}
80
-
81
-ffwords *ffwords_new(void) {
82
- if(debug) fprintf(stderr, PLUGIN_NAME ": initializing words\n");
83
-
84
- ffwords *new = malloc(sizeof(ffwords) + FFWORDS_INCREASE_STEP * sizeof(char *));
85
- if(!new) return NULL;
86
-
87
- new->len = 0;
88
- new->size = FFWORDS_INCREASE_STEP;
89
- return new;
90
-}
91
-
92
-void ffwords_reset(ffwords *fw) {
93
- if(debug) fprintf(stderr, PLUGIN_NAME ": reseting words\n");
94
- fw->len = 0;
95
-}
96
-
97
-void ffwords_free(ffwords *fw) {
98
- if(debug) fprintf(stderr, PLUGIN_NAME ": freeing words\n");
99
-
100
- free(fw);
101
-}
102
-
103
-
104
-// ----------------------------------------------------------------------------
105
-// An array of lines
106
-
107
-typedef struct {
108
- uint32_t words; // how many words this line has
109
- uint32_t first; // the id of the first word of this line
110
- // in the words array
111
-} ffline;
112
-
113
-typedef struct {
114
- uint32_t len; // used entries
115
- uint32_t size; // capacity
116
- ffline lines[]; // array of lines
117
-} fflines;
118
-
119
-#define FFLINES_INCREASE_STEP 10
120
-
121
-fflines *fflines_add(fflines *fl, uint32_t first_word) {
122
- if(debug) fprintf(stderr, PLUGIN_NAME ": adding line %d at word %d\n", fl->len, first_word);
123
-
124
- if(fl->len == fl->size) {
125
- if(debug) fprintf(stderr, PLUGIN_NAME ": expanding lines\n");
126
-
127
- fflines *new = realloc(fl, sizeof(fflines) + (fl->size + FFLINES_INCREASE_STEP) * sizeof(ffline));
128
- if(!new) {
129
- fprintf(stderr, PLUGIN_NAME ": failed to expand lines\n");
130
- free(fl);
131
- return NULL;
132
- }
133
- fl = new;
134
- fl->size += FFLINES_INCREASE_STEP;
135
- }
136
-
137
- fl->lines[fl->len].words = 0;
138
- fl->lines[fl->len++].first = first_word;
139
-
140
- return fl;
141
-}
142
-
143
-fflines *fflines_new(void) {
144
- if(debug) fprintf(stderr, PLUGIN_NAME ": initializing lines\n");
145
-
146
- fflines *new = malloc(sizeof(fflines) + FFLINES_INCREASE_STEP * sizeof(ffline));
147
- if(!new) return NULL;
148
-
149
- new->len = 0;
150
- new->size = FFLINES_INCREASE_STEP;
151
- return new;
152
-}
153
-
154
-void fflines_reset(fflines *fl) {
155
- if(debug) fprintf(stderr, PLUGIN_NAME ": reseting lines\n");
156
-
157
- fl->len = 0;
158
-}
159
-
160
-void fflines_free(fflines *fl) {
161
- if(debug) fprintf(stderr, PLUGIN_NAME ": freeing lines\n");
162
-
163
- free(fl);
164
-}
165
-
166
-
167
-// ----------------------------------------------------------------------------
168
-// The fastfile
169
-
170
-typedef struct {
171
- char filename[FILENAME_MAX + 1];
172
- int fd; // the file desriptor
173
- ssize_t len; // the bytes we have placed into data
174
- ssize_t size; // the bytes we have allocated for data
175
- fflines *lines;
176
- ffwords *words;
177
- char separators[256];
178
- char data[]; // allocated buffer to keep file contents
179
-} fastfile;
180
-
181
-#define FASTFILE_INITIAL_BUFFER 512
182
-#define FASTFILE_INCREMENT_BUFFER 1024
183
-
184
-#define CHAR_IS_SEPARATOR 0
185
-#define CHAR_IS_NEWLINE 1
186
-#define CHAR_IS_WORD 2
187
-
188
-void fastfile_close(fastfile *ff) {
189
- if(debug) fprintf(stderr, PLUGIN_NAME ": Closing file '%s'. Reason: %s\n", ff->filename, strerror(errno));
190
-
191
- if(ff->lines) fflines_free(ff->lines);
192
- if(ff->words) ffwords_free(ff->words);
193
-
194
- if(ff->fd != -1) close(ff->fd);
195
- free(ff);
196
-}
197
-
198
-fastfile *fastfile_parser(fastfile *ff) {
199
- if(debug) fprintf(stderr, PLUGIN_NAME ": Parsing file '%s'\n", ff->filename);
200
-
201
- char *s = ff->data, *e = ff->data, *t = ff->data;
202
- uint32_t l = 0, w = 0;
203
- e += ff->len;
204
-
205
- ff->lines = fflines_add(ff->lines, w);
206
- if(!ff->lines) goto cleanup;
207
-
208
- while(s < e) {
209
- switch(ff->separators[(int)(*s)]) {
210
- case CHAR_IS_SEPARATOR:
211
- if(s == t) {
212
- // skip all leading white spaces
213
- t = ++s;
214
- continue;
215
- }
216
-
217
- // end of word
218
- *s = '\0';
219
-
220
- ff->words = ffwords_add(ff->words, t);
221
- if(!ff->words) goto cleanup;
222
-
223
- ff->lines->lines[l].words++;
224
- w++;
225
-
226
- t = ++s;
227
- continue;
228
-
229
- case CHAR_IS_NEWLINE:
230
- // end of line
231
- *s = '\0';
232
-
233
- ff->words = ffwords_add(ff->words, t);
234
- if(!ff->words) goto cleanup;
235
-
236
- ff->lines->lines[l].words++;
237
- w++;
238
-
239
- if(debug) fprintf(stderr, PLUGIN_NAME ": ended line %d with %d words\n", l, ff->lines->lines[l].words);
240
-
241
- ff->lines = fflines_add(ff->lines, w);
242
- if(!ff->lines) goto cleanup;
243
- l++;
244
-
245
- t = ++s;
246
- continue;
247
-
248
- default:
249
- s++;
250
- continue;
251
- }
252
- }
253
-
254
- if(s != t) {
255
- // the last word
256
- if(ff->len < ff->size) *s = '\0';
257
- else {
258
- // we are going to loose the last byte
259
- ff->data[ff->size - 1] = '\0';
260
- }
261
-
262
- ff->words = ffwords_add(ff->words, t);
263
- if(!ff->words) goto cleanup;
264
-
265
- ff->lines->lines[l].words++;
266
- w++;
267
- }
268
-
269
- return ff;
270
-
271
-cleanup:
272
- fprintf(stderr, PLUGIN_NAME ": Failed to parse file '%s'. Reason: %s\n", ff->filename, strerror(errno));
273
- fastfile_close(ff);
274
- return NULL;
275
-}
276
-
277
-fastfile *fastfile_readall(fastfile *ff) {
278
- if(debug) fprintf(stderr, PLUGIN_NAME ": Reading file '%s'.\n", ff->filename);
279
-
280
- ssize_t s = 0, r = ff->size, x = ff->size;
281
- ff->len = 0;
282
-
283
- while(r == x) {
284
- if(s) {
285
- if(debug) fprintf(stderr, PLUGIN_NAME ": Expanding data buffer for file '%s'.\n", ff->filename);
286
-
287
- fastfile *new = realloc(ff, sizeof(fastfile) + ff->size + FASTFILE_INCREMENT_BUFFER);
288
- if(!new) {
289
- fprintf(stderr, PLUGIN_NAME ": Cannot allocate memory for file '%s'. Reason: %s\n", ff->filename, strerror(errno));
290
- fastfile_close(ff);
291
- return NULL;
292
- }
293
- ff = new;
294
- ff->size += FASTFILE_INCREMENT_BUFFER;
295
- x = FASTFILE_INCREMENT_BUFFER;
296
- }
297
-
298
- r = read(ff->fd, &ff->data[s], ff->size - s);
299
- if(r == -1) {
300
- fprintf(stderr, PLUGIN_NAME ": Cannot read from file '%s'. Reason: %s\n", ff->filename, strerror(errno));
301
- fastfile_close(ff);
302
- return NULL;
303
- }
304
-
305
- ff->len += r;
306
- s = ff->len;
307
- }
308
-
309
- if(lseek(ff->fd, 0, SEEK_SET) == -1) {
310
- fprintf(stderr, PLUGIN_NAME ": Cannot rewind on file '%s'.\n", ff->filename);
311
- fastfile_close(ff);
312
- return NULL;
313
- }
314
-
315
- fflines_reset(ff->lines);
316
- ffwords_reset(ff->words);
317
-
318
- ff = fastfile_parser(ff);
319
-
320
- return ff;
321
-}
322
-
323
-fastfile *fastfile_open(const char *filename, const char *separators) {
324
- if(debug) fprintf(stderr, PLUGIN_NAME ": Opening file '%s'\n", filename);
325
-
326
- int fd = open(filename, O_RDONLY|O_NOATIME, 0666);
327
- if(fd == -1) {
328
- fprintf(stderr, PLUGIN_NAME ": Cannot open file '%s'. Reason: %s\n", filename, strerror(errno));
329
- return NULL;
330
- }
331
-
332
- fastfile *ff = malloc(sizeof(fastfile) + FASTFILE_INITIAL_BUFFER);
333
- if(!ff) {
334
- fprintf(stderr, PLUGIN_NAME ": Cannot allocate memory for file '%s'. Reason: %s\n", ff->filename, strerror(errno));
335
- close(fd);
336
- return NULL;
337
- }
338
-
339
- strncpy(ff->filename, filename, FILENAME_MAX);
340
- ff->filename[FILENAME_MAX] = '\0';
341
-
342
- ff->fd = fd;
343
- ff->size = FASTFILE_INITIAL_BUFFER;
344
- ff->len = 0;
345
-
346
- ff->lines = fflines_new();
347
- ff->words = ffwords_new();
348
-
349
- if(!ff->lines || !ff->words) {
350
- fprintf(stderr, PLUGIN_NAME ": Cannot initialize parser for file '%s'. Reason: %s\n", ff->filename, strerror(errno));
351
- fastfile_close(ff);
352
- return NULL;
353
- }
354
-
355
- int i;
356
- for(i = 0; i < 256 ;i++) {
357
- if(i == '\n' || i == '\r') ff->separators[i] = CHAR_IS_NEWLINE;
358
- else if(isspace(i) || !isprint(i)) ff->separators[i] = CHAR_IS_SEPARATOR;
359
- else ff->separators[i] = CHAR_IS_WORD;
360
- }
361
-
362
- if(!separators) separators = " \t=|";
363
- const char *s = separators;
364
- while(*s) ff->separators[(int)*s++] = CHAR_IS_SEPARATOR;
365
-
366
- return ff;
367
-}
368
-
369
-// ----------------------------------------------------------------------------
370
-/*
371
-#define NETDATA_COMMAND_GETOPTION
372
-#define NETDATA_COMMAND_CREATECHART
373
-#define NETDATA_COMMAND_VALUES
374
-
375
-typedef struct {
376
- char magic[5];
377
- uint16_t version;
378
- uint32_t transaction;
379
- uint32_t options;
380
- uint8_t command;
381
- uint32_t content_length;
382
-} netdata_msg_header;
383
-
384
-typedef struct {
385
- netdata_msg_header header;
386
- char section[NETDATA_CONFIG_SECTION_LEN + 1];
387
- char option[NETDATA_CONFIG_OPTION_LEN + 1];
388
- uint8_t type;
389
- union default {
390
- uint8_t boolean;
391
-
392
- }
393
-} netdata_getoption;
394
-
395
-typedef struct {
396
- netdata_header header;
397
-
398
-}
399
-*/
400
-
401
-// ----------------------------------------------------------------------------
402
-
403
-// return the number of lines present
404
-#define fastfile_lines(ff) (ff->lines->len)
405
-
406
-// return the Nth word of the file, or NULL
407
-#define fastfile_word(ff, word) (((word) < (ff)->words->len) ? (ff)->words->words[(word)] : NULL)
408
-
409
-// return the first word of the Nth line, or NULL
410
-#define fastfile_line(ff, line) (((line) < fastfile_lines(ff)) ? fastfile_word((ff), (ff)->lines->lines[(line)].first) : NULL)
411
-
412
-// return the number of words of the Nth line
413
-#define fastfile_linewords(ff, line) (((line) < fastfile_lines(ff)) ? (ff)->lines->lines[(line)].words : 0)
414
-
415
-// return the Nth word of the current line
416
-#define fastfile_lineword(ff, line, word) (((line) < fastfile_lines(ff) && (word) < fastfile_linewords(ff, (line))) ? fastfile_word((ff), (ff)->lines->lines[(line)].first + word) : NULL)
417
-
418
-// a basic processor to print the parsed file
419
-void print_processor(fastfile *ff, unsigned long long usec) {
420
- uint32_t lines = fastfile_lines(ff), l;
421
- uint32_t words, w;
422
- char *s;
423
-
424
- fprintf(stderr, PLUGIN_NAME ": File '%s' with %d lines and %d words\n", ff->filename, ff->lines->len, ff->words->len);
425
-
426
- for(l = 0; l < lines ;l++) {
427
- words = fastfile_linewords(ff, l);
428
-
429
- fprintf(stderr, PLUGIN_NAME ": line %d starts at word %d and has %d words\n", l, ff->lines->lines[l].first, ff->lines->lines[l].words);
430
-
431
- for(w = 0; w < words ;w++) {
432
- s = fastfile_lineword(ff, l, w);
433
- fprintf(stderr, PLUGIN_NAME ": [%d.%d] '%s'\n", l, w, s);
434
- }
435
- }
436
-}
437
-
438
-
439
-void proc_net_dev_processor(fastfile *ff, unsigned long long usec) {
440
- uint32_t lines = fastfile_lines(ff), l;
441
- uint32_t words;
442
-
443
- for(l = 2; l < lines ;l++) {
444
- words = fastfile_linewords(ff, l);
445
- if(words < 17) continue;
446
-
447
- fprintf(stdout, "BEGIN net.%s %llu\n", fastfile_lineword(ff, l, 0), usec);
448
- fprintf(stdout, "SET received = %s\n", fastfile_lineword(ff, l, 1));
449
- fprintf(stdout, "SET sent = %s\n", fastfile_lineword(ff, l, 9));
450
- fprintf(stdout, "END\n");
451
-
452
- fprintf(stdout, "BEGIN net_packets.%s %llu\n", fastfile_lineword(ff, l, 0), usec);
453
- fprintf(stdout, "SET received = %s\n", fastfile_lineword(ff, l, 2));
454
- fprintf(stdout, "SET sent = %s\n", fastfile_lineword(ff, l, 10));
455
- fprintf(stdout, "END\n");
456
-
457
- fprintf(stdout, "BEGIN net_errors.%s %llu\n", fastfile_lineword(ff, l, 0), usec);
458
- fprintf(stdout, "SET received = %s\n", fastfile_lineword(ff, l, 3));
459
- fprintf(stdout, "SET sent = %s\n", fastfile_lineword(ff, l, 11));
460
- fprintf(stdout, "END\n");
461
-
462
- fprintf(stdout, "BEGIN net_drops.%s %llu\n", fastfile_lineword(ff, l, 0), usec);
463
- fprintf(stdout, "SET received = %s\n", fastfile_lineword(ff, l, 4));
464
- fprintf(stdout, "SET sent = %s\n", fastfile_lineword(ff, l, 12));
465
- fprintf(stdout, "END\n");
466
-
467
- fprintf(stdout, "BEGIN net_fifo.%s %llu\n", fastfile_lineword(ff, l, 0), usec);
468
- fprintf(stdout, "SET received = %s\n", fastfile_lineword(ff, l, 5));
469
- fprintf(stdout, "SET sent = %s\n", fastfile_lineword(ff, l, 13));
470
- fprintf(stdout, "END\n");
471
-
472
- fprintf(stdout, "BEGIN net_compressed.%s %llu\n", fastfile_lineword(ff, l, 0), usec);
473
- fprintf(stdout, "SET received = %s\n", fastfile_lineword(ff, l, 7));
474
- fprintf(stdout, "SET sent = %s\n", fastfile_lineword(ff, l, 16));
475
- fprintf(stdout, "END\n");
476
-
477
- fprintf(stdout, "BEGIN net_other.%s %llu\n", fastfile_lineword(ff, l, 0), usec);
478
- fprintf(stdout, "SET frames = %s\n", fastfile_lineword(ff, l, 6));
479
- fprintf(stdout, "SET multicast = %s\n", fastfile_lineword(ff, l, 8));
480
- fprintf(stdout, "SET collisions = %s\n", fastfile_lineword(ff, l, 14));
481
- fprintf(stdout, "SET carrier = %s\n", fastfile_lineword(ff, l, 15));
482
- fprintf(stdout, "END\n");
483
- }
484
-}
485
-
486
-
487
-// ----------------------------------------------------------------------------
488
-
489
-
490
-
491
-typedef struct {
492
- const char filename[FILENAME_MAX + 1];
493
- const char separators[256];
494
- void (*processor)(fastfile *, unsigned long long);
495
- fastfile *ff;
496
- int enabled;
497
-} proc_files;
498
-
499
-proc_files files[] = {
500
- { "/proc/net/dev", " \t,:|", proc_net_dev_processor, NULL, 1 },
501
- { "/proc/diskstats", " \t,:|", print_processor, NULL, 1 },
502
- { "/proc/net/snmp", " \t,:|", print_processor, NULL, 1 },
503
- { "/proc/net/netstat", " \t,:|", print_processor, NULL, 1 },
504
- { "/proc/net/stat/nf_conntrack", " \t,:|", print_processor, NULL, 1 },
505
- { "/proc/net/ip_vs_stats", " \t,:|", print_processor, NULL, 1 },
506
- { "/proc/stat", " \t,:|", print_processor, NULL, 1 },
507
- { "/proc/meminfo", " \t,:|", print_processor, NULL, 1 },
508
- { "/proc/vmstat", " \t,:|", print_processor, NULL, 1 },
509
- { "/proc/self/mountstats", " \t", print_processor, NULL, 1 },
510
- { "/sys/class/thermal/thermal_zone0/temp", "", print_processor, NULL, 1 },
511
- { "/sys/devices/system/cpu/cpu3/cpufreq/cpuinfo_cur_freq", "", print_processor, NULL, 1 },
512
- { "", "", NULL, NULL, 0 },
513
-};
514
-
515
-void do_proc_files() {
516
- int i;
517
-
518
- unsigned long started_t = time(NULL), current_t;
519
- unsigned long long usec = 0, susec = 0;
520
- struct timeval last, now;
521
- gettimeofday(&last, NULL);
522
-
523
- while(1) {
524
- gettimeofday(&now, NULL);
525
- usec = usecdiff(&now, &last) - susec;
526
-
527
- for(i = 0; files[i].filename[0] ;i++) {
528
- if(!files[i].enabled) continue;
529
-
530
- if(debug) fprintf(stderr, PLUGIN_NAME ": File '%s'\n", files[i].filename);
531
-
532
- if(!files[i].ff) {
533
- files[i].ff = fastfile_open(files[i].filename, files[i].separators);
534
- if(!files[i].ff) {
535
- files[i].enabled = 0;
536
- continue;
537
- }
538
- }
539
-
540
- if(files[i].ff) files[i].ff = fastfile_readall(files[i].ff);
541
- if(files[i].ff) files[i].processor(files[i].ff, usec + susec);
542
- }
543
-
544
- fprintf(stderr, PLUGIN_NAME ": Last loop took %llu usec (worked for %llu, sleeped for %llu).\n", usec + susec, usec, susec);
545
- if(debug) {
546
- exit(1);
547
- }
548
-
549
- // if the last loop took less than half the time
550
- // wait the rest of the time
551
- if(usec < (update_every * 1000000ULL / 2)) susec = (update_every * 1000000ULL) - usec;
552
- else susec = update_every * 1000000ULL / 2;
553
-
554
- usleep(susec);
555
- bcopy(&now, &last, sizeof(struct timeval));
556
-
557
- current_t = time(NULL);
558
- if(current_t - started_t > 3600) exit(0);
559
- }
560
-}
561
-
562
-// ----------------------------------------------------------------------------
563
-// parse command line arguments
564
-
565
-void parse_args(int argc, char **argv)
566
-{
567
- int i, freq = 0;
568
-
569
- for(i = 1; i < argc; i++) {
570
- if(!freq) {
571
- int n = atoi(argv[i]);
572
- if(n > 0) {
573
- freq = n;
574
- continue;
575
- }
576
- }
577
-
578
- if(strcmp("debug", argv[i]) == 0) {
579
- debug = 1;
580
- continue;
581
- }
582
-
583
- fprintf(stderr, PLUGIN_NAME ": ERROR: cannot understand option %s\n", argv[i]);
584
- exit(1);
585
- }
586
-
587
- if(freq > 0) update_every = freq;
588
-}
589
-
590
-int main(int argc, char **argv)
591
-{
592
- parse_args(argc, argv);
593
-
594
- // show_charts();
595
- do_proc_files();
596
- return 0;
597
-}
src/old-and-tests/netdata.c
deleted
-7795
@@ -1,7795 +0,0 @@
1
-// enable strcasestr()
2
-#define _GNU_SOURCE
3
-
4
-#include <stdio.h>
5
-#include <stdlib.h>
6
-#include <string.h>
7
-#include <time.h>
8
-#include <unistd.h>
9
-#include <pwd.h>
10
-#include <sys/types.h>
11
-#include <sys/time.h>
12
-#include <sys/wait.h>
13
-
14
-#include <sys/socket.h>
15
-#include <sys/select.h>
16
-#include <sys/resource.h>
17
-#include <sys/stat.h>
18
-#include <sys/sendfile.h>
19
-
20
-#include <arpa/inet.h>
21
-#include <netinet/in.h>
22
-#include <netinet/tcp.h>
23
-
24
-#include <errno.h>
25
-#include <stdarg.h>
26
-#include <locale.h>
27
-#include <signal.h>
28
-#include <ctype.h>
29
-#include <time.h>
30
-#include <fcntl.h>
31
-#include <syslog.h>
32
-
33
-#include <pthread.h>
34
-#include <zlib.h>
35
-#include <malloc.h>
36
-#include <inttypes.h>
37
-#include <dirent.h>
38
-#include <sys/mman.h>
39
-
40
-void process_childs(int wait);
41
-
42
-// enabling this will detach the plugins from netdata
43
-// each plugin will have its own process group
44
-// #define DETACH_PLUGINS_FROM_NETDATA
45
-
46
-#define RRD_TYPE_NET "net"
47
-#define RRD_TYPE_NET_LEN strlen(RRD_TYPE_NET)
48
-
49
-#define RRD_TYPE_TC "tc"
50
-#define RRD_TYPE_TC_LEN strlen(RRD_TYPE_TC)
51
-
52
-#define RRD_TYPE_DISK "disk"
53
-#define RRD_TYPE_DISK_LEN strlen(RRD_TYPE_DISK)
54
-
55
-#define RRD_TYPE_NET_SNMP "ipv4"
56
-#define RRD_TYPE_NET_SNMP_LEN strlen(RRD_TYPE_NET_SNMP)
57
-
58
-#define RRD_TYPE_NET_STAT_CONNTRACK "conntrack"
59
-#define RRD_TYPE_NET_STAT_CONNTRACK_LEN strlen(RRD_TYPE_NET_STAT_CONNTRACK)
60
-
61
-#define RRD_TYPE_NET_IPVS "ipvs"
62
-#define RRD_TYPE_NET_IPVS_LEN strlen(RRD_TYPE_NET_IPVS)
63
-
64
-#define RRD_TYPE_STAT "cpu"
65
-#define RRD_TYPE_STAT_LEN strlen(RRD_TYPE_STAT)
66
-
67
-#define WEB_PATH_FILE "file"
68
-#define WEB_PATH_DATA "data"
69
-#define WEB_PATH_DATASOURCE "datasource"
70
-#define WEB_PATH_GRAPH "graph"
71
-
72
-// type of JSON generations
73
-#define DATASOURCE_JSON 0
74
-#define DATASOURCE_GOOGLE_JSON 1
75
-#define DATASOURCE_GOOGLE_JSONP 2
76
-
77
-// internal defaults
78
-#define UPDATE_EVERY 1
79
-#define UPDATE_EVERY_MAX 3600
80
-#define LISTEN_PORT 19999
81
-#define HISTORY 3600
82
-#define HISTORY_MAX (86400*10)
83
-#define SAVE_PATH "/tmp"
84
-
85
-#define D_WEB_BUFFER 0x00000001
86
-#define D_WEB_CLIENT 0x00000002
87
-#define D_LISTENER 0x00000004
88
-#define D_WEB_DATA 0x00000008
89
-#define D_OPTIONS 0x00000010
90
-#define D_PROCNETDEV_LOOP 0x00000020
91
-#define D_RRD_STATS 0x00000040
92
-#define D_WEB_CLIENT_ACCESS 0x00000080
93
-#define D_TC_LOOP 0x00000100
94
-#define D_DEFLATE 0x00000200
95
-#define D_CONFIG 0x00000400
96
-#define D_PLUGINSD 0x00000800
97
-#define D_CHILDS 0x00001000
98
-#define D_EXIT 0x00002000
99
-#define D_CHECKS 0x00004000
100
-
101
-#define CT_APPLICATION_JSON 1
102
-#define CT_TEXT_PLAIN 2
103
-#define CT_TEXT_HTML 3
104
-#define CT_APPLICATION_X_JAVASCRIPT 4
105
-#define CT_TEXT_CSS 5
106
-#define CT_TEXT_XML 6
107
-#define CT_APPLICATION_XML 7
108
-#define CT_TEXT_XSL 8
109
-#define CT_APPLICATION_OCTET_STREAM 9
110
-#define CT_APPLICATION_X_FONT_TRUETYPE 10
111
-#define CT_APPLICATION_X_FONT_OPENTYPE 11
112
-#define CT_APPLICATION_FONT_WOFF 12
113
-#define CT_APPLICATION_VND_MS_FONTOBJ 13
114
-#define CT_IMAGE_SVG_XML 14
115
-
116
-
117
-#define DEBUG (D_WEB_CLIENT_ACCESS|D_LISTENER|D_RRD_STATS)
118
-//#define DEBUG 0xffffffff
119
-//#define DEBUG (0)
120
-
121
-#define HOSTNAME_MAX 1024
122
-char *hostname;
123
-
124
-#define EXIT_FAILURE 1
125
-#define LISTEN_BACKLOG 100
126
-
127
-#define INITIAL_WEB_DATA_LENGTH 65536
128
-#define WEB_DATA_LENGTH_INCREASE_STEP 65536
129
-#define ZLIB_CHUNK 16384
130
-
131
-#define MAX_HTTP_HEADER_SIZE 16384
132
-
133
-#define MAX_PROC_NET_SNMP_LINE 4096
134
-#define MAX_PROC_NET_SNMP_NAME 1024
135
-
136
-#define MAX_PROC_NET_STAT_CONNTRACK_LINE 4096
137
-#define MAX_PROC_NET_STAT_CONNTRACK_NAME 1024
138
-
139
-#define MAX_PROC_NET_IPVS_LINE 4096
140
-#define MAX_PROC_NET_IPVS_NAME 1024
141
-
142
-#define MAX_PROC_STAT_LINE 4096
143
-#define MAX_PROC_STAT_NAME 1024
144
-
145
-
146
-int silent = 0;
147
-int save_history = HISTORY;
148
-int update_every = UPDATE_EVERY;
149
-int listen_port = LISTEN_PORT;
150
-
151
-
152
-// ----------------------------------------------------------------------------
153
-// global statistics
154
-
155
-struct global_statistics {
156
-
157
- unsigned long long connected_clients;
158
-
159
- unsigned long long web_requests;
160
-
161
- unsigned long long bytes_received;
162
- unsigned long long bytes_sent;
163
-
164
-} global_statistics = { 0ULL, 0ULL, 0ULL, 0ULL };
165
-
166
-pthread_mutex_t global_statistics_mutex = PTHREAD_MUTEX_INITIALIZER;
167
-
168
-void global_statistics_lock(void)
169
-{
170
- pthread_mutex_lock(&global_statistics_mutex);
171
-}
172
-void global_statistics_unlock(void)
173
-{
174
- pthread_mutex_unlock(&global_statistics_mutex);
175
-}
176
-
177
-// ----------------------------------------------------------------------------
178
-// LOG
179
-
180
-unsigned long long debug_flags = DEBUG;
181
-
182
-int access_fd = -1;
183
-FILE *stdaccess = NULL;
184
-
185
-int access_log_syslog = 1;
186
-int error_log_syslog = 1;
187
-int output_log_syslog = 1; // debug log
188
-
189
-
190
-void log_date(FILE *out)
191
-{
192
- char outstr[200];
193
- time_t t;
194
- struct tm *tmp;
195
-
196
- t = time(NULL);
197
- tmp = localtime(&t);
198
-
199
- if (tmp == NULL) return;
200
- if (strftime(outstr, sizeof(outstr), "%y-%m-%d %H:%M:%S", tmp) == 0) return;
201
-
202
- fprintf(out, "%s: ", outstr);
203
-}
204
-
205
-int debug_variable;
206
-//#define debug(args...) debug_int(__FILE__, __FUNCTION__, __LINE__, ##args)
207
-#define debug(type, args...) do { if(!silent && debug_flags & type) debug_int(__FILE__, __FUNCTION__, __LINE__, ##args); } while(0)
208
-
209
-void debug_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
210
-{
211
- if(file) { ; }
212
- va_list args;
213
-
214
- log_date(stdout);
215
- va_start( args, fmt );
216
- fprintf(stdout, "DEBUG (%04lu@%-15.15s): ", line, function);
217
- vfprintf( stdout, fmt, args );
218
- va_end( args );
219
- fprintf(stdout, "\n");
220
-
221
- if(output_log_syslog) {
222
- va_start( args, fmt );
223
- vsyslog(LOG_ERR, fmt, args );
224
- va_end( args );
225
- }
226
-}
227
-
228
-#define info(args...) info_int(__FILE__, __FUNCTION__, __LINE__, ##args)
229
-
230
-void info_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
231
-{
232
- if(file) { ; }
233
- va_list args;
234
-
235
- log_date(stderr);
236
-
237
- va_start( args, fmt );
238
- if(debug_flags) fprintf(stderr, "INFO (%04lu@%-15.15s): ", line, function);
239
- else fprintf(stderr, "INFO: ");
240
- vfprintf( stderr, fmt, args );
241
- va_end( args );
242
-
243
- fprintf(stderr, "\n");
244
-
245
- if(error_log_syslog) {
246
- va_start( args, fmt );
247
- vsyslog(LOG_INFO, fmt, args );
248
- va_end( args );
249
- }
250
-}
251
-
252
-#define error(args...) error_int(__FILE__, __FUNCTION__, __LINE__, ##args)
253
-
254
-void error_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
255
-{
256
- if(file) { ; }
257
- va_list args;
258
-
259
- log_date(stderr);
260
-
261
- va_start( args, fmt );
262
- if(debug_flags) fprintf(stderr, "ERROR (%04lu@%-15.15s): ", line, function);
263
- else fprintf(stderr, "ERROR: ");
264
- vfprintf( stderr, fmt, args );
265
- va_end( args );
266
-
267
- if(errno) {
268
- fprintf(stderr, " (errno %d, %s)\n", errno, strerror(errno));
269
- errno = 0;
270
- }
271
- else fprintf(stderr, "\n");
272
-
273
- if(error_log_syslog) {
274
- va_start( args, fmt );
275
- vsyslog(LOG_ERR, fmt, args );
276
- va_end( args );
277
- }
278
-}
279
-
280
-#define fatal(args...) fatal_int(__FILE__, __FUNCTION__, __LINE__, ##args)
281
-
282
-void fatal_int( const char *file, const char *function, const unsigned long line, const char *fmt, ... )
283
-{
284
- if(file) { ; }
285
- va_list args;
286
-
287
- log_date(stderr);
288
-
289
- va_start( args, fmt );
290
- if(debug_flags) fprintf(stderr, "FATAL (%04lu@%-15.15s): ", line, function);
291
- else fprintf(stderr, "FATAL: ");
292
- vfprintf( stderr, fmt, args );
293
- va_end( args );
294
-
295
- perror(" # ");
296
- fprintf(stderr, "\n");
297
-
298
- if(error_log_syslog) {
299
- va_start( args, fmt );
300
- vsyslog(LOG_CRIT, fmt, args );
301
- va_end( args );
302
- }
303
-
304
- exit(EXIT_FAILURE);
305
-}
306
-
307
-void log_access( const char *fmt, ... )
308
-{
309
- va_list args;
310
-
311
- if(stdaccess) {
312
- log_date(stdaccess);
313
-
314
- va_start( args, fmt );
315
- vfprintf( stdaccess, fmt, args );
316
- va_end( args );
317
- fprintf( stdaccess, "\n");
318
- fflush( stdaccess );
319
- }
320
-
321
- if(access_log_syslog) {
322
- va_start( args, fmt );
323
- vsyslog(LOG_INFO, fmt, args );
324
- va_end( args );
325
- }
326
-}
327
-
328
-
329
-// ----------------------------------------------------------------------------
330
-// helpers
331
-
332
-#define abs(x) ((x < 0)? -x : x)
333
-
334
-unsigned long long usecdiff(struct timeval *now, struct timeval *last) {
335
- return ((((now->tv_sec * 1000000ULL) + now->tv_usec) - ((last->tv_sec * 1000000ULL) + last->tv_usec)));
336
-}
337
-
338
-unsigned long simple_hash(const char *name)
339
-{
340
- int i, len = strlen(name);
341
- unsigned long hash = 0;
342
-
343
- for(i = 0; i < len ;i++) hash += (i * name[i]) + i + name[i];
344
-
345
- return hash;
346
-}
347
-
348
-#define PIPE_READ 0
349
-#define PIPE_WRITE 1
350
-
351
-FILE *mypopen(const char *command, pid_t *pidptr)
352
-{
353
- int pipefd[2];
354
-
355
- if(pipe(pipefd) == -1) return NULL;
356
-
357
- int pid = fork();
358
- if(pid == -1) {
359
- close(pipefd[PIPE_READ]);
360
- close(pipefd[PIPE_WRITE]);
361
- return NULL;
362
- }
363
- if(pid != 0) {
364
- // the parent
365
- *pidptr = pid;
366
- close(pipefd[PIPE_WRITE]);
367
- FILE *fp = fdopen(pipefd[PIPE_READ], "r");
368
- return(fp);
369
- }
370
- // the child
371
-
372
- // close all files
373
- int i;
374
- for(i = sysconf(_SC_OPEN_MAX); i > 0; i--)
375
- if(i != STDIN_FILENO && i != STDERR_FILENO && i != pipefd[PIPE_WRITE]) close(i);
376
-
377
- // move the pipe to stdout
378
- if(pipefd[PIPE_WRITE] != STDOUT_FILENO) {
379
- dup2(pipefd[PIPE_WRITE], STDOUT_FILENO);
380
- close(pipefd[PIPE_WRITE]);
381
- }
382
-
383
-#ifdef DETACH_PLUGINS_FROM_NETDATA
384
- // this was an attempt to detach the child and use the suspend mode charts.d
385
- // unfortunatelly it does not work as expected.
386
-
387
- // fork again to become session leader
388
- pid = fork();
389
- if(pid == -1) fprintf(stderr, "Cannot fork again on pid %d\n", getpid());
390
- if(pid != 0) {
391
- // the parent
392
- exit(0);
393
- }
394
-
395
- // set a new process group id for just this child
396
- if( setpgid(0, 0) != 0 )
397
- fprintf(stderr, "Cannot set a new process group for pid %d (%s)\n", getpid(), strerror(errno));
398
-
399
- if( getpgid(0) != getpid() )
400
- fprintf(stderr, "Process group set is incorrect. Expected %d, found %d\n", getpid(), getpgid(0));
401
-
402
- if( setsid() != 0 )
403
- fprintf(stderr, "Cannot set session id for pid %d (%s)\n", getpid(), strerror(errno));
404
-
405
- fprintf(stdout, "MYPID %d\n", getpid());
406
- fflush(NULL);
407
-#endif
408
-
409
- // ignore all signals
410
- for (i = 1 ; i < 65 ;i++) if(i != SIGSEGV) signal(i, SIG_DFL);
411
-
412
- fprintf(stderr, "executing command: '%s' on pid %d.\n", command, getpid());
413
- execl("/bin/sh", "sh", "-c", command, NULL);
414
- exit(1);
415
-}
416
-
417
-void mypclose(FILE *fp)
418
-{
419
- // this is a very poor implementation of pclose()
420
- // the caller should catch SIGCHLD and waitpid() on the exited child
421
- // otherwise the child will be a zombie forever
422
-
423
- fclose(fp);
424
-}
425
-
426
-
427
-// ----------------------------------------------------------------------------
428
-// URL encode / decode
429
-// code from: http://www.geekhideout.com/urlcode.shtml
430
-
431
-/* Converts a hex character to its integer value */
432
-char from_hex(char ch) {
433
- return (char)(isdigit(ch) ? ch - '0' : tolower(ch) - 'a' + 10);
434
-}
435
-
436
-/* Converts an integer value to its hex character*/
437
-char to_hex(char code) {
438
- static char hex[] = "0123456789abcdef";
439
- return hex[code & 15];
440
-}
441
-
442
-/* Returns a url-encoded version of str */
443
-/* IMPORTANT: be sure to free() the returned string after use */
444
-char *url_encode(char *str) {
445
- char *pstr = str,
446
- *buf = malloc(strlen(str) * 3 + 1),
447
- *pbuf = buf;
448
-
449
- while (*pstr) {
450
- if (isalnum(*pstr) || *pstr == '-' || *pstr == '_' || *pstr == '.' || *pstr == '~')
451
- *pbuf++ = *pstr;
452
-
453
- else if (*pstr == ' ')
454
- *pbuf++ = '+';
455
-
456
- else
457
- *pbuf++ = '%', *pbuf++ = to_hex(*pstr >> 4), *pbuf++ = to_hex(*pstr & 15);
458
-
459
- pstr++;
460
- }
461
-
462
- *pbuf = '\0';
463
-
464
- return buf;
465
-}
466
-
467
-/* Returns a url-decoded version of str */
468
-/* IMPORTANT: be sure to free() the returned string after use */
469
-char *url_decode(char *str) {
470
- char *pstr = str,
471
- *buf = malloc(strlen(str) + 1),
472
- *pbuf = buf;
473
-
474
- if(!buf) fatal("Cannot allocate memory.");
475
-
476
- while (*pstr) {
477
- if (*pstr == '%') {
478
- if (pstr[1] && pstr[2]) {
479
- *pbuf++ = from_hex(pstr[1]) << 4 | from_hex(pstr[2]);
480
- pstr += 2;
481
- }
482
- }
483
- else if (*pstr == '+')
484
- *pbuf++ = ' ';
485
-
486
- else
487
- *pbuf++ = *pstr;
488
-
489
- pstr++;
490
- }
491
-
492
- *pbuf = '\0';
493
-
494
- return buf;
495
-}
496
-
497
-
498
-// ----------------------------------------------------------------------------
499
-// socket
500
-
501
-int listen_fd = -1;
502
-
503
-int create_listen_socket(int port)
504
-{
505
- int sock=-1;
506
- int sockopt=1;
507
- struct sockaddr_in name;
508
-
509
- debug(D_LISTENER, "Creating new listening socket on port %d", port);
510
-
511
- sock = socket(AF_INET, SOCK_STREAM, 0);
512
- if (sock < 0)
513
- fatal("socket() failed, errno=%d", errno);
514
-
515
- /* avoid "address already in use" */
516
- setsockopt(sock, SOL_SOCKET, SO_REUSEADDR, (void*)&sockopt, sizeof(sockopt));
517
-
518
- memset(&name, 0, sizeof(struct sockaddr_in));
519
- name.sin_family = AF_INET;
520
- name.sin_port = htons (port);
521
- name.sin_addr.s_addr = htonl (INADDR_ANY);
522
- if (bind (sock, (struct sockaddr *) &name, sizeof (name)) < 0)
523
- fatal("bind() failed, errno=%d", errno);
524
-
525
- if (listen(sock, LISTEN_BACKLOG) < 0)
526
- fatal("listen() failed, errno=%d", errno);
527
-
528
- debug(D_LISTENER, "Listening Port %d created", port);
529
- return sock;
530
-}
531
-
532
-
533
-// ----------------------------------------------------------------------------
534
-// CONFIG
535
-
536
-#define CONFIG_MAX_NAME 100
537
-#define CONFIG_MAX_VALUE 1024
538
-#define CONFIG_FILENAME "netdata.conf"
539
-#define CONFIG_FILE_LINE_MAX 4096
540
-
541
-pthread_rwlock_t config_rwlock = PTHREAD_RWLOCK_INITIALIZER;
542
-
543
-struct config_value {
544
- char name[CONFIG_MAX_NAME + 1];
545
- char value[CONFIG_MAX_VALUE + 1];
546
-
547
- unsigned long hash; // a simple hash to speed up searching
548
- // we first compare hashes, and only if the hashes are equal we do string comparisons
549
-
550
- int loaded; // loaded from the user config
551
- int used; // has been accessed from the program
552
- int changed; // changed from the internal default
553
-
554
- struct config_value *next;
555
-};
556
-
557
-struct config {
558
- char name[CONFIG_MAX_NAME + 1];
559
-
560
- unsigned long hash; // a simple hash to speed up searching
561
- // we first compare hashes, and only if the hashes are equal we do string comparisons
562
-
563
- struct config_value *values;
564
-
565
- struct config *next;
566
-} *config_root = NULL;
567
-
568
-struct config_value *config_value_create(struct config *co, const char *name, const char *value)
569
-{
570
- debug(D_CONFIG, "Creating config entry for name '%s', value '%s', in section '%s'.", name, value, co->name);
571
-
572
- struct config_value *cv = calloc(1, sizeof(struct config_value));
573
- if(!cv) fatal("Cannot allocate config_value");
574
-
575
- strncpy(cv->name, name, CONFIG_MAX_NAME);
576
- strncpy(cv->value, value, CONFIG_MAX_VALUE);
577
- cv->hash = simple_hash(cv->name);
578
-
579
- // no need for string termination, due to calloc()
580
-
581
- struct config_value *cv2 = co->values;
582
- if(cv2) {
583
- while (cv2->next) cv2 = cv2->next;
584
- cv2->next = cv;
585
- }
586
- else co->values = cv;
587
-
588
- return cv;
589
-}
590
-
591
-struct config *config_create(const char *section)
592
-{
593
- debug(D_CONFIG, "Creating section '%s'.", section);
594
-
595
- struct config *co = calloc(1, sizeof(struct config));
596
- if(!co) fatal("Cannot allocate config");
597
-
598
- strncpy(co->name, section, CONFIG_MAX_NAME);
599
- co->hash = simple_hash(co->name);
600
-
601
- // no need for string termination, due to calloc()
602
-
603
- struct config *co2 = config_root;
604
- if(co2) {
605
- while (co2->next) co2 = co2->next;
606
- co2->next = co;
607
- }
608
- else config_root = co;
609
-
610
- return co;
611
-}
612
-
613
-struct config *config_find_section(const char *section)
614
-{
615
- struct config *co;
616
- unsigned long hash = simple_hash(section);
617
-
618
- for(co = config_root; co ; co = co->next)
619
- if(hash == co->hash)
620
- if(strcmp(co->name, section) == 0)
621
- break;
622
-
623
- return co;
624
-}
625
-
626
-char *trim(char *s)
627
-{
628
- // skip leading spaces
629
- while(*s && isspace(*s)) s++;
630
- if(!*s || *s == '#') return NULL;
631
-
632
- // skip tailing spaces
633
- int c = strlen(s) - 1;
634
- while(c >= 0 && isspace(s[c])) {
635
- s[c] = '\0';
636
- c--;
637
- }
638
- if(c < 0) return NULL;
639
- if(!*s) return NULL;
640
- return s;
641
-}
642
-
643
-int load_config(char *filename, int overwrite_used)
644
-{
645
- int line = 0;
646
- struct config *co = NULL;
647
-
648
- pthread_rwlock_wrlock(&config_rwlock);
649
-
650
- char buffer[CONFIG_FILE_LINE_MAX + 1], *s;
651
-
652
- if(!filename) filename = CONFIG_DIR "/" CONFIG_FILENAME;
653
- FILE *fp = fopen(filename, "r");
654
- if(!fp) {
655
- error("Cannot open file '%s'", CONFIG_DIR "/" CONFIG_FILENAME);
656
- pthread_rwlock_unlock(&config_rwlock);
657
- return 0;
658
- }
659
-
660
- while(fgets(buffer, CONFIG_FILE_LINE_MAX, fp) != NULL) {
661
- buffer[CONFIG_FILE_LINE_MAX] = '\0';
662
- line++;
663
-
664
- s = trim(buffer);
665
- if(!s) {
666
- debug(D_CONFIG, "Ignoring line %d, it is empty.", line);
667
- continue;
668
- }
669
-
670
- int len = strlen(s);
671
- if(*s == '[' && s[len - 1] == ']') {
672
- // new section
673
- s[len - 1] = '\0';
674
- s++;
675
-
676
- co = config_find_section(s);
677
- if(!co) co = config_create(s);
678
-
679
- continue;
680
- }
681
-
682
- if(!co) {
683
- // line outside a section
684
- error("Ignoring line %d ('%s'), it is outsize all sections.", line, s);
685
- continue;
686
- }
687
-
688
- char *name = s;
689
- char *value = strchr(s, '=');
690
- if(!value) {
691
- error("Ignoring line %d ('%s'), there is no = in it.", line, s);
692
- continue;
693
- }
694
- *value = '\0';
695
- value++;
696
-
697
- name = trim(name);
698
- value = trim(value);
699
-
700
- if(!name) {
701
- error("Ignoring line %d, name is empty.", line);
702
- continue;
703
- }
704
- if(!value) {
705
- debug(D_CONFIG, "Ignoring line %d, value is empty.", line);
706
- continue;
707
- }
708
-
709
- struct config_value *cv;
710
- for(cv = co->values; cv ; cv = cv->next)
711
- if(strcmp(cv->name, name) == 0) break;
712
-
713
- if(!cv) cv = config_value_create(co, name, value);
714
- else {
715
- if((cv->used && overwrite_used) || !cv->used) {
716
- debug(D_CONFIG, "Overwriting '%s/%s'.", line, co->name, cv->name);
717
- strncpy(cv->value, value, CONFIG_MAX_VALUE);
718
- // termination is already there
719
- }
720
- else
721
- debug(D_CONFIG, "Ignoring line %d, '%s/%s' is already present and used.", line, co->name, cv->name);
722
- }
723
- cv->loaded = 1;
724
- }
725
-
726
- fclose(fp);
727
-
728
- pthread_rwlock_unlock(&config_rwlock);
729
- return 1;
730
-}
731
-
732
-char *config_get(const char *section, const char *name, const char *default_value)
733
-{
734
- struct config_value *cv;
735
-
736
- debug(D_CONFIG, "request to get config in section '%s', name '%s', default_value '%s'", section, name, default_value);
737
-
738
- pthread_rwlock_rdlock(&config_rwlock);
739
-
740
- struct config *co = config_find_section(section);
741
- if(!co) co = config_create(section);
742
-
743
- unsigned long hash = simple_hash(name);
744
- for(cv = co->values; cv ; cv = cv->next)
745
- if(hash == cv->hash)
746
- if(strcmp(cv->name, name) == 0)
747
- break;
748
-
749
- if(!cv) cv = config_value_create(co, name, default_value);
750
- cv->used = 1;
751
-
752
- if(cv->loaded || cv->changed) {
753
- // this is a loaded value from the config file
754
- // if it is different that the default, mark it
755
- if(strcmp(cv->value, default_value) != 0) cv->changed = 1;
756
- }
757
- else {
758
- // this is not loaded from the config
759
- // copy the default value to it
760
- strncpy(cv->value, default_value, CONFIG_MAX_VALUE);
761
- }
762
-
763
- pthread_rwlock_unlock(&config_rwlock);
764
- return(cv->value);
765
-}
766
-
767
-long long config_get_number(const char *section, const char *name, long long value)
768
-{
769
- char buffer[100], *s;
770
- sprintf(buffer, "%lld", value);
771
-
772
- s = config_get(section, name, buffer);
773
- return strtoll(s, NULL, 0);
774
-}
775
-
776
-int config_get_boolean(const char *section, const char *name, int value)
777
-{
778
- char *s;
779
- if(value) s = "yes";
780
- else s = "no";
781
-
782
- s = config_get(section, name, s);
783
-
784
- if(strcmp(s, "yes") == 0 || strcmp(s, "true") == 0 || strcmp(s, "1") == 0) {
785
- strcpy(s, "yes");
786
- return 1;
787
- }
788
- else {
789
- strcpy(s, "no");
790
- return 0;
791
- }
792
-}
793
-
794
-const char *config_set(const char *section, const char *name, const char *value)
795
-{
796
- struct config_value *cv;
797
-
798
- debug(D_CONFIG, "request to set config in section '%s', name '%s', value '%s'", section, name, value);
799
-
800
- pthread_rwlock_wrlock(&config_rwlock);
801
-
802
- struct config *co = config_find_section(section);
803
- if(!co) co = config_create(section);
804
-
805
- unsigned long hash = simple_hash(name);
806
- for(cv = co->values; cv ; cv = cv->next)
807
- if(hash == cv->hash)
808
- if(strcmp(cv->name, name) == 0)
809
- break;
810
-
811
- if(!cv) cv = config_value_create(co, name, value);
812
- cv->used = 1;
813
-
814
- if(strcmp(cv->value, value) != 0) cv->changed = 1;
815
-
816
- strncpy(cv->value, value, CONFIG_MAX_VALUE);
817
- // termination is already there
818
-
819
- pthread_rwlock_unlock(&config_rwlock);
820
-
821
- return value;
822
-}
823
-
824
-long long config_set_number(const char *section, const char *name, long long value)
825
-{
826
- char buffer[100];
827
- sprintf(buffer, "%lld", value);
828
-
829
- config_set(section, name, buffer);
830
-
831
- return value;
832
-}
833
-
834
-int config_set_boolean(const char *section, const char *name, int value)
835
-{
836
- char *s;
837
- if(value) s = "yes";
838
- else s = "no";
839
-
840
- config_set(section, name, s);
841
-
842
- return value;
843
-}
844
-
845
-
846
-// ----------------------------------------------------------------------------
847
-// chart types
848
-
849
-#define CHART_TYPE_LINE_NAME "line"
850
-#define CHART_TYPE_AREA_NAME "area"
851
-#define CHART_TYPE_STACKED_NAME "stacked"
852
-
853
-
854
-#define CHART_TYPE_LINE 0
855
-#define CHART_TYPE_AREA 1
856
-#define CHART_TYPE_STACKED 2
857
-
858
-int chart_type_id(const char *name)
859
-{
860
- if(strcmp(name, CHART_TYPE_AREA_NAME) == 0) return CHART_TYPE_AREA;
861
- if(strcmp(name, CHART_TYPE_STACKED_NAME) == 0) return CHART_TYPE_STACKED;
862
- if(strcmp(name, CHART_TYPE_LINE_NAME) == 0) return CHART_TYPE_LINE;
863
- return CHART_TYPE_LINE;
864
-}
865
-
866
-const char *chart_type_name(int chart_type)
867
-{
868
- static char line[] = CHART_TYPE_LINE_NAME;
869
- static char area[] = CHART_TYPE_AREA_NAME;
870
- static char stacked[] = CHART_TYPE_STACKED_NAME;
871
-
872
- switch(chart_type) {
873
- case CHART_TYPE_LINE:
874
- return line;
875
-
876
- case CHART_TYPE_AREA:
877
- return area;
878
-
879
- case CHART_TYPE_STACKED:
880
- return stacked;
881
- }
882
- return line;
883
-}
884
-
885
-
886
-// ----------------------------------------------------------------------------
887
-// algorithms types
888
-
889
-#define RRD_DIMENSION_ABSOLUTE_NAME "absolute"
890
-#define RRD_DIMENSION_INCREMENTAL_NAME "incremental"
891
-#define RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL_NAME "percentage-of-incremental-row"
892
-#define RRD_DIMENSION_PCENT_OVER_ROW_TOTAL_NAME "percentage-of-absolute-row"
893
-
894
-#define RRD_DIMENSION_ABSOLUTE 0
895
-#define RRD_DIMENSION_INCREMENTAL 1
896
-#define RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL 2
897
-#define RRD_DIMENSION_PCENT_OVER_ROW_TOTAL 3
898
-
899
-int algorithm_id(const char *name)
900
-{
901
- if(strcmp(name, RRD_DIMENSION_ABSOLUTE_NAME) == 0) return RRD_DIMENSION_ABSOLUTE;
902
- if(strcmp(name, RRD_DIMENSION_INCREMENTAL_NAME) == 0) return RRD_DIMENSION_INCREMENTAL;
903
- if(strcmp(name, RRD_DIMENSION_PCENT_OVER_ROW_TOTAL_NAME) == 0) return RRD_DIMENSION_PCENT_OVER_ROW_TOTAL;
904
- if(strcmp(name, RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL_NAME) == 0) return RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL;
905
- return RRD_DIMENSION_ABSOLUTE;
906
-}
907
-
908
-const char *algorithm_name(int chart_type)
909
-{
910
- static char absolute[] = RRD_DIMENSION_ABSOLUTE_NAME;
911
- static char incremental[] = RRD_DIMENSION_INCREMENTAL_NAME;
912
- static char percentage_of_absolute_row[] = RRD_DIMENSION_PCENT_OVER_ROW_TOTAL_NAME;
913
- static char percentage_of_incremental_row[] = RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL_NAME;
914
-
915
- switch(chart_type) {
916
- case RRD_DIMENSION_ABSOLUTE:
917
- return absolute;
918
-
919
- case RRD_DIMENSION_INCREMENTAL:
920
- return incremental;
921
-
922
- case RRD_DIMENSION_PCENT_OVER_ROW_TOTAL:
923
- return percentage_of_absolute_row;
924
-
925
- case RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL:
926
- return percentage_of_incremental_row;
927
- }
928
- return absolute;
929
-}
930
-
931
-
932
-// ----------------------------------------------------------------------------
933
-// FAST NUMBER TO STRING
934
-
935
-static void strreverse(char* begin, char* end)
936
-{
937
- char aux;
938
- while (end > begin)
939
- aux = *end, *end-- = *begin, *begin++ = aux;
940
-}
941
-
942
-
943
-// ----------------------------------------------------------------------------
944
-// mmap() wrapper
945
-
946
-#define NETDATA_MEMORY_MODE_RAM_NAME "ram"
947
-#define NETDATA_MEMORY_MODE_MAP_NAME "map"
948
-#define NETDATA_MEMORY_MODE_SAVE_NAME "save"
949
-
950
-#define NETDATA_MEMORY_MODE_RAM 0
951
-#define NETDATA_MEMORY_MODE_MAP 1
952
-#define NETDATA_MEMORY_MODE_SAVE 2
953
-
954
-int memory_mode = NETDATA_MEMORY_MODE_SAVE;
955
-
956
-const char *memory_mode_name(int id)
957
-{
958
- static const char ram[] = NETDATA_MEMORY_MODE_RAM_NAME;
959
- static const char map[] = NETDATA_MEMORY_MODE_MAP_NAME;
960
- static const char save[] = NETDATA_MEMORY_MODE_SAVE_NAME;
961
-
962
- switch(id) {
963
- case NETDATA_MEMORY_MODE_RAM:
964
- return ram;
965
-
966
- case NETDATA_MEMORY_MODE_MAP:
967
- return map;
968
-
969
- case NETDATA_MEMORY_MODE_SAVE:
970
- default:
971
- return save;
972
- }
973
-
974
- return save;
975
-}
976
-
977
-int memory_mode_id(const char *name)
978
-{
979
- if(!strcmp(name, NETDATA_MEMORY_MODE_RAM_NAME))
980
- return NETDATA_MEMORY_MODE_RAM;
981
- else if(!strcmp(name, NETDATA_MEMORY_MODE_MAP_NAME))
982
- return NETDATA_MEMORY_MODE_MAP;
983
-
984
- return NETDATA_MEMORY_MODE_SAVE;
985
-}
986
-
987
-void *mymmap(const char *filename, unsigned long size)
988
-{
989
- if(memory_mode == NETDATA_MEMORY_MODE_RAM) return NULL;
990
-
991
- int fd, flags;
992
- void *mem = NULL;
993
-
994
- if(memory_mode == NETDATA_MEMORY_MODE_MAP)
995
- flags = MAP_SHARED;
996
- else
997
- flags = MAP_PRIVATE;
998
-
999
- errno = 0;
1000
- fd = open(filename, O_RDWR|O_CREAT|O_NOATIME, 0664);
1001
- if(fd != -1) {
1002
- if(lseek(fd, size, SEEK_SET) == (long)size) {
1003
- if(write(fd, "", 1) == 1) {
1004
-
1005
- if(ftruncate(fd, size))
1006
- error("Cannot truncate file '%s' to size %ld. Will use the larger file.", filename, size);
1007
-
1008
- mem = mmap(NULL, size, PROT_READ|PROT_WRITE, flags, fd, 0);
1009
- if(mem) {
1010
- if(madvise(mem, size, MADV_SEQUENTIAL|MADV_DONTFORK|MADV_WILLNEED) != 0)
1011
- error("Cannot advise the kernel about the memory usage of file '%s'.", filename);
1012
- }
1013
- }
1014
- else error("Cannot write to file '%s' at position %ld.", filename, size);
1015
- }
1016
- else error("Cannot seek file '%s' to size %ld.", filename, size);
1017
-
1018
- close(fd);
1019
- }
1020
- else error("Cannot create/open file '%s'.", filename);
1021
-
1022
- return mem;
1023
-}
1024
-
1025
-int savememory(const char *filename, void *mem, unsigned long size)
1026
-{
1027
- char tmpfilename[FILENAME_MAX + 1];
1028
-
1029
- snprintf(tmpfilename, FILENAME_MAX, "%s.%ld.tmp", filename, (long)getpid());
1030
-
1031
- int fd = open(tmpfilename, O_RDWR|O_CREAT|O_NOATIME, 0664);
1032
- if(fd < 0) {
1033
- error("Cannot create/open file '%s'.", filename);
1034
- return -1;
1035
- }
1036
-
1037
- if(write(fd, mem, size) != (long)size) {
1038
- error("Cannot write to file '%s' %ld bytes.", filename, (long)size);
1039
- close(fd);
1040
- return -1;
1041
- }
1042
-
1043
- close(fd);
1044
-
1045
- int ret = 0;
1046
- if(rename(tmpfilename, filename)) {
1047
- error("Cannot rename '%s' to '%s'", tmpfilename, filename);
1048
- ret = -1;
1049
- }
1050
-
1051
- return ret;
1052
-}
1053
-
1054
-
1055
-// ----------------------------------------------------------------------------
1056
-// RRD STATS
1057
-
1058
-#define RRD_STATS_NAME_MAX 1024
1059
-
1060
-typedef long double calculated_number;
1061
-#define CALCULATED_NUMBER_FORMAT "%0.7Lf"
1062
-//typedef long long calculated_number;
1063
-//#define CALCULATED_NUMBER_FORMAT "%lld"
1064
-
1065
-typedef long long collected_number;
1066
-#define COLLECTED_NUMBER_FORMAT "%lld"
1067
-
1068
-typedef long long total_number;
1069
-#define TOTAL_NUMBER_FORMAT "%lld"
1070
-
1071
-typedef int32_t storage_number;
1072
-typedef uint32_t ustorage_number;
1073
-#define STORAGE_NUMBER_FORMAT "%d"
1074
-
1075
-storage_number pack_storage_number(calculated_number value)
1076
-{
1077
- storage_number r = 0;
1078
- if(!value) return r;
1079
-
1080
- // bit 32 = sign
1081
- // bit 31 = 0:divide, 1:multiply
1082
- // bit 30, 29, 28 = (multiplier or divider) 0-7
1083
- // bit 27 to 25 = reserved for flags
1084
- // bit 24 to bit 1 = the value
1085
-
1086
- storage_number sign = 0, exp = 0, mul;
1087
- int m = 0;
1088
- calculated_number n = value;
1089
-
1090
- if(n < 0) {
1091
- sign = 1;
1092
- n = -n;
1093
- }
1094
-
1095
- while(m < 7 && n > (calculated_number)0x00ffffff) {
1096
- n /= 10;
1097
- m++;
1098
- }
1099
- while(m > -7 && n < (calculated_number)0x00199999) {
1100
- n *= 10;
1101
- m--;
1102
- }
1103
-
1104
- if(m <= 0) {
1105
- exp = 0;
1106
- m = -m;
1107
- }
1108
- else exp = 1;
1109
-
1110
- if(n > (calculated_number)0x00ffffff) {
1111
- error("Number " CALCULATED_NUMBER_FORMAT " is too big.", value);
1112
- n = (calculated_number)0x00ffffff;
1113
- }
1114
-
1115
- mul = m;
1116
-
1117
- r = (sign << 31) + (exp << 30) + (mul << 27) + n;
1118
- // fprintf(stderr, "PACK: %08X, sign = %d, exp = %d, mul = %d, n = " CALCULATED_NUMBER_FORMAT "\n", r, sign, exp, mul, n);
1119
-
1120
- return r;
1121
-}
1122
-
1123
-calculated_number unpack_storage_number(storage_number value)
1124
-{
1125
- if(!value) return 0;
1126
-
1127
- int sign = 0;
1128
- int exp = 0;
1129
-
1130
- if(value & (1 << 31)) {
1131
- sign = 1;
1132
- value ^= 1 << 31;
1133
- }
1134
-
1135
- if(value & (1 << 30)) {
1136
- exp = 1;
1137
- value ^= 1 << 30;
1138
- }
1139
-
1140
- int mul = value >> 27;
1141
- value ^= mul << 27;
1142
-
1143
- calculated_number n = value;
1144
-
1145
- // fprintf(stderr, "UNPACK: %08X, sign = %d, exp = %d, mul = %d, n = " CALCULATED_NUMBER_FORMAT "\n", value, sign, exp, mul, n);
1146
-
1147
- while(mul > 0) {
1148
- if(exp) n *= 10;
1149
- else n /= 10;
1150
- mul--;
1151
- }
1152
-
1153
- if(sign) n = -n;
1154
- return n;
1155
-}
1156
-
1157
-
1158
-#define RRD_STATS_MAGIC "NETDATA CACHE STATS FILE V009"
1159
-#define RRD_DIMENSION_MAGIC "NETDATA CACHE DIMENSION FILE V009"
1160
-
1161
-struct rrd_dimension {
1162
- char magic[sizeof(RRD_DIMENSION_MAGIC) + 1]; // our magic
1163
- char id[RRD_STATS_NAME_MAX + 1]; // the id of this dimension (for internal identification)
1164
- char *name; // the name of this dimension (as presented to user)
1165
- char cache_file[FILENAME_MAX+1];
1166
-
1167
- unsigned long hash; // a simple hash on the id, to speed up searching
1168
- // we first compare hashes, and only if the hashes are equal we do string comparisons
1169
-
1170
- long entries; // how many entries this dimension has
1171
- // this should be the same to the entries of the data set
1172
-
1173
- long current_entry; // the entry that is currently being updated
1174
- int update_every; // every how many seconds is this updated?
1175
-
1176
- int hidden; // if set to non zero, this dimension will not be sent to the client
1177
- int mapped; // 1 if the file is mapped
1178
- unsigned long memsize; // the memory allocated for this dimension
1179
-
1180
- int algorithm;
1181
- long multiplier;
1182
- long divisor;
1183
-
1184
- struct timeval last_collected_time; // when was this dimension last updated
1185
- // this is only used to detect un-updated dimensions
1186
- // which are removed after some time
1187
-
1188
- calculated_number calculated_value;
1189
- calculated_number last_calculated_value;
1190
-
1191
- collected_number collected_value; // the value collected at this round
1192
- collected_number last_collected_value; // the value that was collected at the last round
1193
-
1194
- struct rrd_dimension *next; // linking of dimensions within the same data set
1195
-
1196
- storage_number values[]; // the array of values - THIS HAS TO BE THE LAST MEMBER
1197
-};
1198
-typedef struct rrd_dimension RRD_DIMENSION;
1199
-
1200
-struct rrd_stats {
1201
- char magic[sizeof(RRD_STATS_MAGIC) + 1]; // our magic
1202
-
1203
- char id[RRD_STATS_NAME_MAX + 1]; // id of the data set
1204
- char *name; // name of the data set
1205
- char *cache_dir; // the directory to store dimension maps
1206
- char cache_file[FILENAME_MAX+1];
1207
-
1208
- char *type; // the type of graph RRD_TYPE_* (a category, for determining graphing options)
1209
- char *family; // the family of this data set (for grouping them together)
1210
- char *title; // title shown to user
1211
- char *units; // units of measurement
1212
-
1213
- pthread_rwlock_t rwlock;
1214
- unsigned long counter; // the number of times we added values to this rrd
1215
- unsigned long counter_done; // the number of times we added values to this rrd
1216
-
1217
- int mapped; // if set to 1, this is memory mapped
1218
- unsigned long memsize; // how much mem we have allocated for this (without dimensions)
1219
-
1220
- unsigned long hash_name; // a simple hash on the name
1221
- unsigned long hash; // a simple hash on the id, to speed up searching
1222
- // we first compare hashes, and only if the hashes are equal we do string comparisons
1223
-
1224
- long priority;
1225
-
1226
- long entries; // total number of entries in the data set
1227
- long current_entry; // the entry that is currently being updated
1228
- // it goes around in a round-robin fashion
1229
-
1230
- int update_every; // every how many seconds is this updated?
1231
- unsigned long long first_entry_t; // the timestamp (in microseconds) of the oldest entry in the db
1232
- struct timeval last_updated; // when this data set was last updated (updated every time the rrd_stats_done() function)
1233
- struct timeval last_collected_time; //
1234
- unsigned long long usec_since_last_update;
1235
-
1236
- total_number collected_total;
1237
- total_number last_collected_total;
1238
-
1239
- int chart_type;
1240
- int debug;
1241
- int enabled;
1242
- int isdetail; // if set, the data set should be considered as a detail of another
1243
- // (the master data set should be the one that has the same family and is not detail)
1244
-
1245
- RRD_DIMENSION *dimensions; // the actual data for every dimension
1246
-
1247
- struct rrd_stats *next; // linking of rrd stats
1248
-};
1249
-typedef struct rrd_stats RRD_STATS;
1250
-
1251
-RRD_STATS *root = NULL;
1252
-pthread_rwlock_t root_rwlock = PTHREAD_RWLOCK_INITIALIZER;
1253
-
1254
-char *rrd_stats_strncpy_name(char *to, const char *from, int length)
1255
-{
1256
- int i;
1257
- for(i = 0; i < length && from[i] ;i++) {
1258
- if(from[i] == '.' || isalpha(from[i]) || isdigit(from[i])) to[i] = from[i];
1259
- else to[i] = '_';
1260
- }
1261
- if(i < length) to[i] = '\0';
1262
- to[length - 1] = '\0';
1263
-
1264
- return to;
1265
-}
1266
-
1267
-void rrd_stats_set_name(RRD_STATS *st, const char *name)
1268
-{
1269
- char b[CONFIG_MAX_VALUE + 1];
1270
- char n[RRD_STATS_NAME_MAX + 1];
1271
-
1272
- snprintf(n, RRD_STATS_NAME_MAX, "%s.%s", st->type, name);
1273
- rrd_stats_strncpy_name(b, n, CONFIG_MAX_VALUE);
1274
- st->name = config_get(st->id, "name", b);
1275
- st->hash_name = simple_hash(st->name);
1276
-}
1277
-
1278
-char *rrd_stats_cache_dir(const char *id)
1279
-{
1280
- char *ret = NULL;
1281
-
1282
- static char *cache_dir = NULL;
1283
- if(!cache_dir) cache_dir = config_get("global", "database directory", "cache");
1284
-
1285
- char b[FILENAME_MAX + 1];
1286
- char n[FILENAME_MAX + 1];
1287
- rrd_stats_strncpy_name(b, id, FILENAME_MAX);
1288
-
1289
- snprintf(n, FILENAME_MAX, "%s/%s", cache_dir, b);
1290
- ret = config_get(id, "database directory", n);
1291
-
1292
- if(memory_mode == NETDATA_MEMORY_MODE_MAP || memory_mode == NETDATA_MEMORY_MODE_SAVE) {
1293
- int r = mkdir(ret, 0775);
1294
- if(r != 0 && errno != EEXIST)
1295
- error("Cannot create directory '%s'", ret);
1296
- }
1297
-
1298
- return ret;
1299
-}
1300
-
1301
-void rrd_stats_reset(RRD_STATS *st)
1302
-{
1303
- st->last_collected_time.tv_sec = 0;
1304
- st->last_collected_time.tv_usec = 0;
1305
- st->current_entry = 0;
1306
- st->counter_done = 0;
1307
-
1308
- RRD_DIMENSION *rd;
1309
- for(rd = st->dimensions; rd ; rd = rd->next) {
1310
- rd->last_collected_time.tv_sec = 0;
1311
- rd->last_collected_time.tv_usec = 0;
1312
- rd->current_entry = 0;
1313
- }
1314
-}
1315
-
1316
-RRD_STATS *rrd_stats_create(const char *type, const char *id, const char *name, const char *family, const char *title, const char *units, long priority, int update_every, int chart_type)
1317
-{
1318
- if(!id || !id[0]) {
1319
- fatal("Cannot create rrd stats without an id.");
1320
- return NULL;
1321
- }
1322
-
1323
- char fullid[RRD_STATS_NAME_MAX + 1];
1324
- char fullfilename[FILENAME_MAX + 1];
1325
- RRD_STATS *st;
1326
-
1327
- snprintf(fullid, RRD_STATS_NAME_MAX, "%s.%s", type, id);
1328
-
1329
- long entries = config_get_number(fullid, "history", save_history);
1330
- if(entries < 5) entries = config_set_number(fullid, "history", 5);
1331
- if(entries > HISTORY_MAX) entries = config_set_number(fullid, "history", HISTORY_MAX);
1332
-
1333
- int enabled = config_get_boolean(fullid, "enabled", 1);
1334
- if(!enabled) entries = 5;
1335
-
1336
- unsigned long size = sizeof(RRD_STATS);
1337
- char *cache_dir = rrd_stats_cache_dir(fullid);
1338
-
1339
- debug(D_RRD_STATS, "Creating RRD_STATS for '%s.%s'.", type, id);
1340
-
1341
- snprintf(fullfilename, FILENAME_MAX, "%s/main.db", cache_dir);
1342
- st = (RRD_STATS *)mymmap(fullfilename, size);
1343
- if(st) {
1344
- if(strcmp(st->magic, RRD_STATS_MAGIC) != 0) {
1345
- errno = 0;
1346
- error("File %s does not have our version. Clearing it.", fullfilename);
1347
- bzero(st, size);
1348
- }
1349
- else if(strcmp(st->id, fullid) != 0) {
1350
- errno = 0;
1351
- error("File %s does not have our id. Unmapping it.", fullfilename);
1352
- munmap(st, size);
1353
- st = NULL;
1354
- }
1355
- else if(st->memsize != size || st->entries != entries) {
1356
- errno = 0;
1357
- error("File %s does not have the desired size. Clearing it.", fullfilename);
1358
- bzero(st, size);
1359
- }
1360
- else if(st->update_every != update_every) {
1361
- errno = 0;
1362
- error("File %s does not have the desired update frequency. Clearing it.", fullfilename);
1363
- bzero(st, size);
1364
- }
1365
- }
1366
-
1367
- if(st) {
1368
- st->name = NULL;
1369
- st->type = NULL;
1370
- st->family = NULL;
1371
- st->title = NULL;
1372
- st->units = NULL;
1373
- st->dimensions = NULL;
1374
- st->next = NULL;
1375
- st->mapped = memory_mode;
1376
- }
1377
- else {
1378
- st = calloc(1, size);
1379
- if(!st) {
1380
- fatal("Cannot allocate memory for RRD_STATS %s.%s", type, id);
1381
- return NULL;
1382
- }
1383
- st->mapped = NETDATA_MEMORY_MODE_RAM;
1384
- }
1385
- st->memsize = size;
1386
- st->entries = entries;
1387
- st->update_every = update_every;
1388
-
1389
- strcpy(st->cache_file, fullfilename);
1390
- strcpy(st->magic, RRD_STATS_MAGIC);
1391
-
1392
- strcpy(st->id, fullid);
1393
- st->hash = simple_hash(st->id);
1394
-
1395
- st->cache_dir = cache_dir;
1396
-
1397
- st->family = config_get(st->id, "family", family?family:st->id);
1398
- st->units = config_get(st->id, "units", units?units:"");
1399
- st->type = config_get(st->id, "type", type);
1400
- st->chart_type = chart_type_id(config_get(st->id, "chart type", chart_type_name(chart_type)));
1401
-
1402
- if(name && *name) rrd_stats_set_name(st, name);
1403
- else rrd_stats_set_name(st, id);
1404
-
1405
- {
1406
- char varvalue[CONFIG_MAX_VALUE + 1];
1407
- snprintf(varvalue, CONFIG_MAX_VALUE, "%s (%s)", title?title:"", st->name);
1408
- st->title = config_get(st->id, "title", varvalue);
1409
- }
1410
-
1411
- st->priority = config_get_number(st->id, "priority", priority);
1412
- st->enabled = enabled;
1413
-
1414
- st->isdetail = 0;
1415
- st->debug = 0;
1416
-
1417
- st->last_collected_time.tv_sec = 0;
1418
- st->last_collected_time.tv_usec = 0;
1419
- st->counter_done = 0;
1420
-
1421
- pthread_rwlock_init(&st->rwlock, NULL);
1422
- pthread_rwlock_wrlock(&root_rwlock);
1423
-
1424
- st->next = root;
1425
- root = st;
1426
-
1427
- pthread_rwlock_unlock(&root_rwlock);
1428
-
1429
- return(st);
1430
-}
1431
-
1432
-RRD_DIMENSION *rrd_stats_dimension_add(RRD_STATS *st, const char *id, const char *name, long multiplier, long divisor, int algorithm)
1433
-{
1434
- char filename[FILENAME_MAX + 1];
1435
- char fullfilename[FILENAME_MAX + 1];
1436
-
1437
- char varname[CONFIG_MAX_NAME + 1];
1438
- RRD_DIMENSION *rd;
1439
- unsigned long size = sizeof(RRD_DIMENSION) + (st->entries * sizeof(storage_number));
1440
-
1441
- debug(D_RRD_STATS, "Adding dimension '%s/%s'.", st->id, id);
1442
-
1443
- rrd_stats_strncpy_name(filename, id, FILENAME_MAX);
1444
- snprintf(fullfilename, FILENAME_MAX, "%s/%s.db", st->cache_dir, filename);
1445
- rd = (RRD_DIMENSION *)mymmap(fullfilename, size);
1446
- if(rd) {
1447
- struct timeval now;
1448
- gettimeofday(&now, NULL);
1449
-
1450
- if(strcmp(rd->magic, RRD_DIMENSION_MAGIC) != 0) {
1451
- errno = 0;
1452
- error("File %s does not have our version. Clearing it.", fullfilename);
1453
- bzero(rd, size);
1454
- }
1455
- else if(rd->memsize != size) {
1456
- errno = 0;
1457
- error("File %s does not have the desired size. Clearing it.", fullfilename);
1458
- bzero(rd, size);
1459
- }
1460
- else if(rd->multiplier != multiplier) {
1461
- errno = 0;
1462
- error("File %s does not have the same multiplier. Clearing it.", fullfilename);
1463
- bzero(rd, size);
1464
- }
1465
- else if(rd->divisor != divisor) {
1466
- errno = 0;
1467
- error("File %s does not have the same divisor. Clearing it.", fullfilename);
1468
- bzero(rd, size);
1469
- }
1470
- else if(rd->algorithm != algorithm) {
1471
- errno = 0;
1472
- error("File %s does not have the same algorithm. Clearing it.", fullfilename);
1473
- bzero(rd, size);
1474
- }
1475
- else if(rd->update_every != st->update_every) {
1476
- errno = 0;
1477
- error("File %s does not have the same refresh frequency. Clearing it.", fullfilename);
1478
- bzero(rd, size);
1479
- }
1480
- else if(usecdiff(&now, &rd->last_collected_time) > (rd->entries * rd->update_every * 1000000ULL)) {
1481
- errno = 0;
1482
- error("File %s is too old. Clearing it.", fullfilename);
1483
- bzero(rd, size);
1484
- }
1485
- else if(strcmp(rd->id, id) != 0) {
1486
- errno = 0;
1487
- error("File %s does not have our dimension id. Unmapping it.", fullfilename);
1488
- munmap(rd, size);
1489
- rd = NULL;
1490
- }
1491
- }
1492
-
1493
- if(rd) {
1494
- // we have a file mapped for rd
1495
- rd->mapped = memory_mode;
1496
- rd->hidden = 0;
1497
- rd->next = NULL;
1498
- rd->name = NULL;
1499
- }
1500
- else {
1501
- // if we didn't manage to get a mmap'd dimension, just create one
1502
-
1503
- rd = calloc(1, size);
1504
- if(!rd) {
1505
- fatal("Cannot allocate RRD_DIMENSION %s/%s.", st->id, id);
1506
- return NULL;
1507
- }
1508
-
1509
- rd->mapped = NETDATA_MEMORY_MODE_RAM;
1510
- }
1511
- rd->memsize = size;
1512
-
1513
- strcpy(rd->magic, RRD_DIMENSION_MAGIC);
1514
- strcpy(rd->cache_file, fullfilename);
1515
- strncpy(rd->id, id, RRD_STATS_NAME_MAX);
1516
- rd->hash = simple_hash(rd->id);
1517
-
1518
- snprintf(varname, CONFIG_MAX_NAME, "dim %s name", rd->id);
1519
- rd->name = config_get(st->id, varname, (name && *name)?name:rd->id);
1520
-
1521
- snprintf(varname, CONFIG_MAX_NAME, "dim %s algorithm", rd->id);
1522
- rd->algorithm = algorithm_id(config_get(st->id, varname, algorithm_name(algorithm)));
1523
-
1524
- snprintf(varname, CONFIG_MAX_NAME, "dim %s multiplier", rd->id);
1525
- rd->multiplier = config_get_number(st->id, varname, multiplier);
1526
-
1527
- snprintf(varname, CONFIG_MAX_NAME, "dim %s divisor", rd->id);
1528
- rd->divisor = config_get_number(st->id, varname, divisor);
1529
- if(!rd->divisor) rd->divisor = 1;
1530
-
1531
- rd->entries = st->entries;
1532
- rd->update_every = st->update_every;
1533
-
1534
- // append this dimension
1535
- if(!st->dimensions)
1536
- st->dimensions = rd;
1537
- else {
1538
- RRD_DIMENSION *td = st->dimensions;
1539
- for(; td->next; td = td->next) ;
1540
- td->next = rd;
1541
- }
1542
-
1543
- return(rd);
1544
-}
1545
-
1546
-void rrd_stats_dimension_set_name(RRD_STATS *st, RRD_DIMENSION *rd, const char *name)
1547
-{
1548
- char varname[CONFIG_MAX_NAME + 1];
1549
- snprintf(varname, CONFIG_MAX_NAME, "dim %s name", rd->id);
1550
- config_get(st->id, varname, name);
1551
-}
1552
-
1553
-void rrd_stats_dimension_free(RRD_DIMENSION *rd)
1554
-{
1555
- if(rd->next) rrd_stats_dimension_free(rd->next);
1556
- // free(rd->annotations);
1557
- if(rd->mapped == NETDATA_MEMORY_MODE_SAVE) {
1558
- debug(D_RRD_STATS, "Saving dimension '%s' to '%s'.", rd->name, rd->cache_file);
1559
- savememory(rd->cache_file, rd, rd->memsize);
1560
-
1561
- debug(D_RRD_STATS, "Unmapping dimension '%s'.", rd->name);
1562
- munmap(rd, rd->memsize);
1563
- }
1564
- else if(rd->mapped == NETDATA_MEMORY_MODE_MAP) {
1565
- debug(D_RRD_STATS, "Unmapping dimension '%s'.", rd->name);
1566
- munmap(rd, rd->memsize);
1567
- }
1568
- else {
1569
- debug(D_RRD_STATS, "Removing dimension '%s'.", rd->name);
1570
- free(rd);
1571
- }
1572
-}
1573
-
1574
-void rrd_stats_free_all(void)
1575
-{
1576
- info("Freeing all memory...");
1577
-
1578
- RRD_STATS *st;
1579
- for(st = root; st ;) {
1580
- RRD_STATS *next = st->next;
1581
-
1582
- if(st->dimensions) rrd_stats_dimension_free(st->dimensions);
1583
- st->dimensions = NULL;
1584
-
1585
- if(st->mapped == NETDATA_MEMORY_MODE_SAVE) {
1586
- debug(D_RRD_STATS, "Saving stats '%s' to '%s'.", st->name, st->cache_file);
1587
- savememory(st->cache_file, st, st->memsize);
1588
-
1589
- debug(D_RRD_STATS, "Unmapping stats '%s'.", st->name);
1590
- munmap(st, st->memsize);
1591
- }
1592
- else if(st->mapped == NETDATA_MEMORY_MODE_MAP) {
1593
- debug(D_RRD_STATS, "Unmapping stats '%s'.", st->name);
1594
- munmap(st, st->memsize);
1595
- }
1596
- else
1597
- free(st);
1598
-
1599
- st = next;
1600
- }
1601
- root = NULL;
1602
-
1603
- info("Memory cleanup completed...");
1604
-}
1605
-
1606
-void rrd_stats_save_all(void)
1607
-{
1608
- RRD_STATS *st;
1609
- RRD_DIMENSION *rd;
1610
-
1611
- pthread_rwlock_wrlock(&root_rwlock);
1612
- for(st = root; st ; st = st->next) {
1613
- pthread_rwlock_wrlock(&st->rwlock);
1614
-
1615
- if(st->mapped == NETDATA_MEMORY_MODE_SAVE) {
1616
- debug(D_RRD_STATS, "Saving stats '%s' to '%s'.", st->name, st->cache_file);
1617
- savememory(st->cache_file, st, st->memsize);
1618
- }
1619
-
1620
- for(rd = st->dimensions; rd ; rd = rd->next) {
1621
- if(rd->mapped == NETDATA_MEMORY_MODE_SAVE) {
1622
- debug(D_RRD_STATS, "Saving dimension '%s' to '%s'.", rd->name, rd->cache_file);
1623
- savememory(rd->cache_file, rd, rd->memsize);
1624
- }
1625
- }
1626
-
1627
- pthread_rwlock_unlock(&st->rwlock);
1628
- }
1629
- pthread_rwlock_unlock(&root_rwlock);
1630
-}
1631
-
1632
-
1633
-RRD_STATS *rrd_stats_find(const char *id)
1634
-{
1635
- unsigned long hash = simple_hash(id);
1636
-
1637
- pthread_rwlock_rdlock(&root_rwlock);
1638
- RRD_STATS *st = root;
1639
- for ( ; st ; st = st->next )
1640
- if(hash == st->hash)
1641
- if(strcmp(st->id, id) == 0)
1642
- break;
1643
- pthread_rwlock_unlock(&root_rwlock);
1644
-
1645
- return(st);
1646
-}
1647
-
1648
-RRD_STATS *rrd_stats_find_bytype(const char *type, const char *id)
1649
-{
1650
- char buf[RRD_STATS_NAME_MAX + 1];
1651
-
1652
- strncpy(buf, type, RRD_STATS_NAME_MAX - 1);
1653
- buf[RRD_STATS_NAME_MAX - 1] = '\0';
1654
- strcat(buf, ".");
1655
- int len = strlen(buf);
1656
- strncpy(&buf[len], id, RRD_STATS_NAME_MAX - len);
1657
- buf[RRD_STATS_NAME_MAX] = '\0';
1658
-
1659
- return(rrd_stats_find(buf));
1660
-}
1661
-
1662
-RRD_STATS *rrd_stats_find_byname(const char *name)
1663
-{
1664
- char b[CONFIG_MAX_VALUE + 1];
1665
-
1666
- rrd_stats_strncpy_name(b, name, CONFIG_MAX_VALUE);
1667
- unsigned long hash = simple_hash(b);
1668
-
1669
- pthread_rwlock_rdlock(&root_rwlock);
1670
- RRD_STATS *st = root;
1671
- for ( ; st ; st = st->next ) {
1672
- if(hash == st->hash_name && strcmp(st->name, b) == 0) break;
1673
- }
1674
- pthread_rwlock_unlock(&root_rwlock);
1675
-
1676
- return(st);
1677
-}
1678
-
1679
-RRD_DIMENSION *rrd_stats_dimension_find(RRD_STATS *st, const char *id)
1680
-{
1681
- unsigned long hash = simple_hash(id);
1682
-
1683
- RRD_DIMENSION *rd = st->dimensions;
1684
-
1685
- for ( ; rd ; rd = rd->next )
1686
- if(hash == rd->hash)
1687
- if(strcmp(rd->id, id) == 0)
1688
- break;
1689
-
1690
- return(rd);
1691
-}
1692
-
1693
-int rrd_stats_dimension_hide(RRD_STATS *st, const char *id)
1694
-{
1695
- RRD_DIMENSION *rd = rrd_stats_dimension_find(st, id);
1696
- if(!rd) {
1697
- error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id);
1698
- return 1;
1699
- }
1700
-
1701
- rd->hidden = 1;
1702
- return 0;
1703
-}
1704
-
1705
-void rrd_stats_dimension_set_by_pointer(RRD_STATS *st, RRD_DIMENSION *rd, collected_number value)
1706
-{
1707
- if(st) {;}
1708
-
1709
- gettimeofday(&rd->last_collected_time, NULL);
1710
- rd->collected_value = value;
1711
-}
1712
-
1713
-int rrd_stats_dimension_set(RRD_STATS *st, char *id, collected_number value)
1714
-{
1715
- RRD_DIMENSION *rd = rrd_stats_dimension_find(st, id);
1716
- if(!rd) {
1717
- error("Cannot find dimension with id '%s' on stats '%s' (%s).", id, st->name, st->id);
1718
- return 1;
1719
- }
1720
-
1721
- rrd_stats_dimension_set_by_pointer(st, rd, value);
1722
- return 0;
1723
-}
1724
-
1725
-void rrd_stats_next_usec(RRD_STATS *st, unsigned long long microseconds)
1726
-{
1727
- if(st->debug) debug(D_RRD_STATS, "%s: NEXT: %llu microseconds", st->name, microseconds);
1728
- st->usec_since_last_update = microseconds;
1729
-}
1730
-
1731
-void rrd_stats_next(RRD_STATS *st)
1732
-{
1733
- unsigned long long microseconds = 0;
1734
-
1735
- if(st->last_collected_time.tv_sec) {
1736
- struct timeval now;
1737
- gettimeofday(&now, NULL);
1738
- microseconds = usecdiff(&now, &st->last_collected_time);
1739
- }
1740
-
1741
- rrd_stats_next_usec(st, microseconds);
1742
-}
1743
-
1744
-void rrd_stats_next_plugins(RRD_STATS *st)
1745
-{
1746
- rrd_stats_next(st);
1747
-}
1748
-
1749
-unsigned long long rrd_stats_done(RRD_STATS *st)
1750
-{
1751
- RRD_DIMENSION *rd, *last;
1752
- int oldstate;
1753
-
1754
- if(pthread_setcancelstate(PTHREAD_CANCEL_DISABLE, &oldstate) != 0)
1755
- error("Cannot set pthread cancel state to DISABLE.");
1756
-
1757
- // a read lock is OK here
1758
- pthread_rwlock_rdlock(&st->rwlock);
1759
-
1760
- if(st->debug) debug(D_RRD_STATS, "%s: microseconds since last update: %llu", st->name, st->usec_since_last_update);
1761
-
1762
- if(!st->last_collected_time.tv_sec) gettimeofday(&st->last_collected_time, NULL);
1763
- else {
1764
- unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec + st->usec_since_last_update;
1765
- st->last_collected_time.tv_sec = ut / 1000000ULL;
1766
- st->last_collected_time.tv_usec = ut % 1000000ULL;
1767
- }
1768
-
1769
- if(!st->last_updated.tv_sec) {
1770
- unsigned long long ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec - st->usec_since_last_update;
1771
- st->last_updated.tv_sec = ut / 1000000ULL;
1772
- st->last_updated.tv_usec = ut % 1000000ULL;
1773
-
1774
- if(st->debug) debug(D_RRD_STATS, "%s: initializing last_updated to now - %llu microseconds (%0.3Lf)", st->name, st->usec_since_last_update, (long double)ut/1000000.0);
1775
- }
1776
-
1777
- unsigned long long last_ut = st->last_updated.tv_sec * 1000000ULL + st->last_updated.tv_usec;
1778
- unsigned long long now_ut = st->last_collected_time.tv_sec * 1000000ULL + st->last_collected_time.tv_usec;
1779
- unsigned long long next_ut = (st->last_updated.tv_sec + st->update_every) * 1000000ULL;
1780
-
1781
- if(st->debug) debug(D_RRD_STATS, "%s: last ut = %0.3Lf (last updated time)", st->name, (long double)last_ut/1000000.0);
1782
- if(st->debug) debug(D_RRD_STATS, "%s: now ut = %0.3Lf (current update time)", st->name, (long double)now_ut/1000000.0);
1783
- if(st->debug) debug(D_RRD_STATS, "%s: next ut = %0.3Lf (next interpolation point)", st->name, (long double)next_ut/1000000.0);
1784
-
1785
- st->counter_done++;
1786
-
1787
- // calculate totals and count the dimensions
1788
- int dimensions;
1789
- st->collected_total = 0;
1790
- for( rd = st->dimensions, dimensions = 0 ; rd ; rd = rd->next, dimensions++ )
1791
- st->collected_total += rd->collected_value;
1792
-
1793
- // process all dimensions to calculate their values
1794
- // based on the collected figures only
1795
- // at this stage we do not interpolate anything
1796
- for( rd = st->dimensions ; rd ; rd = rd->next ) {
1797
- if(st->debug) debug(D_RRD_STATS, "%s/%s: "
1798
- " last_collected_value = " COLLECTED_NUMBER_FORMAT
1799
- " collected_value = " COLLECTED_NUMBER_FORMAT
1800
- " last_calculated_value = " CALCULATED_NUMBER_FORMAT
1801
- " calculated_value = " CALCULATED_NUMBER_FORMAT
1802
- , st->id, rd->name
1803
- , rd->last_collected_value
1804
- , rd->collected_value
1805
- , rd->last_calculated_value
1806
- , rd->calculated_value
1807
- );
1808
-
1809
- switch(rd->algorithm) {
1810
- case RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL:
1811
- // the percentage of the current increment
1812
- // over the increment of all dimensions together
1813
- if(st->collected_total == st->last_collected_total) rd->calculated_value = 0;
1814
- else rd->calculated_value =
1815
- (calculated_number)100
1816
- * (calculated_number)(rd->collected_value - rd->last_collected_value)
1817
- / (calculated_number)(st->collected_total - st->last_collected_total);
1818
-
1819
- if(st->debug)
1820
- debug(D_RRD_STATS, "%s/%s: CALC PCENT-DIFF "
1821
- CALCULATED_NUMBER_FORMAT " = 100"
1822
- " * (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")"
1823
- " / (" COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT ")"
1824
- , st->id, rd->name
1825
- , rd->calculated_value
1826
- , rd->collected_value, rd->last_collected_value
1827
- , st->collected_total, st->last_collected_total
1828
- );
1829
- break;
1830
-
1831
- case RRD_DIMENSION_PCENT_OVER_ROW_TOTAL:
1832
- if(!st->collected_total) rd->calculated_value = 0;
1833
- else
1834
- // the percentage of the current value
1835
- // over the total of all dimensions
1836
- rd->calculated_value =
1837
- (calculated_number)100
1838
- * (calculated_number)rd->collected_value
1839
- / (calculated_number)st->collected_total;
1840
-
1841
- if(st->debug)
1842
- debug(D_RRD_STATS, "%s/%s: CALC PCENT-ROW "
1843
- CALCULATED_NUMBER_FORMAT " = 100"
1844
- " * " COLLECTED_NUMBER_FORMAT
1845
- " / " COLLECTED_NUMBER_FORMAT
1846
- , st->id, rd->name
1847
- , rd->calculated_value
1848
- , rd->collected_value
1849
- , st->collected_total
1850
- );
1851
- break;
1852
-
1853
- case RRD_DIMENSION_INCREMENTAL:
1854
- // if the new is smaller than the old (an overflow, or reset), set the old equal to the new
1855
- // to reset the calculation (it will give zero as the calculation for this second)
1856
- if(rd->last_collected_value > rd->collected_value) rd->last_collected_value = rd->collected_value;
1857
-
1858
- rd->calculated_value += (calculated_number)(rd->collected_value - rd->last_collected_value);
1859
-
1860
- if(st->debug)
1861
- debug(D_RRD_STATS, "%s/%s: CALC INC "
1862
- CALCULATED_NUMBER_FORMAT " += "
1863
- COLLECTED_NUMBER_FORMAT " - " COLLECTED_NUMBER_FORMAT
1864
- , st->id, rd->name
1865
- , rd->calculated_value
1866
- , rd->collected_value, rd->last_collected_value
1867
- );
1868
- break;
1869
-
1870
- case RRD_DIMENSION_ABSOLUTE:
1871
- rd->calculated_value = (calculated_number)rd->collected_value;
1872
-
1873
- if(st->debug)
1874
- debug(D_RRD_STATS, "%s/%s: CALC ABS/ABS-NO-IN "
1875
- CALCULATED_NUMBER_FORMAT " = "
1876
- COLLECTED_NUMBER_FORMAT
1877
- , st->id, rd->name
1878
- , rd->calculated_value
1879
- , rd->collected_value
1880
- );
1881
- break;
1882
-
1883
- default:
1884
- // make the default zero, to make sure
1885
- // it gets noticed when we add new types
1886
- rd->calculated_value = 0;
1887
-
1888
- if(st->debug)
1889
- debug(D_RRD_STATS, "%s/%s: CALC "
1890
- CALCULATED_NUMBER_FORMAT " = 0"
1891
- , st->id, rd->name
1892
- , rd->calculated_value
1893
- );
1894
- break;
1895
- }
1896
- }
1897
- // at this point we have all the calculated values ready
1898
-
1899
- if(st->counter_done == 1 || next_ut > now_ut) {
1900
- // we don't have any usable data yet
1901
- if(st->debug) debug(D_RRD_STATS, "%s: Skipping collected values (usec since last update = %llu, counter_done = %lu)", st->name, st->usec_since_last_update, st->counter_done);
1902
-
1903
- for( rd = st->dimensions; rd ; rd = rd->next ) {
1904
- rd->last_calculated_value = rd->calculated_value;
1905
- rd->last_collected_value = rd->collected_value;
1906
-
1907
- switch(rd->algorithm) {
1908
- case RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL:
1909
- case RRD_DIMENSION_INCREMENTAL:
1910
- if(!st->usec_since_last_update) rd->calculated_value = 0;
1911
- // keep the previous values
1912
- // the next time, a new incremental total will be calculated
1913
- break;
1914
- }
1915
-
1916
- rd->collected_value = 0;
1917
- }
1918
- st->last_collected_total = st->collected_total;
1919
-
1920
- pthread_rwlock_unlock(&st->rwlock);
1921
- if(pthread_setcancelstate(oldstate, NULL) != 0)
1922
- error("Cannot set pthread cancel state to RESTORE (%d).", oldstate);
1923
-
1924
- return(st->usec_since_last_update);
1925
- }
1926
-
1927
- // it is now time to interpolate values on a second boundary
1928
- unsigned long long first_ut = last_ut;
1929
- for( ; next_ut <= now_ut ; next_ut += st->update_every * 1000000ULL ) {
1930
- if(st->debug) debug(D_RRD_STATS, "%s: last ut = %0.3Lf (last updated time)", st->name, (long double)last_ut/1000000.0);
1931
- if(st->debug) debug(D_RRD_STATS, "%s: next ut = %0.3Lf (next interpolation point)", st->name, (long double)next_ut/1000000.0);
1932
-
1933
- st->last_updated.tv_sec = next_ut / 1000000ULL;
1934
- st->last_updated.tv_usec = 0;
1935
-
1936
- for( rd = st->dimensions ; rd ; rd = rd->next ) {
1937
- calculated_number new_value;
1938
-
1939
- switch(rd->algorithm) {
1940
- case RRD_DIMENSION_INCREMENTAL:
1941
- new_value = (calculated_number)
1942
- ( rd->calculated_value
1943
- * (calculated_number)(next_ut - last_ut)
1944
- / (calculated_number)(now_ut - last_ut)
1945
- );
1946
-
1947
- if(st->debug)
1948
- debug(D_RRD_STATS, "%s/%s: CALC2 INC "
1949
- CALCULATED_NUMBER_FORMAT " = "
1950
- CALCULATED_NUMBER_FORMAT
1951
- " * %llu"
1952
- " / %llu"
1953
- , st->id, rd->name
1954
- , new_value
1955
- , rd->calculated_value
1956
- , (unsigned long long)(next_ut - last_ut)
1957
- , (unsigned long long)(now_ut - last_ut)
1958
- );
1959
-
1960
- rd->calculated_value -= new_value;
1961
- break;
1962
-
1963
- case RRD_DIMENSION_ABSOLUTE:
1964
- case RRD_DIMENSION_PCENT_OVER_ROW_TOTAL:
1965
- case RRD_DIMENSION_PCENT_OVER_DIFF_TOTAL:
1966
- default:
1967
- new_value = (calculated_number)
1968
- ( ( (rd->calculated_value - rd->last_calculated_value)
1969
- * (calculated_number)(next_ut - first_ut)
1970
- / (calculated_number)(now_ut - first_ut)
1971
- )
1972
- + rd->last_calculated_value
1973
- );
1974
-
1975
- if(st->debug)
1976
- debug(D_RRD_STATS, "%s/%s: CALC2 DEF "
1977
- CALCULATED_NUMBER_FORMAT " = ((("
1978
- "(" CALCULATED_NUMBER_FORMAT " - " CALCULATED_NUMBER_FORMAT ")"
1979
- " * %llu"
1980
- " / %llu) + " CALCULATED_NUMBER_FORMAT
1981
- , st->id, rd->name
1982
- , new_value
1983
- , rd->calculated_value, rd->last_calculated_value
1984
- , (next_ut - first_ut)
1985
- , (now_ut - first_ut), rd->last_calculated_value
1986
- );
1987
-
1988
- if(next_ut + st->update_every * 1000000ULL > now_ut) rd->calculated_value = new_value;
1989
- break;
1990
-
1991
- }
1992
-
1993
-
1994
- rd->values[st->current_entry] = pack_storage_number(
1995
- new_value
1996
- * (calculated_number)rd->multiplier
1997
- / (calculated_number)rd->divisor
1998
- );
1999
-
2000
- if(st->debug)
2001
- debug(D_RRD_STATS, "%s/%s: STORE[%ld] "
2002
- CALCULATED_NUMBER_FORMAT " = " CALCULATED_NUMBER_FORMAT
2003
- " * %ld"
2004
- " / %ld"
2005
- , st->id, rd->name
2006
- , st->current_entry
2007
- , unpack_storage_number(rd->values[st->current_entry]), new_value
2008
- , rd->multiplier
2009
- , rd->divisor
2010
- );
2011
- }
2012
-
2013
- if(st->first_entry_t && st->counter >= (unsigned long long)st->entries) {
2014
- // the db is overwriting values
2015
- // add the value we will overwrite
2016
- st->first_entry_t += st->update_every * 1000000ULL;
2017
- }
2018
-
2019
- st->counter++;
2020
- st->current_entry = ((st->current_entry + 1) >= st->entries) ? 0 : st->current_entry + 1;
2021
- if(!st->first_entry_t) st->first_entry_t = next_ut;
2022
- last_ut = next_ut;
2023
- }
2024
-
2025
- for( rd = st->dimensions; rd ; rd = rd->next ) {
2026
- rd->last_collected_value = rd->collected_value;
2027
- rd->last_calculated_value = rd->calculated_value;
2028
- rd->collected_value = 0;
2029
- }
2030
- st->last_collected_total = st->collected_total;
2031
-
2032
- // ALL DONE ABOUT THE DATA UPDATE
2033
- // --------------------------------------------------------------------
2034
-
2035
-
2036
- // find if there are any obsolete dimensions (not updated recently)
2037
- for( rd = st->dimensions; rd ; rd = rd->next )
2038
- if((rd->last_collected_time.tv_sec + (10 * st->update_every)) < st->last_collected_time.tv_sec)
2039
- break;
2040
-
2041
- if(rd) {
2042
- // there is dimension to free
2043
- // upgrade our read lock to a write lock
2044
- pthread_rwlock_unlock(&st->rwlock);
2045
- pthread_rwlock_wrlock(&st->rwlock);
2046
-
2047
- for( rd = st->dimensions, last = NULL ; rd ; ) {
2048
- if((rd->last_collected_time.tv_sec + (10 * st->update_every)) < st->last_collected_time.tv_sec) { // remove it only it is not updated in 10 seconds
2049
- debug(D_RRD_STATS, "Removing obsolete dimension '%s' (%s) of '%s' (%s).", rd->name, rd->id, st->name, st->id);
2050
-
2051
- if(!last) {
2052
- st->dimensions = rd->next;
2053
- rd->next = NULL;
2054
- rrd_stats_dimension_free(rd);
2055
- rd = st->dimensions;
2056
- continue;
2057
- }
2058
- else {
2059
- last->next = rd->next;
2060
- rd->next = NULL;
2061
- rrd_stats_dimension_free(rd);
2062
- rd = last->next;
2063
- continue;
2064
- }
2065
- }
2066
-
2067
- last = rd;
2068
- rd = rd->next;
2069
- }
2070
-
2071
- if(!st->dimensions) st->enabled = 0;
2072
- }
2073
-
2074
- pthread_rwlock_unlock(&st->rwlock);
2075
-
2076
- if(pthread_setcancelstate(oldstate, NULL) != 0)
2077
- error("Cannot set pthread cancel state to RESTORE (%d).", oldstate);
2078
-
2079
- return(st->usec_since_last_update);
2080
-}
2081
-
2082
-
2083
-
2084
-// ----------------------------------------------------------------------------
2085
-// web buffer
2086
-
2087
-struct web_buffer {
2088
- long size; // allocation size of buffer
2089
- long bytes; // current data length in buffer
2090
- long sent; // current data length sent to output
2091
- char *buffer; // the buffer
2092
- int contenttype;
2093
- long rbytes; // if non-zero, the excepted size of ifd
2094
- time_t date; // the date this content has been generated
2095
-};
2096
-
2097
-#define web_buffer_printf(wb, args...) wb->bytes += snprintf(&wb->buffer[wb->bytes], (wb->size - wb->bytes), ##args)
2098
-#define web_buffer_reset(wb) wb->buffer[wb->bytes = 0] = '\0'
2099
-
2100
-void web_buffer_strcpy(struct web_buffer *wb, const char *txt)
2101
-{
2102
- char *buffer = wb->buffer;
2103
- long bytes = wb->bytes, size = wb->size, i = 0;
2104
-
2105
- while(txt[i] && bytes < size)
2106
- buffer[bytes++] = txt[i++];
2107
-
2108
- wb->bytes = bytes;
2109
-}
2110
-
2111
-int print_calculated_number(char *str, calculated_number value)
2112
-{
2113
- char *wstr = str;
2114
-
2115
- // make sure it is unsigned
2116
- unsigned long long uvalue = (unsigned long long)(((value < 0) ? -value : value) * (calculated_number)10000);
2117
-
2118
- // print each digit
2119
- do *wstr++ = (char)(48 + (uvalue % 10)); while(uvalue /= 10);
2120
-
2121
- // make sure we have 8 bytes at least
2122
- while((wstr - str) < 5) *wstr++ = '0';
2123
-
2124
- // put the sign back
2125
- if (value < 0) *wstr++ = '-';
2126
-
2127
- // reverse it
2128
- wstr--;
2129
- strreverse(str, wstr);
2130
-
2131
- // terminate it, one position to the right
2132
- // to let space for a dot
2133
- wstr[2] = '\0';
2134
-
2135
- int i;
2136
- for(i = 0; i < 4 ;i++) {
2137
- wstr[1] = wstr[0];
2138
- wstr--;
2139
- }
2140
- wstr[1] = '.';
2141
-
2142
- // return the buffer length
2143
- return ( (wstr - str) + 6 );
2144
-}
2145
-
2146
-void web_buffer_rrd_value(struct web_buffer *wb, calculated_number value)
2147
-{
2148
- if(wb->size - wb->bytes < 50) return;
2149
- wb->bytes += print_calculated_number(&wb->buffer[wb->bytes], value);
2150
-}
2151
-
2152
-// generate a javascript date, the fastest possible way...
2153
-void web_buffer_jsdate(struct web_buffer *wb, int year, int month, int day, int hours, int minutes, int seconds)
2154
-{
2155
- // 10 20 30 = 35
2156
- // 01234567890123456789012345678901234
2157
- // Date(2014, 04, 01, 03, 28, 20, 065)
2158
-
2159
- if(wb->size - wb->bytes < 36) return;
2160
-
2161
- char *b = &wb->buffer[wb->bytes];
2162
-
2163
- int i = 0;
2164
- b[i++]='D';
2165
- b[i++]='a';
2166
- b[i++]='t';
2167
- b[i++]='e';
2168
- b[i++]='(';
2169
- b[i++]= 48 + year / 1000; year -= (year / 1000) * 1000;
2170
- b[i++]= 48 + year / 100; year -= (year / 100) * 100;
2171
- b[i++]= 48 + year / 10;
2172
- b[i++]= 48 + year % 10;
2173
- b[i++]=',';
2174
- //b[i++]=' ';
2175
- b[i]= 48 + month / 10; if(b[i] != '0') i++;
2176
- b[i++]= 48 + month % 10;
2177
- b[i++]=',';
2178
- //b[i++]=' ';
2179
- b[i]= 48 + day / 10; if(b[i] != '0') i++;
2180
- b[i++]= 48 + day % 10;
2181
- b[i++]=',';
2182
- //b[i++]=' ';
2183
- b[i]= 48 + hours / 10; if(b[i] != '0') i++;
2184
- b[i++]= 48 + hours % 10;
2185
- b[i++]=',';
2186
- //b[i++]=' ';
2187
- b[i]= 48 + minutes / 10; if(b[i] != '0') i++;
2188
- b[i++]= 48 + minutes % 10;
2189
- b[i++]=',';
2190
- //b[i++]=' ';
2191
- b[i]= 48 + seconds / 10; if(b[i] != '0') i++;
2192
- b[i++]= 48 + seconds % 10;
2193
- b[i++]=')';
2194
- b[i]='\0';
2195
-
2196
- wb->bytes += i;
2197
-}
2198
-
2199
-struct web_buffer *web_buffer_create(long size)
2200
-{
2201
- struct web_buffer *b;
2202
-
2203
- debug(D_WEB_BUFFER, "Creating new web buffer of size %d.", size);
2204
-
2205
- b = calloc(1, sizeof(struct web_buffer));
2206
- if(!b) {
2207
- error("Cannot allocate a web_buffer.");
2208
- return NULL;
2209
- }
2210
-
2211
- b->buffer = malloc(size);
2212
- if(!b->buffer) {
2213
- error("Cannot allocate a buffer of size %u.", size);
2214
- free(b);
2215
- return NULL;
2216
- }
2217
- b->buffer[0] = '\0';
2218
- b->size = size;
2219
- b->contenttype = CT_TEXT_PLAIN;
2220
- return(b);
2221
-}
2222
-
2223
-void web_buffer_free(struct web_buffer *b)
2224
-{
2225
- debug(D_WEB_BUFFER, "Freeing web buffer of size %d.", b->size);
2226
-
2227
- if(b->buffer) free(b->buffer);
2228
- free(b);
2229
-}
2230
-
2231
-void web_buffer_increase(struct web_buffer *b, long free_size_required)
2232
-{
2233
- long left = b->size - b->bytes;
2234
-
2235
- if(left >= free_size_required) return;
2236
- long increase = free_size_required - left;
2237
- if(increase < WEB_DATA_LENGTH_INCREASE_STEP) increase = WEB_DATA_LENGTH_INCREASE_STEP;
2238
-
2239
- debug(D_WEB_BUFFER, "Increasing data buffer from size %d to %d.", b->size, b->size + increase);
2240
-
2241
- b->buffer = realloc(b->buffer, b->size + increase);
2242
- if(!b->buffer) fatal("Failed to increase data buffer from size %d to %d.", b->size, b->size + increase);
2243
-
2244
- b->size += increase;
2245
-}
2246
-
2247
-#define WEB_CLIENT_MODE_NORMAL 0
2248
-#define WEB_CLIENT_MODE_FILECOPY 1
2249
-
2250
-#define URL_MAX 8192
2251
-
2252
-struct web_client {
2253
- unsigned long long id;
2254
- char client_ip[101];
2255
- char last_url[URL_MAX+1];
2256
-
2257
- struct timeval tv_in, tv_ready;
2258
-
2259
- int mode;
2260
- int keepalive;
2261
-
2262
- struct sockaddr_in clientaddr;
2263
-
2264
- pthread_t thread; // the thread servicing this client
2265
- int obsolete; // if set to 1, the listener will remove this client
2266
-
2267
- int ifd;
2268
- int ofd;
2269
-
2270
- struct web_buffer *data;
2271
-
2272
- int zoutput; // if set to 1, web_client_send() will send compressed data
2273
- z_stream zstream; // zlib stream for sending compressed output to client
2274
- Bytef zbuffer[ZLIB_CHUNK]; // temporary buffer for storing compressed output
2275
- long zsent; // the compressed bytes we have sent to the client
2276
- long zhave; // the compressed bytes that we have to send
2277
- int zinitialized;
2278
-
2279
- int wait_receive;
2280
- int wait_send;
2281
-
2282
- char response_header[MAX_HTTP_HEADER_SIZE+1];
2283
-
2284
- struct web_client *prev;
2285
- struct web_client *next;
2286
-} *web_clients = NULL;
2287
-
2288
-unsigned long long web_clients_count = 0;
2289
-
2290
-struct web_client *web_client_create(int listener)
2291
-{
2292
- struct web_client *w;
2293
- socklen_t addrlen;
2294
-
2295
- w = calloc(1, sizeof(struct web_client));
2296
- if(!w) {
2297
- error("Cannot allocate new web_client memory.");
2298
- return NULL;
2299
- }
2300
-
2301
- w->id = ++web_clients_count;
2302
- w->mode = WEB_CLIENT_MODE_NORMAL;
2303
-
2304
- addrlen = sizeof(w->clientaddr);
2305
- w->ifd = accept(listener, (struct sockaddr *)&w->clientaddr, &addrlen);
2306
- if (w->ifd == -1) {
2307
- error("%llu: Cannot accept new incoming connection.", w->id);
2308
- free(w);
2309
- return NULL;
2310
- }
2311
- w->ofd = w->ifd;
2312
-
2313
- strncpy(w->client_ip, inet_ntoa(w->clientaddr.sin_addr), 100);
2314
- w->client_ip[100] = '\0';
2315
-
2316
- debug(D_WEB_CLIENT_ACCESS, "%llu: New web client from %s on socket %d.", w->id, w->client_ip, w->ifd);
2317
-
2318
- {
2319
- int flag = 1;
2320
- if(setsockopt(w->ifd, SOL_SOCKET, SO_KEEPALIVE, (char *) &flag, sizeof(int)) != 0) error("%llu: Cannot set SO_KEEPALIVE on socket.", w->id);
2321
- }
2322
-
2323
- w->data = web_buffer_create(INITIAL_WEB_DATA_LENGTH);
2324
- if(!w->data) {
2325
- close(w->ifd);
2326
- free(w);
2327
- return NULL;
2328
- }
2329
-
2330
- w->wait_receive = 1;
2331
-
2332
- if(web_clients) web_clients->prev = w;
2333
- w->next = web_clients;
2334
- web_clients = w;
2335
-
2336
- global_statistics.connected_clients++;
2337
-
2338
- return(w);
2339
-}
2340
-
2341
-struct web_client *web_client_free(struct web_client *w)
2342
-{
2343
- struct web_client *n = w->next;
2344
-
2345
- debug(D_WEB_CLIENT_ACCESS, "%llu: Closing web client from %s.", w->id, inet_ntoa(w->clientaddr.sin_addr));
2346
-
2347
- if(w->prev) w->prev->next = w->next;
2348
- if(w->next) w->next->prev = w->prev;
2349
-
2350
- if(w == web_clients) web_clients = w->next;
2351
-
2352
- if(w->data) web_buffer_free(w->data);
2353
- close(w->ifd);
2354
- if(w->ofd != w->ifd) close(w->ofd);
2355
- free(w);
2356
-
2357
- global_statistics.connected_clients--;
2358
-
2359
- return(n);
2360
-}
2361
-
2362
-#define GROUP_AVERAGE 0
2363
-#define GROUP_MAX 1
2364
-#define GROUP_SUM 2
2365
-
2366
-// find the oldest entry in the data, skipping all empty slots
2367
-time_t rrd_stats_first_entry_t(RRD_STATS *st)
2368
-{
2369
- if(!st->first_entry_t) return st->last_updated.tv_sec;
2370
-
2371
- return st->first_entry_t / 1000000;
2372
-}
2373
-
2374
-unsigned long rrd_stats_one_json(RRD_STATS *st, char *options, struct web_buffer *wb)
2375
-{
2376
- time_t now = time(NULL);
2377
- web_buffer_increase(wb, 16384);
2378
-
2379
- pthread_rwlock_rdlock(&st->rwlock);
2380
-
2381
- web_buffer_printf(wb,
2382
- "\t\t{\n"
2383
- "\t\t\t\"id\": \"%s\",\n"
2384
- "\t\t\t\"name\": \"%s\",\n"
2385
- "\t\t\t\"type\": \"%s\",\n"
2386
- "\t\t\t\"family\": \"%s\",\n"
2387
- "\t\t\t\"title\": \"%s\",\n"
2388
- "\t\t\t\"priority\": %ld,\n"
2389
- "\t\t\t\"enabled\": %d,\n"
2390
- "\t\t\t\"units\": \"%s\",\n"
2391
- "\t\t\t\"url\": \"/data/%s/%s\",\n"
2392
- "\t\t\t\"chart_type\": \"%s\",\n"
2393
- "\t\t\t\"counter\": %ld,\n"
2394
- "\t\t\t\"entries\": %ld,\n"
2395
- "\t\t\t\"first_entry_t\": %lu,\n"
2396
- "\t\t\t\"last_entry\": %ld,\n"
2397
- "\t\t\t\"last_entry_t\": %lu,\n"
2398
- "\t\t\t\"last_entry_secs_ago\": %lu,\n"
2399
- "\t\t\t\"update_every\": %d,\n"
2400
- "\t\t\t\"isdetail\": %d,\n"
2401
- "\t\t\t\"usec_since_last_update\": %llu,\n"
2402
- "\t\t\t\"collected_total\": " TOTAL_NUMBER_FORMAT ",\n"
2403
- "\t\t\t\"last_collected_total\": " TOTAL_NUMBER_FORMAT ",\n"
2404
- "\t\t\t\"dimensions\": [\n"
2405
- , st->id
2406
- , st->name
2407
- , st->type
2408
- , st->family
2409
- , st->title
2410
- , st->priority
2411
- , st->enabled
2412
- , st->units
2413
- , st->name, options?options:""
2414
- , chart_type_name(st->chart_type)
2415
- , st->counter
2416
- , st->entries
2417
- , rrd_stats_first_entry_t(st)
2418
- , st->current_entry
2419
- , st->last_updated.tv_sec
2420
- , now - (st->last_updated.tv_sec > now) ? now : st->last_updated.tv_sec
2421
- , st->update_every
2422
- , st->isdetail
2423
- , st->usec_since_last_update
2424
- , st->collected_total
2425
- , st->last_collected_total
2426
- );
2427
-
2428
- unsigned long memory = st->memsize;
2429
-
2430
- RRD_DIMENSION *rd;
2431
- for(rd = st->dimensions; rd ; rd = rd->next) {
2432
- memory += rd->memsize;
2433
-
2434
- web_buffer_printf(wb,
2435
- "\t\t\t\t{\n"
2436
- "\t\t\t\t\t\"id\": \"%s\",\n"
2437
- "\t\t\t\t\t\"name\": \"%s\",\n"
2438
- "\t\t\t\t\t\"entries\": %ld,\n"
2439
- "\t\t\t\t\t\"isHidden\": %d,\n"
2440
- "\t\t\t\t\t\"algorithm\": \"%s\",\n"
2441
- "\t\t\t\t\t\"multiplier\": %ld,\n"
2442
- "\t\t\t\t\t\"divisor\": %ld,\n"
2443
- "\t\t\t\t\t\"last_entry_t\": %lu,\n"
2444
- "\t\t\t\t\t\"collected_value\": " COLLECTED_NUMBER_FORMAT ",\n"
2445
- "\t\t\t\t\t\"calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n"
2446
- "\t\t\t\t\t\"last_collected_value\": " COLLECTED_NUMBER_FORMAT ",\n"
2447
- "\t\t\t\t\t\"last_calculated_value\": " CALCULATED_NUMBER_FORMAT ",\n"
2448
- "\t\t\t\t\t\"memory\": %lu\n"
2449
- "\t\t\t\t}%s\n"
2450
- , rd->id
2451
- , rd->name
2452
- , rd->entries
2453
- , rd->hidden
2454
- , algorithm_name(rd->algorithm)
2455
- , rd->multiplier
2456
- , rd->divisor
2457
- , rd->last_collected_time.tv_sec
2458
- , rd->collected_value
2459
- , rd->calculated_value
2460
- , rd->last_collected_value
2461
- , rd->last_calculated_value
2462
- , rd->memsize
2463
- , rd->next?",":""
2464
- );
2465
- }
2466
-
2467
- web_buffer_printf(wb,
2468
- "\t\t\t],\n"
2469
- "\t\t\t\"memory\" : %lu\n"
2470
- "\t\t}"
2471
- , memory
2472
- );
2473
-
2474
- pthread_rwlock_unlock(&st->rwlock);
2475
- return memory;
2476
-}
2477
-
2478
-#define RRD_GRAPH_JSON_HEADER "{\n\t\"charts\": [\n"
2479
-#define RRD_GRAPH_JSON_FOOTER "\n\t]\n}\n"
2480
-
2481
-void rrd_stats_graph_json(RRD_STATS *st, char *options, struct web_buffer *wb)
2482
-{
2483
- web_buffer_increase(wb, 16384);
2484
-
2485
- web_buffer_printf(wb, RRD_GRAPH_JSON_HEADER);
2486
- rrd_stats_one_json(st, options, wb);
2487
- web_buffer_printf(wb, RRD_GRAPH_JSON_FOOTER);
2488
-}
2489
-
2490
-void rrd_stats_all_json(struct web_buffer *wb)
2491
-{
2492
- web_buffer_increase(wb, 1024);
2493
-
2494
- unsigned long memory = 0;
2495
- long c;
2496
- RRD_STATS *st;
2497
-
2498
- web_buffer_printf(wb, RRD_GRAPH_JSON_HEADER);
2499
-
2500
- pthread_rwlock_rdlock(&root_rwlock);
2501
- for(st = root, c = 0; st ; st = st->next) {
2502
- if(st->enabled) {
2503
- if(c) web_buffer_printf(wb, "%s", ",\n");
2504
- memory += rrd_stats_one_json(st, NULL, wb);
2505
- c++;
2506
- }
2507
- }
2508
- pthread_rwlock_unlock(&root_rwlock);
2509
-
2510
- web_buffer_printf(wb, "\n\t],\n"
2511
- "\t\"hostname\": \"%s\",\n"
2512
- "\t\"update_every\": %d,\n"
2513
- "\t\"history\": %d,\n"
2514
- "\t\"memory\": %lu\n"
2515
- "}\n"
2516
- , hostname
2517
- , update_every
2518
- , save_history
2519
- , memory
2520
- );
2521
-}
2522
-
2523
-unsigned long rrd_stats_json(int type, RRD_STATS *st, struct web_buffer *wb, int entries_to_show, int group, int group_method, time_t after, time_t before, int only_non_zero)
2524
-{
2525
- int c;
2526
- pthread_rwlock_rdlock(&st->rwlock);
2527
-
2528
-
2529
- // -------------------------------------------------------------------------
2530
- // switch from JSON to google JSON
2531
-
2532
- char kq[2] = "\"";
2533
- char sq[2] = "\"";
2534
- switch(type) {
2535
- case DATASOURCE_GOOGLE_JSON:
2536
- case DATASOURCE_GOOGLE_JSONP:
2537
- kq[0] = '\0';
2538
- sq[0] = '\'';
2539
- break;
2540
-
2541
- case DATASOURCE_JSON:
2542
- default:
2543
- break;
2544
- }
2545
-
2546
-
2547
- // -------------------------------------------------------------------------
2548
- // validate the parameters
2549
-
2550
- if(entries_to_show < 1) entries_to_show = 1;
2551
- if(group < 1) group = 1;
2552
-
2553
- // make sure current_entry is within limits
2554
- long current_entry = (long)st->current_entry - (long)1;
2555
- if(current_entry < 0) current_entry = 0;
2556
- else if(current_entry >= st->entries) current_entry = st->entries - 1;
2557
-
2558
- // find the oldest entry of the round-robin
2559
- long max_entries_init = (st->counter < (unsigned long)st->entries) ? st->counter : (unsigned long)st->entries;
2560
-
2561
- time_t time_init = st->last_updated.tv_sec;
2562
-
2563
- if(before == 0 || before > time_init) before = time_init;
2564
- if(after == 0) after = rrd_stats_first_entry_t(st);
2565
-
2566
-
2567
- // ---
2568
-
2569
- // our return value (the last timestamp printed)
2570
- // this is required to detect re-transmit in google JSONP
2571
- time_t last_timestamp = 0;
2572
-
2573
-
2574
- // -------------------------------------------------------------------------
2575
- // find how many dimensions we have
2576
-
2577
- int dimensions = 0;
2578
- RRD_DIMENSION *rd;
2579
- for( rd = st->dimensions ; rd ; rd = rd->next) dimensions++;
2580
- if(!dimensions) {
2581
- pthread_rwlock_unlock(&st->rwlock);
2582
- web_buffer_printf(wb, "No dimensions yet.");
2583
- return 0;
2584
- }
2585
-
2586
-
2587
- // -------------------------------------------------------------------------
2588
- // prepare various strings, to speed up the loop
2589
-
2590
- char overflow_annotation[201]; snprintf(overflow_annotation, 200, ",{%sv%s:%sRESET OR OVERFLOW%s},{%sv%s:%sThe counters have been wrapped.%s}", kq, kq, sq, sq, kq, kq, sq, sq);
2591
- char normal_annotation[201]; snprintf(normal_annotation, 200, ",{%sv%s:null},{%sv%s:null}", kq, kq, kq, kq);
2592
- char pre_date[51]; snprintf(pre_date, 50, " {%sc%s:[{%sv%s:%s", kq, kq, kq, kq, sq);
2593
- char post_date[21]; snprintf(post_date, 20, "%s}", sq);
2594
- char pre_value[21]; snprintf(pre_value, 20, ",{%sv%s:", kq, kq);
2595
- char post_value[21]; snprintf(post_value, 20, "}");
2596
-
2597
-
2598
- // -------------------------------------------------------------------------
2599
- // checks for debuging
2600
-
2601
- if(st->debug) {
2602
- debug(D_RRD_STATS, "%s first_entry_t = %lu, last_entry_t = %lu, duration = %lu, after = %lu, before = %lu, duration = %lu, entries_to_show = %lu, group = %lu, max_entries = %ld"
2603
- , st->id
2604
- , rrd_stats_first_entry_t(st)
2605
- , st->last_updated.tv_sec
2606
- , st->last_updated.tv_sec - rrd_stats_first_entry_t(st)
2607
- , after
2608
- , before
2609
- , before - after
2610
- , entries_to_show
2611
- , group
2612
- , max_entries_init
2613
- );
2614
-
2615
- if(before < after)
2616
- debug(D_RRD_STATS, "WARNING: %s The newest value in the database (%lu) is earlier than the oldest (%lu)", st->name, before, after);
2617
-
2618
- if((before - after) > st->entries * st->update_every)
2619
- debug(D_RRD_STATS, "WARNING: %s The time difference between the oldest and the newest entries (%lu) is higher than the capacity of the database (%lu)", st->name, before - after, st->entries * st->update_every);
2620
- }
2621
-
2622
-
2623
- // -------------------------------------------------------------------------
2624
- // temp arrays for keeping values per dimension
2625
-
2626
- calculated_number group_values[dimensions]; // keep sums when grouping
2627
- calculated_number print_values[dimensions]; // keep the final value to be printed
2628
- int print_hidden[dimensions]; // keep hidden flags
2629
- int found_non_zero[dimensions];
2630
-
2631
- // initialize them
2632
- for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
2633
- group_values[c] = print_values[c] = 0;
2634
- print_hidden[c] = rd->hidden;
2635
- found_non_zero[c] = 0;
2636
- }
2637
-
2638
- // -------------------------------------------------------------------------
2639
- // remove dimensions that contain only zeros
2640
-
2641
- int max_loop = 1;
2642
- if(only_non_zero) max_loop = 2;
2643
-
2644
- for(; max_loop ; max_loop--) {
2645
-
2646
- // -------------------------------------------------------------------------
2647
- // print the JSON header
2648
-
2649
- web_buffer_printf(wb, "{\n %scols%s:\n [\n", kq, kq);
2650
- web_buffer_printf(wb, " {%sid%s:%s%s,%slabel%s:%stime%s,%spattern%s:%s%s,%stype%s:%sdatetime%s},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq);
2651
- web_buffer_printf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotation%s}},\n", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
2652
- web_buffer_printf(wb, " {%sid%s:%s%s,%slabel%s:%s%s,%spattern%s:%s%s,%stype%s:%sstring%s,%sp%s:{%srole%s:%sannotationText%s}}", kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, sq, sq, kq, kq, kq, kq, sq, sq);
2653
-
2654
- // print the header for each dimension
2655
- // and update the print_hidden array for the dimensions that should be hidden
2656
- int pc = 0;
2657
- for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
2658
- if(!print_hidden[c]) {
2659
- pc++;
2660
- web_buffer_printf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, rd->name, sq, kq, kq, sq, sq, kq, kq, sq, sq);
2661
- }
2662
- }
2663
- if(!pc) {
2664
- web_buffer_printf(wb, ",\n {%sid%s:%s%s,%slabel%s:%s%s%s,%spattern%s:%s%s,%stype%s:%snumber%s}", kq, kq, sq, sq, kq, kq, sq, "no data", sq, kq, kq, sq, sq, kq, kq, sq, sq);
2665
- }
2666
-
2667
- // print the begin of row data
2668
- web_buffer_printf(wb, "\n ],\n %srows%s:\n [\n", kq, kq);
2669
-
2670
-
2671
- // -------------------------------------------------------------------------
2672
- // the main loop
2673
-
2674
- int annotate_reset = 0;
2675
- int annotation_count = 0;
2676
-
2677
- // to allow grouping on the same values, we need a pad
2678
- long pad = before % group;
2679
-
2680
- // the minimum line length we expect
2681
- int line_size = 4096 + (dimensions * 200);
2682
-
2683
- time_t now = time_init;
2684
- long max_entries = max_entries_init;
2685
-
2686
- long t;
2687
-
2688
- long count = 0, printed = 0, group_count = 0;
2689
- last_timestamp = 0;
2690
- for(t = current_entry; max_entries ; now -= st->update_every, t--, max_entries--) {
2691
- if(t < 0) t = st->entries - 1;
2692
-
2693
- int print_this = 0;
2694
-
2695
- if(st->debug) {
2696
- debug(D_RRD_STATS, "%s t = %ld, count = %ld, group_count = %ld, printed = %ld, now = %lu, %s %s"
2697
- , st->id
2698
- , t
2699
- , count + 1
2700
- , group_count + 1
2701
- , printed
2702
- , now
2703
- , (((count + 1 - pad) % group) == 0)?"PRINT":" - "
2704
- , (now >= after && now <= before)?"RANGE":" - "
2705
- );
2706
- }
2707
-
2708
- // make sure we return data in the proper time range
2709
- if(now < after || now > before) continue;
2710
-
2711
- count++;
2712
- group_count++;
2713
-
2714
- if(((count - pad) % group) == 0) {
2715
- if(printed >= entries_to_show) {
2716
- // debug(D_RRD_STATS, "Already printed all rows. Stopping.");
2717
- break;
2718
- }
2719
-
2720
- if(group_count != group) {
2721
- // this is an incomplete group, skip it.
2722
- for( rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++)
2723
- group_values[c] = 0;
2724
-
2725
- group_count = 0;
2726
- continue;
2727
- }
2728
-
2729
- // check if we may exceed the buffer provided
2730
- web_buffer_increase(wb, line_size);
2731
-
2732
- // generate the local date time
2733
- struct tm *tm = localtime(&now);
2734
- if(!tm) { error("localtime() failed."); continue; }
2735
- if(now > last_timestamp) last_timestamp = now;
2736
-
2737
- if(printed) web_buffer_strcpy(wb, "]},\n");
2738
- web_buffer_strcpy(wb, pre_date);
2739
- web_buffer_jsdate(wb, tm->tm_year + 1900, tm->tm_mon, tm->tm_mday, tm->tm_hour, tm->tm_min, tm->tm_sec);
2740
- web_buffer_strcpy(wb, post_date);
2741
-
2742
- print_this = 1;
2743
- }
2744
-
2745
- for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
2746
- calculated_number value = unpack_storage_number(rd->values[t]);
2747
-
2748
- switch(group_method) {
2749
- case GROUP_MAX:
2750
- if(abs(value) > abs(group_values[c])) group_values[c] = value;
2751
- break;
2752
-
2753
- case GROUP_SUM:
2754
- group_values[c] += value;
2755
- break;
2756
-
2757
- default:
2758
- case GROUP_AVERAGE:
2759
- group_values[c] += value;
2760
- if(print_this) group_values[c] /= group_count;
2761
- break;
2762
- }
2763
-
2764
- if(print_this) {
2765
- print_values[c] = group_values[c];
2766
- group_values[c] = 0;
2767
- }
2768
- }
2769
-
2770
- if(print_this) {
2771
- group_count = 0;
2772
-
2773
- if(annotate_reset) {
2774
- annotation_count++;
2775
- web_buffer_strcpy(wb, overflow_annotation);
2776
- annotate_reset = 0;
2777
- }
2778
- else
2779
- web_buffer_strcpy(wb, normal_annotation);
2780
-
2781
- pc = 0;
2782
- for(c = 0 ; c < dimensions ; c++) {
2783
- if(!print_hidden[c]) {
2784
- pc++;
2785
- web_buffer_strcpy(wb, pre_value);
2786
- web_buffer_rrd_value(wb, print_values[c]);
2787
- web_buffer_strcpy(wb, post_value);
2788
-
2789
- if(print_values[c]) found_non_zero[c]++;
2790
- }
2791
- }
2792
- if(!pc) {
2793
- web_buffer_strcpy(wb, pre_value);
2794
- web_buffer_rrd_value(wb, (calculated_number)0);
2795
- web_buffer_strcpy(wb, post_value);
2796
- }
2797
-
2798
- printed++;
2799
- }
2800
- }
2801
-
2802
- if(printed) web_buffer_printf(wb, "]}");
2803
- web_buffer_printf(wb, "\n ]\n}\n");
2804
-
2805
- if(only_non_zero && max_loop > 1) {
2806
- int changed = 0;
2807
- for(rd = st->dimensions, c = 0 ; rd && c < dimensions ; rd = rd->next, c++) {
2808
- group_values[c] = 0;
2809
-
2810
- if(!print_hidden[c] && !found_non_zero[c]) {
2811
- changed = 1;
2812
- print_hidden[c] = 1;
2813
- }
2814
- }
2815
-
2816
- if(changed) web_buffer_reset(wb);
2817
- else break;
2818
- }
2819
- else break;
2820
-
2821
- } // max_loop
2822
-
2823
- debug(D_RRD_STATS, "RRD_STATS_JSON: %s total %ld bytes", st->name, wb->bytes);
2824
-
2825
- pthread_rwlock_unlock(&st->rwlock);
2826
- return last_timestamp;
2827
-}
2828
-
2829
-void generate_config(struct web_buffer *wb, int only_changed)
2830
-{
2831
- int i, pri;
2832
- struct config *co;
2833
- struct config_value *cv;
2834
-
2835
- for(i = 0; i < 3 ;i++) {
2836
- web_buffer_increase(wb, 500);
2837
- switch(i) {
2838
- case 0:
2839
- web_buffer_printf(wb,
2840
- "# NetData Configuration\n"
2841
- "# You can uncomment and change any of the options bellow.\n"
2842
- "# The value shown in the commented settings, is the default value.\n"
2843
- "\n# global netdata configuration\n");
2844
- break;
2845
-
2846
- case 1:
2847
- web_buffer_printf(wb, "\n\n# per plugin configuration\n");
2848
- break;
2849
-
2850
- case 2:
2851
- web_buffer_printf(wb, "\n\n# per chart configuration\n");
2852
- break;
2853
- }
2854
-
2855
- for(co = config_root; co ; co = co->next) {
2856
- if(strcmp(co->name, "global") == 0 || strcmp(co->name, "plugins") == 0) pri = 0;
2857
- else if(strncmp(co->name, "plugin:", 7) == 0) pri = 1;
2858
- else pri = 2;
2859
-
2860
- if(i == pri) {
2861
- int used = 0;
2862
- int changed = 0;
2863
- int count = 0;
2864
- for(cv = co->values; cv ; cv = cv->next) {
2865
- used += cv->used;
2866
- changed += cv->changed;
2867
- count++;
2868
- }
2869
-
2870
- if(!count) continue;
2871
- if(only_changed && !changed) continue;
2872
-
2873
- if(!used) {
2874
- web_buffer_increase(wb, 500);
2875
- web_buffer_printf(wb, "\n# node '%s' is not used.", co->name);
2876
- }
2877
-
2878
- web_buffer_increase(wb, CONFIG_MAX_NAME + 4);
2879
- web_buffer_printf(wb, "\n[%s]\n", co->name);
2880
-
2881
- for(cv = co->values; cv ; cv = cv->next) {
2882
-
2883
- if(used && !cv->used) {
2884
- web_buffer_increase(wb, CONFIG_MAX_NAME + 200);
2885
- web_buffer_printf(wb, "\n\t# option '%s' is not used.\n", cv->name);
2886
- }
2887
- web_buffer_increase(wb, CONFIG_MAX_NAME + CONFIG_MAX_VALUE + 5);
2888
- web_buffer_printf(wb, "\t%s%s = %s\n", (!cv->changed && cv->used)?"# ":"", cv->name, cv->value);
2889
- }
2890
- }
2891
- }
2892
- }
2893
-}
2894
-
2895
-int mysendfile(struct web_client *w, char *filename)
2896
-{
2897
- static char *web_dir = NULL;
2898
- if(!web_dir) web_dir = config_get("global", "web files directory", "web");
2899
-
2900
- debug(D_WEB_CLIENT, "%llu: Looking for file '%s'...", w->id, filename);
2901
-
2902
- // skip leading slashes
2903
- while (*filename == '/') filename++;
2904
-
2905
- // if the filename contain known paths, skip them
2906
- if(strncmp(filename, WEB_PATH_DATA "/", strlen(WEB_PATH_DATA) + 1) == 0) filename = &filename[strlen(WEB_PATH_DATA) + 1];
2907
- else if(strncmp(filename, WEB_PATH_DATASOURCE "/", strlen(WEB_PATH_DATASOURCE) + 1) == 0) filename = &filename[strlen(WEB_PATH_DATASOURCE) + 1];
2908
- else if(strncmp(filename, WEB_PATH_GRAPH "/", strlen(WEB_PATH_GRAPH) + 1) == 0) filename = &filename[strlen(WEB_PATH_GRAPH) + 1];
2909
- else if(strncmp(filename, WEB_PATH_FILE "/", strlen(WEB_PATH_FILE) + 1) == 0) filename = &filename[strlen(WEB_PATH_FILE) + 1];
2910
-
2911
- // if the filename contains a / or a .., refuse to serve it
2912
- if(strchr(filename, '/') != 0 || strstr(filename, "..") != 0) {
2913
- debug(D_WEB_CLIENT_ACCESS, "%llu: File '%s' is not acceptable.", w->id, filename);
2914
- web_buffer_printf(w->data, "File '%s' cannot be served. Filenames cannot contain / or ..", filename);
2915
- return 400;
2916
- }
2917
-
2918
- // access the file
2919
- char webfilename[FILENAME_MAX + 1];
2920
- snprintf(webfilename, FILENAME_MAX, "%s/%s", web_dir, filename);
2921
-
2922
- // check if the file exists
2923
- struct stat stat;
2924
- if(lstat(webfilename, &stat) != 0) {
2925
- error("%llu: File '%s' is not found.", w->id, webfilename);
2926
- web_buffer_printf(w->data, "File '%s' does not exist, or is not accessible.", filename);
2927
- return 404;
2928
- }
2929
-
2930
- // check if the file is owned by us
2931
- if(stat.st_uid != getuid() && stat.st_uid != geteuid()) {
2932
- error("%llu: File '%s' is owned by user %d (I run as user %d). Access Denied.", w->id, webfilename, stat.st_uid, getuid());
2933
- web_buffer_printf(w->data, "Access to file '%s' is not permitted.", filename);
2934
- return 403;
2935
- }
2936
-
2937
- // open the file
2938
- w->ifd = open(webfilename, O_NONBLOCK, O_RDONLY);
2939
- if(w->ifd == -1) {
2940
- w->ifd = w->ofd;
2941
-
2942
- if(errno == EBUSY || errno == EAGAIN) {
2943
- error("%llu: File '%s' is busy, sending 307 Moved Temporarily to force retry.", w->id, webfilename);
2944
- snprintf(w->response_header, MAX_HTTP_HEADER_SIZE, "Location: /" WEB_PATH_FILE "/%s\r\n", filename);
2945
- web_buffer_printf(w->data, "The file '%s' is currently busy. Please try again later.", filename);
2946
- return 307;
2947
- }
2948
- else {
2949
- error("%llu: Cannot open file '%s'.", w->id, webfilename);
2950
- web_buffer_printf(w->data, "Cannot open file '%s'.", filename);
2951
- return 404;
2952
- }
2953
- }
2954
-
2955
- // pick a Content-Type for the file
2956
- if(strstr(filename, ".html") != NULL) w->data->contenttype = CT_TEXT_HTML;
2957
- else if(strstr(filename, ".js") != NULL) w->data->contenttype = CT_APPLICATION_X_JAVASCRIPT;
2958
- else if(strstr(filename, ".css") != NULL) w->data->contenttype = CT_TEXT_CSS;
2959
- else if(strstr(filename, ".xml") != NULL) w->data->contenttype = CT_TEXT_XML;
2960
- else if(strstr(filename, ".xsl") != NULL) w->data->contenttype = CT_TEXT_XSL;
2961
- else if(strstr(filename, ".txt") != NULL) w->data->contenttype = CT_TEXT_PLAIN;
2962
- else if(strstr(filename, ".svg") != NULL) w->data->contenttype = CT_IMAGE_SVG_XML;
2963
- else if(strstr(filename, ".ttf") != NULL) w->data->contenttype = CT_APPLICATION_X_FONT_TRUETYPE;
2964
- else if(strstr(filename, ".otf") != NULL) w->data->contenttype = CT_APPLICATION_X_FONT_OPENTYPE;
2965
- else if(strstr(filename, ".woff") != NULL) w->data->contenttype = CT_APPLICATION_FONT_WOFF;
2966
- else if(strstr(filename, ".eot") != NULL) w->data->contenttype = CT_APPLICATION_VND_MS_FONTOBJ;
2967
- else w->data->contenttype = CT_APPLICATION_OCTET_STREAM;
2968
-
2969
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending file '%s' (%ld bytes, ifd %d, ofd %d).", w->id, webfilename, stat.st_size, w->ifd, w->ofd);
2970
-
2971
- w->mode = WEB_CLIENT_MODE_FILECOPY;
2972
- w->wait_receive = 1;
2973
- w->wait_send = 0;
2974
- w->data->bytes = 0;
2975
- w->data->buffer[0] = '\0';
2976
- w->data->rbytes = stat.st_size;
2977
- w->data->date = stat.st_mtim.tv_sec;
2978
-
2979
- return 200;
2980
-}
2981
-
2982
-char *mystrsep(char **ptr, char *s)
2983
-{
2984
- char *p = "";
2985
- while ( p && !p[0] && *ptr ) p = strsep(ptr, s);
2986
- return(p);
2987
-}
2988
-
2989
-void web_client_reset(struct web_client *w)
2990
-{
2991
- struct timeval tv;
2992
- gettimeofday(&tv, NULL);
2993
-
2994
- long sent = w->zoutput?(long)w->zstream.total_out:((w->mode == WEB_CLIENT_MODE_FILECOPY)?w->data->rbytes:w->data->bytes);
2995
- long size = (w->mode == WEB_CLIENT_MODE_FILECOPY)?w->data->rbytes:w->data->bytes;
2996
-
2997
- if(w->last_url[0]) log_access("%llu: (sent/all = %ld/%ld bytes %0.0f%%, prep/sent/total = %0.2f/%0.2f/%0.2f ms) %s: '%s'",
2998
- w->id,
2999
- sent, size, -((size>0)?((float)(size-sent)/(float)size * 100.0):0.0),
3000
- (float)usecdiff(&w->tv_ready, &w->tv_in) / 1000.0,
3001
- (float)usecdiff(&tv, &w->tv_ready) / 1000.0,
3002
- (float)usecdiff(&tv, &w->tv_in) / 1000.0,
3003
- (w->mode == WEB_CLIENT_MODE_FILECOPY)?"filecopy":"data",
3004
- w->last_url
3005
- );
3006
-
3007
- debug(D_WEB_CLIENT, "%llu: Reseting client.", w->id);
3008
-
3009
- if(w->mode == WEB_CLIENT_MODE_FILECOPY) {
3010
- debug(D_WEB_CLIENT, "%llu: Closing filecopy input file.", w->id);
3011
- close(w->ifd);
3012
- w->ifd = w->ofd;
3013
- }
3014
-
3015
- w->last_url[0] = '\0';
3016
-
3017
- w->data->contenttype = CT_TEXT_PLAIN;
3018
- w->mode = WEB_CLIENT_MODE_NORMAL;
3019
-
3020
- w->data->rbytes = 0;
3021
- w->data->bytes = 0;
3022
- w->data->sent = 0;
3023
-
3024
- w->response_header[0] = '\0';
3025
- w->data->buffer[0] = '\0';
3026
-
3027
- w->wait_receive = 1;
3028
- w->wait_send = 0;
3029
-
3030
- // if we had enabled compression, release it
3031
- if(w->zinitialized) {
3032
- debug(D_DEFLATE, "%llu: Reseting compression.", w->id);
3033
- deflateEnd(&w->zstream);
3034
- w->zoutput = 0;
3035
- w->zsent = 0;
3036
- w->zhave = 0;
3037
- w->zstream.avail_in = 0;
3038
- w->zstream.avail_out = 0;
3039
- w->zstream.total_in = 0;
3040
- w->zstream.total_out = 0;
3041
- w->zinitialized = 0;
3042
- }
3043
-}
3044
-
3045
-void web_client_enable_deflate(struct web_client *w) {
3046
- if(w->zinitialized == 1) {
3047
- error("%llu: Compression has already be initialized for this client.", w->id);
3048
- return;
3049
- }
3050
-
3051
- if(w->data->sent) {
3052
- error("%llu: Cannot enable compression in the middle of a conversation.", w->id);
3053
- return;
3054
- }
3055
-
3056
- w->zstream.zalloc = Z_NULL;
3057
- w->zstream.zfree = Z_NULL;
3058
- w->zstream.opaque = Z_NULL;
3059
-
3060
- w->zstream.next_in = (Bytef *)w->data->buffer;
3061
- w->zstream.avail_in = 0;
3062
- w->zstream.total_in = 0;
3063
-
3064
- w->zstream.next_out = w->zbuffer;
3065
- w->zstream.avail_out = 0;
3066
- w->zstream.total_out = 0;
3067
-
3068
- w->zstream.zalloc = Z_NULL;
3069
- w->zstream.zfree = Z_NULL;
3070
- w->zstream.opaque = Z_NULL;
3071
-
3072
-// if(deflateInit(&w->zstream, Z_DEFAULT_COMPRESSION) != Z_OK) {
3073
-// error("%llu: Failed to initialize zlib. Proceeding without compression.", w->id);
3074
-// return;
3075
-// }
3076
-
3077
- // Select GZIP compression: windowbits = 15 + 16 = 31
3078
- if(deflateInit2(&w->zstream, Z_DEFAULT_COMPRESSION, Z_DEFLATED, 31, 8, Z_DEFAULT_STRATEGY) != Z_OK) {
3079
- error("%llu: Failed to initialize zlib. Proceeding without compression.", w->id);
3080
- return;
3081
- }
3082
-
3083
- w->zsent = 0;
3084
- w->zoutput = 1;
3085
- w->zinitialized = 1;
3086
-
3087
- debug(D_DEFLATE, "%llu: Initialized compression.", w->id);
3088
-}
3089
-
3090
-int web_client_data_request(struct web_client *w, char *url, int datasource_type)
3091
-{
3092
- char *args = strchr(url, '?');
3093
- if(args) {
3094
- *args='\0';
3095
- args = &args[1];
3096
- }
3097
-
3098
- // get the name of the data to show
3099
- char *tok = mystrsep(&url, "/");
3100
- debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
3101
-
3102
- // do we have such a data set?
3103
- RRD_STATS *st = rrd_stats_find_byname(tok);
3104
- if(!st) st = rrd_stats_find(tok);
3105
- if(!st) {
3106
- // we don't have it
3107
- // try to send a file with that name
3108
- w->data->bytes = 0;
3109
- return(mysendfile(w, tok));
3110
- }
3111
-
3112
- // we have it
3113
- debug(D_WEB_CLIENT, "%llu: Found RRD data with name '%s'.", w->id, tok);
3114
-
3115
- // how many entries does the client want?
3116
- long lines = save_history;
3117
- long group_count = 1;
3118
- time_t after = 0, before = 0;
3119
- int group_method = GROUP_AVERAGE;
3120
- int nonzero = 0;
3121
-
3122
- if(url) {
3123
- // parse the lines required
3124
- tok = mystrsep(&url, "/");
3125
- if(tok) lines = atoi(tok);
3126
- if(lines < 1) lines = 1;
3127
- }
3128
- if(url) {
3129
- // parse the group count required
3130
- tok = mystrsep(&url, "/");
3131
- if(tok) group_count = atoi(tok);
3132
- if(group_count < 1) group_count = 1;
3133
- //if(group_count > save_history / 20) group_count = save_history / 20;
3134
- }
3135
- if(url) {
3136
- // parse the grouping method required
3137
- tok = mystrsep(&url, "/");
3138
- if(strcmp(tok, "max") == 0) group_method = GROUP_MAX;
3139
- else if(strcmp(tok, "average") == 0) group_method = GROUP_AVERAGE;
3140
- else if(strcmp(tok, "sum") == 0) group_method = GROUP_SUM;
3141
- else debug(D_WEB_CLIENT, "%llu: Unknown group method '%s'", w->id, tok);
3142
- }
3143
- if(url) {
3144
- // parse after time
3145
- tok = mystrsep(&url, "/");
3146
- if(tok) after = strtoul(tok, NULL, 10);
3147
- if(after < 0) after = 0;
3148
- }
3149
- if(url) {
3150
- // parse before time
3151
- tok = mystrsep(&url, "/");
3152
- if(tok) before = strtoul(tok, NULL, 10);
3153
- if(before < 0) before = 0;
3154
- }
3155
- if(url) {
3156
- // parse nonzero
3157
- tok = mystrsep(&url, "/");
3158
- if(tok && strcmp(tok, "nonzero") == 0) nonzero = 1;
3159
- }
3160
-
3161
- w->data->contenttype = CT_APPLICATION_JSON;
3162
- w->data->bytes = 0;
3163
-
3164
- char *google_version = "0.6";
3165
- char *google_reqId = "0";
3166
- char *google_sig = "0";
3167
- char *google_out = "json";
3168
- char *google_responseHandler = "google.visualization.Query.setResponse";
3169
- char *google_outFileName = NULL;
3170
- unsigned long last_timestamp_in_data = 0;
3171
- if(datasource_type == DATASOURCE_GOOGLE_JSON || datasource_type == DATASOURCE_GOOGLE_JSONP) {
3172
-
3173
- w->data->contenttype = CT_APPLICATION_X_JAVASCRIPT;
3174
-
3175
- while(args) {
3176
- tok = mystrsep(&args, "&");
3177
- if(tok) {
3178
- char *name = mystrsep(&tok, "=");
3179
- if(name && strcmp(name, "tqx") == 0) {
3180
- char *key = mystrsep(&tok, ":");
3181
- char *value = mystrsep(&tok, ";");
3182
- if(key && value && *key && *value) {
3183
- if(strcmp(key, "version") == 0)
3184
- google_version = value;
3185
-
3186
- else if(strcmp(key, "reqId") == 0)
3187
- google_reqId = value;
3188
-
3189
- else if(strcmp(key, "sig") == 0)
3190
- google_sig = value;
3191
-
3192
- else if(strcmp(key, "out") == 0)
3193
- google_out = value;
3194
-
3195
- else if(strcmp(key, "responseHandler") == 0)
3196
- google_responseHandler = value;
3197
-
3198
- else if(strcmp(key, "outFileName") == 0)
3199
- google_outFileName = value;
3200
- }
3201
- }
3202
- }
3203
- }
3204
-
3205
- debug(D_WEB_CLIENT_ACCESS, "%llu: GOOGLE JSONP: version = '%s', reqId = '%s', sig = '%s', out = '%s', responseHandler = '%s', outFileName = '%s'",
3206
- w->id, google_version, google_reqId, google_sig, google_out, google_responseHandler, google_outFileName
3207
- );
3208
-
3209
- if(datasource_type == DATASOURCE_GOOGLE_JSONP) {
3210
- last_timestamp_in_data = strtoul(google_sig, NULL, 0);
3211
-
3212
- // check the client wants json
3213
- if(strcmp(google_out, "json") != 0) {
3214
- w->data->bytes = snprintf(w->data->buffer, w->data->size,
3215
- "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'invalid_query',message:'output format is not supported',detailed_message:'the format %s requested is not supported by netdata.'}]});",
3216
- google_responseHandler, google_version, google_reqId, google_out);
3217
- return 200;
3218
- }
3219
- }
3220
- }
3221
-
3222
- if(datasource_type == DATASOURCE_GOOGLE_JSONP) {
3223
- w->data->bytes = snprintf(w->data->buffer, w->data->size,
3224
- "%s({version:'%s',reqId:'%s',status:'ok',sig:'%lu',table:",
3225
- google_responseHandler, google_version, google_reqId, st->last_updated.tv_sec);
3226
- }
3227
-
3228
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending RRD data '%s' (id %s, %d lines, %d group, %d group_method, %lu after, %lu before).", w->id, st->name, st->id, lines, group_count, group_method, after, before);
3229
- unsigned long timestamp_in_data = rrd_stats_json(datasource_type, st, w->data, lines, group_count, group_method, after, before, nonzero);
3230
-
3231
- if(datasource_type == DATASOURCE_GOOGLE_JSONP) {
3232
- if(timestamp_in_data > last_timestamp_in_data)
3233
- w->data->bytes += snprintf(&w->data->buffer[w->data->bytes], w->data->size - w->data->bytes, "});");
3234
-
3235
- else {
3236
- // the client already has the latest data
3237
- w->data->bytes = snprintf(w->data->buffer, w->data->size,
3238
- "%s({version:'%s',reqId:'%s',status:'error',errors:[{reason:'not_modified',message:'Data not modified'}]});",
3239
- google_responseHandler, google_version, google_reqId);
3240
- }
3241
- }
3242
-
3243
- return 200;
3244
-}
3245
-
3246
-void web_client_process(struct web_client *w)
3247
-{
3248
- int code = 500;
3249
- int bytes;
3250
-
3251
- w->wait_receive = 0;
3252
-
3253
- // check if we have an empty line (end of HTTP header)
3254
- if(strstr(w->data->buffer, "\r\n\r\n")) {
3255
- global_statistics_lock();
3256
- global_statistics.web_requests++;
3257
- global_statistics_unlock();
3258
-
3259
- gettimeofday(&w->tv_in, NULL);
3260
- debug(D_WEB_DATA, "%llu: Processing data buffer of %d bytes: '%s'.", w->id, w->data->bytes, w->data->buffer);
3261
-
3262
- // check if the client requested keep-alive HTTP
3263
- if(strcasestr(w->data->buffer, "Connection: keep-alive")) w->keepalive = 1;
3264
- else w->keepalive = 0;
3265
-
3266
- // check if the client accepts deflate
3267
- if(strstr(w->data->buffer, "gzip"))
3268
- web_client_enable_deflate(w);
3269
-
3270
- int datasource_type = DATASOURCE_GOOGLE_JSONP;
3271
- //if(strstr(w->data->buffer, "X-DataSource-Auth"))
3272
- // datasource_type = DATASOURCE_GOOGLE_JSON;
3273
-
3274
- char *buf = w->data->buffer;
3275
- char *tok = strsep(&buf, " \r\n");
3276
- char *url = NULL;
3277
- char *pointer_to_free = NULL; // keep url_decode() allocated buffer
3278
-
3279
- if(buf && strcmp(tok, "GET") == 0) {
3280
- tok = strsep(&buf, " \r\n");
3281
- pointer_to_free = url = url_decode(tok);
3282
- debug(D_WEB_CLIENT, "%llu: Processing HTTP GET on url '%s'.", w->id, url);
3283
- }
3284
- else if (buf && strcmp(tok, "POST") == 0) {
3285
- w->keepalive = 0;
3286
- tok = strsep(&buf, " \r\n");
3287
- pointer_to_free = url = url_decode(tok);
3288
-
3289
- debug(D_WEB_CLIENT, "%llu: I don't know how to handle POST with form data. Assuming it is a GET on url '%s'.", w->id, url);
3290
- }
3291
-
3292
- w->last_url[0] = '\0';
3293
- if(url) {
3294
- strncpy(w->last_url, url, URL_MAX);
3295
- w->last_url[URL_MAX] = '\0';
3296
-
3297
- tok = mystrsep(&url, "/?&");
3298
-
3299
- debug(D_WEB_CLIENT, "%llu: Processing command '%s'.", w->id, tok);
3300
-
3301
- if(strcmp(tok, WEB_PATH_DATA) == 0) { // "data"
3302
- // the client is requesting rrd data
3303
- datasource_type = DATASOURCE_JSON;
3304
- code = web_client_data_request(w, url, datasource_type);
3305
- }
3306
- else if(strcmp(tok, WEB_PATH_DATASOURCE) == 0) { // "datasource"
3307
- // the client is requesting google datasource
3308
- code = web_client_data_request(w, url, datasource_type);
3309
- }
3310
- else if(strcmp(tok, WEB_PATH_GRAPH) == 0) { // "graph"
3311
- // the client is requesting an rrd graph
3312
-
3313
- // get the name of the data to show
3314
- tok = mystrsep(&url, "/?&");
3315
- debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
3316
-
3317
- // do we have such a data set?
3318
- RRD_STATS *st = rrd_stats_find_byname(tok);
3319
- if(!st) {
3320
- // we don't have it
3321
- // try to send a file with that name
3322
- w->data->bytes = 0;
3323
- code = mysendfile(w, tok);
3324
- }
3325
- else {
3326
- code = 200;
3327
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending %s.json of RRD_STATS...", w->id, st->name);
3328
- w->data->contenttype = CT_APPLICATION_JSON;
3329
- w->data->bytes = 0;
3330
- rrd_stats_graph_json(st, url, w->data);
3331
- }
3332
- }
3333
- else if(strcmp(tok, "debug") == 0) {
3334
- w->data->bytes = 0;
3335
-
3336
- // get the name of the data to show
3337
- tok = mystrsep(&url, "/?&");
3338
- debug(D_WEB_CLIENT, "%llu: Searching for RRD data with name '%s'.", w->id, tok);
3339
-
3340
- // do we have such a data set?
3341
- RRD_STATS *st = rrd_stats_find_byname(tok);
3342
- if(!st) {
3343
- code = 404;
3344
- web_buffer_printf(w->data, "Chart %s is not found.\r\n", tok);
3345
- debug(D_WEB_CLIENT_ACCESS, "%llu: %s is not found.", w->id, tok);
3346
- }
3347
- else {
3348
- code = 200;
3349
- debug_flags |= D_RRD_STATS;
3350
- st->debug = st->debug?0:1;
3351
- web_buffer_printf(w->data, "Chart %s has now debug %s.\r\n", tok, st->debug?"enabled":"disabled");
3352
- debug(D_WEB_CLIENT_ACCESS, "%llu: debug for %s is %s.", w->id, tok, st->debug?"enabled":"disabled");
3353
- }
3354
- }
3355
- else if(strcmp(tok, "mirror") == 0) {
3356
- code = 200;
3357
-
3358
- debug(D_WEB_CLIENT_ACCESS, "%llu: Mirroring...", w->id);
3359
-
3360
- // replace the zero bytes with spaces
3361
- int i;
3362
- for(i = 0; i < w->data->size; i++)
3363
- if(w->data->buffer[i] == '\0') w->data->buffer[i] = ' ';
3364
-
3365
- // just leave the buffer as is
3366
- // it will be copied back to the client
3367
- }
3368
- else if(strcmp(tok, "list") == 0) {
3369
- code = 200;
3370
-
3371
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending list of RRD_STATS...", w->id);
3372
-
3373
- w->data->bytes = 0;
3374
- RRD_STATS *st = root;
3375
-
3376
- for ( ; st ; st = st->next )
3377
- web_buffer_printf(w->data, "%s\n", st->name);
3378
- }
3379
- else if(strcmp(tok, "all.json") == 0) {
3380
- code = 200;
3381
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending JSON list of all monitors of RRD_STATS...", w->id);
3382
-
3383
- w->data->contenttype = CT_APPLICATION_JSON;
3384
- w->data->bytes = 0;
3385
- rrd_stats_all_json(w->data);
3386
- }
3387
- else if(strcmp(tok, "netdata.conf") == 0) {
3388
- code = 200;
3389
- debug(D_WEB_CLIENT_ACCESS, "%llu: Sending netdata.conf ...", w->id);
3390
-
3391
- w->data->contenttype = CT_TEXT_PLAIN;
3392
- w->data->bytes = 0;
3393
- generate_config(w->data, 0);
3394
- }
3395
- else if(strcmp(tok, WEB_PATH_FILE) == 0) { // "file"
3396
- tok = mystrsep(&url, "/?&");
3397
- if(tok && *tok) code = mysendfile(w, tok);
3398
- else {
3399
- code = 400;
3400
- w->data->bytes = 0;
3401
- strcpy(w->data->buffer, "You have to give a filename to get.\r\n");
3402
- w->data->bytes = strlen(w->data->buffer);
3403
- }
3404
- }
3405
- else if(!tok[0]) {
3406
- w->data->bytes = 0;
3407
- code = mysendfile(w, "index.html");
3408
- }
3409
- else {
3410
- w->data->bytes = 0;
3411
- code = mysendfile(w, tok);
3412
- }
3413
-
3414
- }
3415
- else {
3416
- strcpy(w->last_url, "not a valid response");
3417
-
3418
- if(buf) debug(D_WEB_CLIENT_ACCESS, "%llu: Cannot understand '%s'.", w->id, buf);
3419
-
3420
- code = 500;
3421
- w->data->bytes = 0;
3422
- strcpy(w->data->buffer, "I don't understand you...\r\n");
3423
- w->data->bytes = strlen(w->data->buffer);
3424
- }
3425
-
3426
- // free url_decode() buffer
3427
- if(pointer_to_free) free(pointer_to_free);
3428
- }
3429
- else if(w->data->bytes > 8192) {
3430
- strcpy(w->last_url, "too big request");
3431
-
3432
- debug(D_WEB_CLIENT_ACCESS, "%llu: Received request is too big.", w->id);
3433
-
3434
- code = 400;
3435
- w->data->bytes = 0;
3436
- strcpy(w->data->buffer, "Received request is too big.\r\n");
3437
- w->data->bytes = strlen(w->data->buffer);
3438
- }
3439
- else {
3440
- // wait for more data
3441
- w->wait_receive = 1;
3442
- return;
3443
- }
3444
-
3445
- if(w->data->bytes > w->data->size) {
3446
- error("%llu: memory overflow encountered (size is %ld, written %ld).", w->data->size, w->data->bytes);
3447
- }
3448
-
3449
- gettimeofday(&w->tv_ready, NULL);
3450
- w->data->date = time(NULL);
3451
- w->data->sent = 0;
3452
-
3453
- // prepare the HTTP response header
3454
- debug(D_WEB_CLIENT, "%llu: Generating HTTP header with response %d.", w->id, code);
3455
-
3456
- char *content_type_string = "";
3457
- switch(w->data->contenttype) {
3458
- case CT_TEXT_HTML:
3459
- content_type_string = "text/html";
3460
- break;
3461
-
3462
- case CT_APPLICATION_XML:
3463
- content_type_string = "application/xml";
3464
- break;
3465
-
3466
- case CT_APPLICATION_JSON:
3467
- content_type_string = "application/json";
3468
- break;
3469
-
3470
- case CT_APPLICATION_X_JAVASCRIPT:
3471
- content_type_string = "application/x-javascript";
3472
- break;
3473
-
3474
- case CT_TEXT_CSS:
3475
- content_type_string = "text/css";
3476
- break;
3477
-
3478
- case CT_TEXT_XML:
3479
- content_type_string = "text/xml";
3480
- break;
3481
-
3482
- case CT_TEXT_XSL:
3483
- content_type_string = "text/xsl";
3484
- break;
3485
-
3486
- case CT_APPLICATION_OCTET_STREAM:
3487
- content_type_string = "application/octet-stream";
3488
- break;
3489
-
3490
- case CT_IMAGE_SVG_XML:
3491
- content_type_string = "image/svg+xml";
3492
- break;
3493
-
3494
- case CT_APPLICATION_X_FONT_TRUETYPE:
3495
- content_type_string = "application/x-font-truetype";
3496
- break;
3497
-
3498
- case CT_APPLICATION_X_FONT_OPENTYPE:
3499
- content_type_string = "application/x-font-opentype";
3500
- break;
3501
-
3502
- case CT_APPLICATION_FONT_WOFF:
3503
- content_type_string = "application/font-woff";
3504
- break;
3505
-
3506
- case CT_APPLICATION_VND_MS_FONTOBJ:
3507
- content_type_string = "application/vnd.ms-fontobject";
3508
- break;
3509
-
3510
- default:
3511
- case CT_TEXT_PLAIN:
3512
- content_type_string = "text/plain";
3513
- break;
3514
- }
3515
-
3516
- char *code_msg = "";
3517
- switch(code) {
3518
- case 200:
3519
- code_msg = "OK";
3520
- break;
3521
-
3522
- case 307:
3523
- code_msg = "Temporary Redirect";
3524
- break;
3525
-
3526
- case 400:
3527
- code_msg = "Bad Request";
3528
- break;
3529
-
3530
- case 403:
3531
- code_msg = "Forbidden";
3532
- break;
3533
-
3534
- case 404:
3535
- code_msg = "Not Found";
3536
- break;
3537
-
3538
- default:
3539
- code_msg = "Internal Server Error";
3540
- break;
3541
- }
3542
-
3543
- char date[100];
3544
- struct tm tm = *gmtime(&w->data->date);
3545
- strftime(date, sizeof(date), "%a, %d %b %Y %H:%M:%S %Z", &tm);
3546
-
3547
- char custom_header[MAX_HTTP_HEADER_SIZE + 1] = "";
3548
- if(w->response_header[0])
3549
- strcpy(custom_header, w->response_header);
3550
-
3551
- int headerlen = 0;
3552
- headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen,
3553
- "HTTP/1.1 %d %s\r\n"
3554
- "Connection: %s\r\n"
3555
- "Server: NetData Embedded HTTP Server\r\n"
3556
- "Content-Type: %s\r\n"
3557
- "Access-Control-Allow-Origin: *\r\n"
3558
- "Date: %s\r\n"
3559
- , code, code_msg
3560
- , w->keepalive?"keep-alive":"close"
3561
- , content_type_string
3562
- , date
3563
- );
3564
-
3565
- if(custom_header[0])
3566
- headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen, "%s", custom_header);
3567
-
3568
- if(w->mode == WEB_CLIENT_MODE_NORMAL) {
3569
- headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen,
3570
- "Expires: %s\r\n"
3571
- "Cache-Control: no-cache\r\n"
3572
- , date
3573
- );
3574
- }
3575
- else {
3576
- headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen,
3577
- "Cache-Control: public\r\n"
3578
- );
3579
- }
3580
-
3581
- // if we know the content length, put it
3582
- if(!w->zoutput && (w->data->bytes || w->data->rbytes))
3583
- headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen,
3584
- "Content-Length: %ld\r\n"
3585
- , w->data->bytes?w->data->bytes:w->data->rbytes
3586
- );
3587
- else if(!w->zoutput)
3588
- w->keepalive = 0; // content-length is required for keep-alive
3589
-
3590
- if(w->zoutput) {
3591
- headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen,
3592
- "Content-Encoding: gzip\r\n"
3593
- "Transfer-Encoding: chunked\r\n"
3594
- );
3595
- }
3596
-
3597
- headerlen += snprintf(&w->response_header[headerlen], MAX_HTTP_HEADER_SIZE - headerlen, "\r\n");
3598
-
3599
- // disable TCP_NODELAY, to buffer the header
3600
- int flag = 0;
3601
- if(setsockopt(w->ofd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) != 0) error("%llu: failed to disable TCP_NODELAY on socket.", w->id);
3602
-
3603
- // sent the HTTP header
3604
- debug(D_WEB_DATA, "%llu: Sending response HTTP header of size %d: '%s'", w->id, headerlen, w->response_header);
3605
-
3606
- bytes = send(w->ofd, w->response_header, headerlen, 0);
3607
- if(bytes != headerlen)
3608
- error("%llu: HTTP Header failed to be sent (I sent %d bytes but the system sent %d bytes).", w->id, headerlen, bytes);
3609
- else {
3610
- global_statistics_lock();
3611
- global_statistics.bytes_sent += bytes;
3612
- global_statistics_unlock();
3613
- }
3614
-
3615
- // enable TCP_NODELAY, to send all data immediately at the next send()
3616
- flag = 1;
3617
- if(setsockopt(w->ofd, IPPROTO_TCP, TCP_NODELAY, (char *) &flag, sizeof(int)) != 0) error("%llu: failed to enable TCP_NODELAY on socket.", w->id);
3618
-
3619
- // enable sending immediately if we have data
3620
- if(w->data->bytes) w->wait_send = 1;
3621
- else w->wait_send = 0;
3622
-
3623
- // pretty logging
3624
- switch(w->mode) {
3625
- case WEB_CLIENT_MODE_NORMAL:
3626
- debug(D_WEB_CLIENT, "%llu: Done preparing the response. Sending data (%d bytes) to client.", w->id, w->data->bytes);
3627
- break;
3628
-
3629
- case WEB_CLIENT_MODE_FILECOPY:
3630
- if(w->data->rbytes) {
3631
- debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending data file of %d bytes to client.", w->id, w->data->rbytes);
3632
- w->wait_receive = 1;
3633
-
3634
- /*
3635
- // utilize the kernel sendfile() for copying the file to the socket.
3636
- // this block of code can be commented, without anything missing.
3637
- // when it is commented, the program will copy the data using async I/O.
3638
- {
3639
- long len = sendfile(w->ofd, w->ifd, NULL, w->data->rbytes);
3640
- if(len != w->data->rbytes) error("%llu: sendfile() should copy %ld bytes, but copied %ld. Falling back to manual copy.", w->id, w->data->rbytes, len);
3641
- else web_client_reset(w);
3642
- }
3643
- */
3644
- }
3645
- else
3646
- debug(D_WEB_CLIENT, "%llu: Done preparing the response. Will be sending an unknown amount of bytes to client.", w->id);
3647
- break;
3648
-
3649
- default:
3650
- fatal("%llu: Unknown client mode %d.", w->id, w->mode);
3651
- break;
3652
- }
3653
-}
3654
-
3655
-long web_client_send_chunk_header(struct web_client *w, int len)
3656
-{
3657
- debug(D_DEFLATE, "%llu: OPEN CHUNK of %d bytes (hex: %x).", w->id, len, len);
3658
- char buf[1024];
3659
- sprintf(buf, "%X\r\n", len);
3660
- int bytes = send(w->ofd, buf, strlen(buf), MSG_DONTWAIT);
3661
-
3662
- if(bytes > 0) debug(D_DEFLATE, "%llu: Sent chunk header %d bytes.", w->id, bytes);
3663
- else if(bytes == 0) debug(D_DEFLATE, "%llu: Did not send chunk header to the client.", w->id);
3664
- else debug(D_DEFLATE, "%llu: Failed to send chunk header to client. Reason: %s", w->id, strerror(errno));
3665
-
3666
- return bytes;
3667
-}
3668
-
3669
-long web_client_send_chunk_close(struct web_client *w)
3670
-{
3671
- //debug(D_DEFLATE, "%llu: CLOSE CHUNK.", w->id);
3672
-
3673
- int bytes = send(w->ofd, "\r\n", 2, MSG_DONTWAIT);
3674
-
3675
- if(bytes > 0) debug(D_DEFLATE, "%llu: Sent chunk suffix %d bytes.", w->id, bytes);
3676
- else if(bytes == 0) debug(D_DEFLATE, "%llu: Did not send chunk suffix to the client.", w->id);
3677
- else debug(D_DEFLATE, "%llu: Failed to send chunk suffix to client. Reason: %s", w->id, strerror(errno));
3678
-
3679
- return bytes;
3680
-}
3681
-
3682
-long web_client_send_chunk_finalize(struct web_client *w)
3683
-{
3684
- //debug(D_DEFLATE, "%llu: FINALIZE CHUNK.", w->id);
3685
-
3686
- int bytes = send(w->ofd, "\r\n0\r\n\r\n", 7, MSG_DONTWAIT);
3687
-
3688
- if(bytes > 0) debug(D_DEFLATE, "%llu: Sent chunk suffix %d bytes.", w->id, bytes);
3689
- else if(bytes == 0) debug(D_DEFLATE, "%llu: Did not send chunk suffix to the client.", w->id);
3690
- else debug(D_DEFLATE, "%llu: Failed to send chunk suffix to client. Reason: %s", w->id, strerror(errno));
3691
-
3692
- return bytes;
3693
-}
3694
-
3695
-long web_client_send_deflate(struct web_client *w)
3696
-{
3697
- long bytes = 0, t = 0;
3698
-
3699
- // when using compression,
3700
- // w->data->sent is the amount of bytes passed through compression
3701
-
3702
- // debug(D_DEFLATE, "%llu: TEST w->data->bytes = %d, w->data->sent = %d, w->zhave = %d, w->zsent = %d, w->zstream.avail_in = %d, w->zstream.avail_out = %d, w->zstream.total_in = %d, w->zstream.total_out = %d.", w->id, w->data->bytes, w->data->sent, w->zhave, w->zsent, w->zstream.avail_in, w->zstream.avail_out, w->zstream.total_in, w->zstream.total_out);
3703
-
3704
- if(w->data->bytes - w->data->sent == 0 && w->zstream.avail_in == 0 && w->zhave == w->zsent && w->zstream.avail_out != 0) {
3705
- // there is nothing to send
3706
-
3707
- debug(D_WEB_CLIENT, "%llu: Out of output data.", w->id);
3708
-
3709
- // finalize the chunk
3710
- if(w->data->sent != 0)
3711
- t += web_client_send_chunk_finalize(w);
3712
-
3713
- // there can be two cases for this
3714
- // A. we have done everything
3715
- // B. we temporarily have nothing to send, waiting for the buffer to be filled by ifd
3716
-
3717
- if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->ifd != w->ofd && w->data->rbytes && w->data->rbytes > w->data->bytes) {
3718
- // we have to wait, more data will come
3719
- debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
3720
- w->wait_send = 0;
3721
- return(0);
3722
- }
3723
-
3724
- if(w->keepalive == 0) {
3725
- debug(D_WEB_CLIENT, "%llu: Closing (keep-alive is not enabled). %ld bytes sent.", w->id, w->data->sent);
3726
- errno = 0;
3727
- return(-1);
3728
- }
3729
-
3730
- // reset the client
3731
- web_client_reset(w);
3732
- debug(D_WEB_CLIENT, "%llu: Done sending all data on socket. Waiting for next request on the same socket.", w->id);
3733
- return(0);
3734
- }
3735
-
3736
- if(w->zstream.avail_out == 0 && w->zhave == w->zsent) {
3737
- // compress more input data
3738
-
3739
- // close the previous open chunk
3740
- if(w->data->sent != 0) t += web_client_send_chunk_close(w);
3741
-
3742
- debug(D_DEFLATE, "%llu: Compressing %d bytes starting from %d.", w->id, (w->data->bytes - w->data->sent), w->data->sent);
3743
-
3744
- // give the compressor all the data not passed through the compressor yet
3745
- if(w->data->bytes > w->data->sent) {
3746
- w->zstream.next_in = (Bytef *)&w->data->buffer[w->data->sent];
3747
- w->zstream.avail_in = (w->data->bytes - w->data->sent);
3748
- }
3749
-
3750
- // reset the compressor output buffer
3751
- w->zstream.next_out = w->zbuffer;
3752
- w->zstream.avail_out = ZLIB_CHUNK;
3753
-
3754
- // ask for FINISH if we have all the input
3755
- int flush = Z_SYNC_FLUSH;
3756
- if(w->mode == WEB_CLIENT_MODE_NORMAL
3757
- || (w->mode == WEB_CLIENT_MODE_FILECOPY && w->data->bytes == w->data->rbytes)) {
3758
- flush = Z_FINISH;
3759
- debug(D_DEFLATE, "%llu: Requesting Z_FINISH.", w->id);
3760
- }
3761
- else {
3762
- debug(D_DEFLATE, "%llu: Requesting Z_SYNC_FLUSH.", w->id);
3763
- }
3764
-
3765
- // compress
3766
- if(deflate(&w->zstream, flush) == Z_STREAM_ERROR) {
3767
- error("%llu: Compression failed. Closing down client.", w->id);
3768
- web_client_reset(w);
3769
- return(-1);
3770
- }
3771
-
3772
- w->zhave = ZLIB_CHUNK - w->zstream.avail_out;
3773
- w->zsent = 0;
3774
-
3775
- // keep track of the bytes passed through the compressor
3776
- w->data->sent = w->data->bytes;
3777
-
3778
- debug(D_DEFLATE, "%llu: Compression produced %d bytes.", w->id, w->zhave);
3779
-
3780
- // open a new chunk
3781
- t += web_client_send_chunk_header(w, w->zhave);
3782
- }
3783
-
3784
- bytes = send(w->ofd, &w->zbuffer[w->zsent], w->zhave - w->zsent, MSG_DONTWAIT);
3785
- if(bytes > 0) {
3786
- w->zsent += bytes;
3787
- if(t > 0) bytes += t;
3788
- debug(D_WEB_CLIENT, "%llu: Sent %d bytes.", w->id, bytes);
3789
- }
3790
- else if(bytes == 0) debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client.", w->id);
3791
- else debug(D_WEB_CLIENT, "%llu: Failed to send data to client. Reason: %s", w->id, strerror(errno));
3792
-
3793
- return(bytes);
3794
-}
3795
-
3796
-long web_client_send(struct web_client *w)
3797
-{
3798
- if(w->zoutput) return web_client_send_deflate(w);
3799
-
3800
- long bytes;
3801
-
3802
- if(w->data->bytes - w->data->sent == 0) {
3803
- // there is nothing to send
3804
-
3805
- debug(D_WEB_CLIENT, "%llu: Out of output data.", w->id);
3806
-
3807
- // there can be two cases for this
3808
- // A. we have done everything
3809
- // B. we temporarily have nothing to send, waiting for the buffer to be filled by ifd
3810
-
3811
- if(w->mode == WEB_CLIENT_MODE_FILECOPY && w->wait_receive && w->ifd != w->ofd && w->data->rbytes && w->data->rbytes > w->data->bytes) {
3812
- // we have to wait, more data will come
3813
- debug(D_WEB_CLIENT, "%llu: Waiting for more data to become available.", w->id);
3814
- w->wait_send = 0;
3815
- return(0);
3816
- }
3817
-
3818
- if(w->keepalive == 0) {
3819
- debug(D_WEB_CLIENT, "%llu: Closing (keep-alive is not enabled). %ld bytes sent.", w->id, w->data->sent);
3820
- errno = 0;
3821
- return(-1);
3822
- }
3823
-
3824
- web_client_reset(w);
3825
- debug(D_WEB_CLIENT, "%llu: Done sending all data on socket. Waiting for next request on the same socket.", w->id);
3826
- return(0);
3827
- }
3828
-
3829
- bytes = send(w->ofd, &w->data->buffer[w->data->sent], w->data->bytes - w->data->sent, MSG_DONTWAIT);
3830
- if(bytes > 0) {
3831
- w->data->sent += bytes;
3832
- debug(D_WEB_CLIENT, "%llu: Sent %d bytes.", w->id, bytes);
3833
- }
3834
- else if(bytes == 0) debug(D_WEB_CLIENT, "%llu: Did not send any bytes to the client.", w->id);
3835
- else debug(D_WEB_CLIENT, "%llu: Failed to send data to client. Reason: %s", w->id, strerror(errno));
3836
-
3837
-
3838
- return(bytes);
3839
-}
3840
-
3841
-long web_client_receive(struct web_client *w)
3842
-{
3843
- // do we have any space for more data?
3844
- web_buffer_increase(w->data, WEB_DATA_LENGTH_INCREASE_STEP);
3845
-
3846
- long left = w->data->size - w->data->bytes;
3847
- long bytes;
3848
-
3849
- if(w->mode == WEB_CLIENT_MODE_FILECOPY)
3850
- bytes = read(w->ifd, &w->data->buffer[w->data->bytes], (left-1));
3851
- else
3852
- bytes = recv(w->ifd, &w->data->buffer[w->data->bytes], left-1, MSG_DONTWAIT);
3853
-
3854
- if(bytes > 0) {
3855
- int old = w->data->bytes;
3856
- w->data->bytes += bytes;
3857
- w->data->buffer[w->data->bytes] = '\0';
3858
-
3859
- debug(D_WEB_CLIENT, "%llu: Received %d bytes.", w->id, bytes);
3860
- debug(D_WEB_DATA, "%llu: Received data: '%s'.", w->id, &w->data->buffer[old]);
3861
-
3862
- if(w->mode == WEB_CLIENT_MODE_FILECOPY) {
3863
- w->wait_send = 1;
3864
- if(w->data->rbytes && w->data->bytes >= w->data->rbytes) w->wait_receive = 0;
3865
- }
3866
- }
3867
- else if(bytes == 0) {
3868
- debug(D_WEB_CLIENT, "%llu: Out of input data.", w->id);
3869
-
3870
- // if we cannot read, it means we have an error on input.
3871
- // if however, we are copying a file from ifd to ofd, we should not return an error.
3872
- // in this case, the error should be generated when the file has been sent to the client.
3873
-
3874
- if(w->mode == WEB_CLIENT_MODE_FILECOPY) {
3875
- // we are copying data fron ifd to ofd
3876
- // let it finish copying...
3877
- w->wait_receive = 0;
3878
- debug(D_WEB_CLIENT, "%llu: Disabling input.", w->id);
3879
- }
3880
- else {
3881
- bytes = -1;
3882
- errno = 0;
3883
- }
3884
- }
3885
-
3886
- return(bytes);
3887
-}
3888
-
3889
-
3890
-// --------------------------------------------------------------------------------------
3891
-// the thread of a single client
3892
-
3893
-// 1. waits for input and output, using async I/O
3894
-// 2. it processes HTTP requests
3895
-// 3. it generates HTTP responses
3896
-// 4. it copies data from input to output if mode is FILECOPY
3897
-
3898
-void *new_client(void *ptr)
3899
-{
3900
- if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
3901
- error("Cannot set pthread cancel type to DEFERRED.");
3902
-
3903
- if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
3904
- error("Cannot set pthread cancel state to ENABLE.");
3905
-
3906
- struct timeval tv;
3907
- struct web_client *w = ptr;
3908
- int retval;
3909
- fd_set ifds, ofds, efds;
3910
- int fdmax = 0;
3911
-
3912
- for(;;) {
3913
- FD_ZERO (&ifds);
3914
- FD_ZERO (&ofds);
3915
- FD_ZERO (&efds);
3916
-
3917
- FD_SET(w->ifd, &efds);
3918
- if(w->ifd != w->ofd) FD_SET(w->ofd, &efds);
3919
- if (w->wait_receive) {
3920
- FD_SET(w->ifd, &ifds);
3921
- if(w->ifd > fdmax) fdmax = w->ifd;
3922
- }
3923
- if (w->wait_send) {
3924
- FD_SET(w->ofd, &ofds);
3925
- if(w->ofd > fdmax) fdmax = w->ofd;
3926
- }
3927
-
3928
- tv.tv_sec = 30;
3929
- tv.tv_usec = 0;
3930
-
3931
- debug(D_WEB_CLIENT, "%llu: Waiting socket async I/O for %s %s", w->id, w->wait_receive?"INPUT":"", w->wait_send?"OUTPUT":"");
3932
- retval = select(fdmax+1, &ifds, &ofds, &efds, &tv);
3933
-
3934
- if(retval == -1) {
3935
- error("%llu: LISTENER: select() failed.", w->id);
3936
- continue;
3937
- }
3938
- else if(!retval) {
3939
- // timeout
3940
- web_client_reset(w);
3941
- w->obsolete = 1;
3942
- return NULL;
3943
- }
3944
-
3945
- if(FD_ISSET(w->ifd, &efds)) {
3946
- debug(D_WEB_CLIENT_ACCESS, "%llu: Received error on input socket (%s).", w->id, strerror(errno));
3947
- web_client_reset(w);
3948
- w->obsolete = 1;
3949
- return NULL;
3950
- }
3951
-
3952
- if(FD_ISSET(w->ofd, &efds)) {
3953
- debug(D_WEB_CLIENT_ACCESS, "%llu: Received error on output socket (%s).", w->id, strerror(errno));
3954
- web_client_reset(w);
3955
- w->obsolete = 1;
3956
- return NULL;
3957
- }
3958
-
3959
- if(w->wait_send && FD_ISSET(w->ofd, &ofds)) {
3960
- long bytes;
3961
- if((bytes = web_client_send(w)) < 0) {
3962
- debug(D_WEB_CLIENT, "%llu: Closing client (input: %s).", w->id, strerror(errno));
3963
- web_client_reset(w);
3964
- w->obsolete = 1;
3965
- errno = 0;
3966
- return NULL;
3967
- }
3968
- else {
3969
- global_statistics_lock();
3970
- global_statistics.bytes_sent += bytes;
3971
- global_statistics_unlock();
3972
- }
3973
- }
3974
-
3975
- if(w->wait_receive && FD_ISSET(w->ifd, &ifds)) {
3976
- long bytes;
3977
- if((bytes = web_client_receive(w)) < 0) {
3978
- debug(D_WEB_CLIENT, "%llu: Closing client (output: %s).", w->id, strerror(errno));
3979
- web_client_reset(w);
3980
- w->obsolete = 1;
3981
- errno = 0;
3982
- return NULL;
3983
- }
3984
- else {
3985
- if(w->mode != WEB_CLIENT_MODE_FILECOPY) {
3986
- global_statistics_lock();
3987
- global_statistics.bytes_received += bytes;
3988
- global_statistics_unlock();
3989
- }
3990
- }
3991
-
3992
- if(w->mode == WEB_CLIENT_MODE_NORMAL) web_client_process(w);
3993
- }
3994
- }
3995
- debug(D_WEB_CLIENT, "%llu: done...", w->id);
3996
-
3997
- return NULL;
3998
-}
3999
-
4000
-// --------------------------------------------------------------------------------------
4001
-// the main socket listener
4002
-
4003
-// 1. it accepts new incoming requests on our port
4004
-// 2. creates a new web_client for each connection received
4005
-// 3. spawns a new pthread to serve the client (this is optimal for keep-alive clients)
4006
-// 4. cleans up old web_clients that their pthreads have been exited
4007
-
4008
-void log_allocations(void)
4009
-{
4010
- static int mem = 0;
4011
-
4012
- struct mallinfo mi;
4013
-
4014
- mi = mallinfo();
4015
- if(mi.uordblks > mem) {
4016
- int clients = 0;
4017
- struct web_client *w;
4018
- for(w = web_clients; w ; w = w->next) clients++;
4019
-
4020
- info("Allocated memory increased from %d to %d (increased by %d bytes). There are %d web clients connected.", mem, mi.uordblks, mi.uordblks - mem, clients);
4021
- mem = mi.uordblks;
4022
- }
4023
-}
4024
-
4025
-void *socket_listen_main(void *ptr)
4026
-{
4027
- if(ptr) { ; }
4028
- struct web_client *w;
4029
- struct timeval tv;
4030
- int retval;
4031
-
4032
- if(ptr) { ; }
4033
-
4034
- if(pthread_setcanceltype(PTHREAD_CANCEL_DEFERRED, NULL) != 0)
4035
- error("Cannot set pthread cancel type to DEFERRED.");
4036
-
4037
- if(pthread_setcancelstate(PTHREAD_CANCEL_ENABLE, NULL) != 0)
4038
- error("Cannot set pthread cancel state to ENABLE.");
4039
-
4040
- // int listener = create_listen_socket(listen_port);
4041
- int listener = listen_fd;
4042
- if(listener == -1) fatal("LISTENER: Cannot create listening socket on port 19999.");
4043
-
4044
- fd_set ifds, ofds, efds;
4045
- int fdmax = listener;
4046
-
4047
- FD_ZERO (&ifds);
4048
- FD_ZERO (&ofds);
4049
- FD_ZERO (&efds);
4050
-
4051
- for(;;) {
4052
- tv.tv_sec = 0;
4053
- tv.tv_usec = 200000;
4054
-
4055
- FD_SET(listener, &ifds);
4056
- FD_SET(listener, &efds);
4057
-
4058
- // debug(D_WEB_CLIENT, "LISTENER: Waiting...");
4059
- retval = select(fdmax+1, &ifds, &ofds, &efds, &tv);
4060
-
4061
- if(retval == -1) {
4062
- error("LISTENER: select() failed.");
4063
- continue;
4064
- }
4065
- else if(retval) {
4066
- // check for new incoming connections
4067
- if(FD_ISSET(listener, &ifds)) {
4068
- w = web_client_create(listener);
4069
-
4070
- if(pthread_create(&w->thread, NULL, new_client, w) != 0) {
4071
- error("%llu: failed to create new thread for web client.");
4072
- w->obsolete = 1;
4073
- }
4074
- else if(pthread_detach(w->thread) != 0) {
4075
- error("%llu: Cannot request detach of newly created web client thread.", w->id);
4076
- w->obsolete = 1;
4077
- }
4078
-
4079
- log_access("%llu: %s connected", w->id, w->client_ip);
4080
- }
4081
- else debug(D_WEB_CLIENT, "LISTENER: select() didn't do anything.");
4082
-
4083
- }
4084
- //else {
4085
- // debug(D_WEB_CLIENT, "LISTENER: select() timeout.");
4086
- //}
4087
-
4088
- // cleanup unused clients
4089
- for(w = web_clients; w ; w = w?w->next:NULL) {
4090
- if(w->obsolete) {
4091
- log_access("%llu: %s disconnected", w->id, w->client_ip);
4092
- debug(D_WEB_CLIENT, "%llu: Removing client.", w->id);
4093
- // pthread_join(w->thread, NULL);
4094
- w = web_client_free(w);
4095
- log_allocations();
4096
- }
4097
- }
4098
- }
4099
-
4100
- error("LISTENER: exit!");
4101
-
4102
- close(listener);
4103
- exit(2);
4104
-
4105
- return NULL;
4106
-}
4107
-
4108
-// ----------------------------------------------------------------------------
4109
-// /proc/net/dev processor
4110
-
4111
-#define MAX_PROC_NET_DEV_LINE 4096
4112
-#define MAX_PROC_NET_DEV_IFACE_NAME 1024
4113
-
4114
-int do_proc_net_dev() {
4115
- static int enable_new_interfaces = -1;
4116
- static int do_bandwidth = -1, do_packets = -1, do_errors = -1, do_fifo = -1, do_compressed = -1;
4117
- static FILE *fp = NULL;
4118
-
4119
- if(enable_new_interfaces == -1) enable_new_interfaces = config_get_boolean("plugin:proc:/proc/net/dev", "enable new interfaces detected at runtime", 1);
4120
-
4121
- if(do_bandwidth == -1) do_bandwidth = config_get_boolean("plugin:proc:/proc/net/dev", "bandwidth for all interfaces", 1);
4122
- if(do_packets == -1) do_packets = config_get_boolean("plugin:proc:/proc/net/dev", "packets for all interfaces", 1);
4123
- if(do_errors == -1) do_errors = config_get_boolean("plugin:proc:/proc/net/dev", "errors for all interfaces", 1);
4124
- if(do_fifo == -1) do_fifo = config_get_boolean("plugin:proc:/proc/net/dev", "fifo for all interfaces", 1);
4125
- if(do_compressed == -1) do_compressed = config_get_boolean("plugin:proc:/proc/net/dev", "compressed packets for all interfaces", 1);
4126
-
4127
- char buffer[MAX_PROC_NET_DEV_LINE+1] = "";
4128
- char iface[MAX_PROC_NET_DEV_IFACE_NAME + 1] = "";
4129
- unsigned long long rbytes, rpackets, rerrors, rdrops, rfifo, rframe, rcompressed, rmulticast;
4130
- unsigned long long tbytes, tpackets, terrors, tdrops, tfifo, tcollisions, tcarrier, tcompressed;
4131
-
4132
- int r;
4133
- char *p;
4134
-
4135
- if(fp) {
4136
- if(fseek(fp, 0, SEEK_SET) == -1) {
4137
- error("Re-opening file /proc/net/dev.");
4138
- fclose(fp);
4139
- fp = NULL;
4140
- }
4141
- }
4142
-
4143
- if(!fp) {
4144
- fp = fopen("/proc/net/dev", "r");
4145
- if(!fp) {
4146
- error("Cannot read /proc/net/dev.");
4147
- return 1;
4148
- }
4149
- }
4150
-
4151
- // skip the first two lines
4152
- p = fgets(buffer, MAX_PROC_NET_DEV_LINE, fp);
4153
- p = fgets(buffer, MAX_PROC_NET_DEV_LINE, fp);
4154
-
4155
- // read the rest of the lines
4156
- for(;1;) {
4157
- char *c;
4158
- p = fgets(buffer, MAX_PROC_NET_DEV_LINE, fp);
4159
- if(!p) break;
4160
-
4161
- c = strchr(buffer, ':');
4162
- if(c) *c = '\t';
4163
-
4164
- r = sscanf(buffer, "%s %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
4165
- iface,
4166
- &rbytes, &rpackets, &rerrors, &rdrops, &rfifo, &rframe, &rcompressed, &rmulticast,
4167
- &tbytes, &tpackets, &terrors, &tdrops, &tfifo, &tcollisions, &tcarrier, &tcompressed);
4168
- if(r == EOF) break;
4169
- if(r != 17) {
4170
- error("Cannot read /proc/net/dev line. Expected 17 params, read %d.", r);
4171
- continue;
4172
- }
4173
-
4174
- // check if it is enabled
4175
- {
4176
- char var_name[4096 + 1];
4177
- snprintf(var_name, 4096, "interface %s", iface);
4178
- if(!config_get_boolean("plugin:proc:/proc/net/dev", var_name, enable_new_interfaces)) continue;
4179
- }
4180
-
4181
- RRD_STATS *st;
4182
-
4183
- // --------------------------------------------------------------------
4184
-
4185
- if(do_bandwidth) {
4186
- st = rrd_stats_find_bytype(RRD_TYPE_NET, iface);
4187
- if(!st) {
4188
- st = rrd_stats_create(RRD_TYPE_NET, iface, NULL, iface, "Bandwidth", "kilobits/s", 1000, update_every, CHART_TYPE_AREA);
4189
-
4190
- rrd_stats_dimension_add(st, "received", NULL, 8, 1024 * update_every, RRD_DIMENSION_INCREMENTAL);
4191
- rrd_stats_dimension_add(st, "sent", NULL, -8, 1024 * update_every, RRD_DIMENSION_INCREMENTAL);
4192
- }
4193
- else rrd_stats_next(st);
4194
-
4195
- rrd_stats_dimension_set(st, "received", rbytes);
4196
- rrd_stats_dimension_set(st, "sent", tbytes);
4197
- rrd_stats_done(st);
4198
- }
4199
-
4200
- // --------------------------------------------------------------------
4201
-
4202
- if(do_packets) {
4203
- st = rrd_stats_find_bytype("net_packets", iface);
4204
- if(!st) {
4205
- st = rrd_stats_create("net_packets", iface, NULL, iface, "Packets", "packets/s", 1001, update_every, CHART_TYPE_LINE);
4206
- st->isdetail = 1;
4207
-
4208
- rrd_stats_dimension_add(st, "received", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4209
- rrd_stats_dimension_add(st, "sent", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4210
- }
4211
- else rrd_stats_next(st);
4212
-
4213
- rrd_stats_dimension_set(st, "received", rpackets);
4214
- rrd_stats_dimension_set(st, "sent", tpackets);
4215
- rrd_stats_done(st);
4216
- }
4217
-
4218
- // --------------------------------------------------------------------
4219
-
4220
- if(do_errors) {
4221
- st = rrd_stats_find_bytype("net_errors", iface);
4222
- if(!st) {
4223
- st = rrd_stats_create("net_errors", iface, NULL, iface, "Interface Errors", "errors/s", 1002, update_every, CHART_TYPE_LINE);
4224
- st->isdetail = 1;
4225
-
4226
- rrd_stats_dimension_add(st, "receive", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4227
- rrd_stats_dimension_add(st, "transmit", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4228
- }
4229
- else rrd_stats_next(st);
4230
-
4231
- rrd_stats_dimension_set(st, "receive", rerrors);
4232
- rrd_stats_dimension_set(st, "transmit", terrors);
4233
- rrd_stats_done(st);
4234
- }
4235
-
4236
- // --------------------------------------------------------------------
4237
-
4238
- if(do_fifo) {
4239
- st = rrd_stats_find_bytype("net_fifo", iface);
4240
- if(!st) {
4241
- st = rrd_stats_create("net_fifo", iface, NULL, iface, "Interface Queue", "packets", 1100, update_every, CHART_TYPE_LINE);
4242
- st->isdetail = 1;
4243
-
4244
- rrd_stats_dimension_add(st, "receive", NULL, 1, 1, RRD_DIMENSION_ABSOLUTE);
4245
- rrd_stats_dimension_add(st, "transmit", NULL, -1, 1, RRD_DIMENSION_ABSOLUTE);
4246
- }
4247
- else rrd_stats_next(st);
4248
-
4249
- rrd_stats_dimension_set(st, "receive", rfifo);
4250
- rrd_stats_dimension_set(st, "transmit", tfifo);
4251
- rrd_stats_done(st);
4252
- }
4253
-
4254
- // --------------------------------------------------------------------
4255
-
4256
- if(do_compressed) {
4257
- st = rrd_stats_find_bytype("net_compressed", iface);
4258
- if(!st) {
4259
- st = rrd_stats_create("net_compressed", iface, NULL, iface, "Compressed Packets", "packets/s", 1200, update_every, CHART_TYPE_LINE);
4260
- st->isdetail = 1;
4261
-
4262
- rrd_stats_dimension_add(st, "received", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4263
- rrd_stats_dimension_add(st, "sent", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4264
- }
4265
- else rrd_stats_next(st);
4266
-
4267
- rrd_stats_dimension_set(st, "received", rcompressed);
4268
- rrd_stats_dimension_set(st, "sent", tcompressed);
4269
- rrd_stats_done(st);
4270
- }
4271
- }
4272
-
4273
- return 0;
4274
-}
4275
-
4276
-// ----------------------------------------------------------------------------
4277
-// /proc/diskstats processor
4278
-
4279
-#define MAX_PROC_DISKSTATS_LINE 4096
4280
-#define MAX_PROC_DISKSTATS_DISK_NAME 1024
4281
-
4282
-int do_proc_diskstats() {
4283
- static int enable_new_disks = -1;
4284
- static int do_io = -1, do_ops = -1, do_merged_ops = -1, do_iotime = -1, do_cur_ops = -1;
4285
- static FILE *fp = NULL;
4286
-
4287
- if(enable_new_disks == -1) enable_new_disks = config_get_boolean("plugin:proc:/proc/diskstats", "enable new disks detected at runtime", 1);
4288
-
4289
- if(do_io == -1) do_io = config_get_boolean("plugin:proc:/proc/diskstats", "bandwidth for all disks", 1);
4290
- if(do_ops == -1) do_ops = config_get_boolean("plugin:proc:/proc/diskstats", "operations for all disks", 1);
4291
- if(do_merged_ops == -1) do_merged_ops = config_get_boolean("plugin:proc:/proc/diskstats", "merged operations for all disks", 1);
4292
- if(do_iotime == -1) do_iotime = config_get_boolean("plugin:proc:/proc/diskstats", "i/o time for all disks", 1);
4293
- if(do_cur_ops == -1) do_cur_ops = config_get_boolean("plugin:proc:/proc/diskstats", "current operations for all disks", 1);
4294
-
4295
- char buffer[MAX_PROC_DISKSTATS_LINE+1] = "";
4296
- char disk[MAX_PROC_DISKSTATS_DISK_NAME + 1] = "";
4297
-
4298
- int r;
4299
- char *p;
4300
-
4301
- if(fp) {
4302
- if(fseek(fp, 0, SEEK_SET) == -1) {
4303
- error("Re-opening file /proc/diskstats.");
4304
- fclose(fp);
4305
- fp = NULL;
4306
- }
4307
- }
4308
-
4309
- if(!fp) {
4310
- fp = fopen("/proc/diskstats", "r");
4311
- if(!fp) {
4312
- error("Cannot read /proc/diskstats.");
4313
- return 1;
4314
- }
4315
- }
4316
-
4317
- for(;1;) {
4318
- unsigned long long major = 0, minor = 0,
4319
- reads = 0, reads_merged = 0, readsectors = 0, readms = 0,
4320
- writes = 0, writes_merged = 0, writesectors = 0, writems = 0,
4321
- currentios = 0, iosms = 0, wiosms = 0;
4322
-
4323
- p = fgets(buffer, MAX_PROC_DISKSTATS_LINE, fp);
4324
- if(!p) break;
4325
-
4326
- r = sscanf(buffer, "%llu %llu %s %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
4327
- &major, &minor, disk,
4328
- &reads, &reads_merged, &readsectors, &readms, &writes, &writes_merged, &writesectors, &writems, ¤tios, &iosms, &wiosms
4329
- );
4330
- if(r == EOF) break;
4331
- if(r != 14) {
4332
- error("Cannot read /proc/diskstats line. Expected 14 params, read %d.", r);
4333
- continue;
4334
- }
4335
-
4336
- int def_enabled = 0;
4337
-
4338
- switch(major) {
4339
- case 9: // MDs
4340
- case 43: // network block
4341
- case 144: // nfs
4342
- case 145: // nfs
4343
- case 146: // nfs
4344
- case 199: // veritas
4345
- case 201: // veritas
4346
- case 251: // dm
4347
- def_enabled = enable_new_disks;
4348
- break;
4349
-
4350
- case 48: // RAID
4351
- case 49: // RAID
4352
- case 50: // RAID
4353
- case 51: // RAID
4354
- case 52: // RAID
4355
- case 53: // RAID
4356
- case 54: // RAID
4357
- case 55: // RAID
4358
- case 112: // RAID
4359
- case 136: // RAID
4360
- case 137: // RAID
4361
- case 138: // RAID
4362
- case 139: // RAID
4363
- case 140: // RAID
4364
- case 141: // RAID
4365
- case 142: // RAID
4366
- case 143: // RAID
4367
- case 179: // MMC
4368
- case 180: // USB
4369
- if(minor % 8) def_enabled = 0; // partitions
4370
- else def_enabled = enable_new_disks;
4371
- break;
4372
-
4373
- case 8: // scsi disks
4374
- case 65: // scsi disks
4375
- case 66: // scsi disks
4376
- case 67: // scsi disks
4377
- case 68: // scsi disks
4378
- case 69: // scsi disks
4379
- case 70: // scsi disks
4380
- case 71: // scsi disks
4381
- case 72: // scsi disks
4382
- case 73: // scsi disks
4383
- case 74: // scsi disks
4384
- case 75: // scsi disks
4385
- case 76: // scsi disks
4386
- case 77: // scsi disks
4387
- case 78: // scsi disks
4388
- case 79: // scsi disks
4389
- case 80: // i2o
4390
- case 81: // i2o
4391
- case 82: // i2o
4392
- case 83: // i2o
4393
- case 84: // i2o
4394
- case 85: // i2o
4395
- case 86: // i2o
4396
- case 87: // i2o
4397
- case 101: // hyperdisk
4398
- case 102: // compressed
4399
- case 104: // scsi
4400
- case 105: // scsi
4401
- case 106: // scsi
4402
- case 107: // scsi
4403
- case 108: // scsi
4404
- case 109: // scsi
4405
- case 110: // scsi
4406
- case 111: // scsi
4407
- case 114: // bios raid
4408
- case 116: // ram board
4409
- case 128: // scsi
4410
- case 129: // scsi
4411
- case 130: // scsi
4412
- case 131: // scsi
4413
- case 132: // scsi
4414
- case 133: // scsi
4415
- case 134: // scsi
4416
- case 135: // scsi
4417
- case 153: // raid
4418
- case 202: // xen
4419
- case 256: // flash
4420
- case 257: // flash
4421
- if(minor % 16) def_enabled = 0; // partitions
4422
- else def_enabled = enable_new_disks;
4423
- break;
4424
-
4425
- case 160: // raid
4426
- case 161: // raid
4427
- if(minor % 32) def_enabled = 0; // partitions
4428
- else def_enabled = enable_new_disks;
4429
- break;
4430
-
4431
- case 3: // ide
4432
- case 13: // 8bit ide
4433
- case 22: // ide
4434
- case 33: // ide
4435
- case 34: // ide
4436
- case 56: // ide
4437
- case 57: // ide
4438
- case 88: // ide
4439
- case 89: // ide
4440
- case 90: // ide
4441
- case 91: // ide
4442
- if(minor % 64) def_enabled = 0; // partitions
4443
- else def_enabled = enable_new_disks;
4444
- break;
4445
-
4446
- default:
4447
- def_enabled = 0;
4448
- break;
4449
- }
4450
-
4451
- // check if it is enabled
4452
- {
4453
- char var_name[4096 + 1];
4454
- snprintf(var_name, 4096, "disk %s", disk);
4455
- if(!config_get_boolean("plugin:proc:/proc/diskstats", var_name, def_enabled)) continue;
4456
- }
4457
-
4458
- RRD_STATS *st;
4459
-
4460
- // --------------------------------------------------------------------
4461
-
4462
- if(do_io) {
4463
- st = rrd_stats_find_bytype(RRD_TYPE_DISK, disk);
4464
- if(!st) {
4465
- char tf[FILENAME_MAX + 1], *t;
4466
- char ssfilename[FILENAME_MAX + 1];
4467
- int sector_size = 512;
4468
-
4469
- strncpy(tf, disk, FILENAME_MAX);
4470
- tf[FILENAME_MAX] = '\0';
4471
-
4472
- // replace all / with !
4473
- while((t = strchr(tf, '/'))) *t = '!';
4474
-
4475
- snprintf(ssfilename, FILENAME_MAX, "/sys/block/%s/queue/hw_sector_size", tf);
4476
- FILE *fpss = fopen(ssfilename, "r");
4477
- if(fpss) {
4478
- char ssbuffer[1025];
4479
- char *tmp = fgets(ssbuffer, 1024, fpss);
4480
-
4481
- if(tmp) {
4482
- sector_size = atoi(tmp);
4483
- if(sector_size <= 0) {
4484
- error("Invalid sector size %d for device %s in %s. Assuming 512.", sector_size, disk, ssfilename);
4485
- sector_size = 512;
4486
- }
4487
- }
4488
- else error("Cannot read data for sector size for device %s from %s. Assuming 512.", disk, ssfilename);
4489
-
4490
- fclose(fpss);
4491
- }
4492
- else error("Cannot read sector size for device %s from %s. Assuming 512.", disk, ssfilename);
4493
-
4494
- st = rrd_stats_create(RRD_TYPE_DISK, disk, NULL, disk, "Disk I/O", "kilobytes/s", 2000, update_every, CHART_TYPE_AREA);
4495
-
4496
- rrd_stats_dimension_add(st, "reads", NULL, sector_size, 1024 * update_every, RRD_DIMENSION_INCREMENTAL);
4497
- rrd_stats_dimension_add(st, "writes", NULL, sector_size * -1, 1024 * update_every, RRD_DIMENSION_INCREMENTAL);
4498
- }
4499
- else rrd_stats_next(st);
4500
-
4501
- rrd_stats_dimension_set(st, "reads", readsectors);
4502
- rrd_stats_dimension_set(st, "writes", writesectors);
4503
- rrd_stats_done(st);
4504
- }
4505
-
4506
- // --------------------------------------------------------------------
4507
-
4508
- if(do_ops) {
4509
- st = rrd_stats_find_bytype("disk_ops", disk);
4510
- if(!st) {
4511
- st = rrd_stats_create("disk_ops", disk, NULL, disk, "Disk Operations", "operations/s", 2001, update_every, CHART_TYPE_LINE);
4512
- st->isdetail = 1;
4513
-
4514
- rrd_stats_dimension_add(st, "reads", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4515
- rrd_stats_dimension_add(st, "writes", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4516
- }
4517
- else rrd_stats_next(st);
4518
-
4519
- rrd_stats_dimension_set(st, "reads", reads);
4520
- rrd_stats_dimension_set(st, "writes", writes);
4521
- rrd_stats_done(st);
4522
- }
4523
-
4524
- // --------------------------------------------------------------------
4525
-
4526
- if(do_merged_ops) {
4527
- st = rrd_stats_find_bytype("disk_merged_ops", disk);
4528
- if(!st) {
4529
- st = rrd_stats_create("disk_merged_ops", disk, NULL, disk, "Merged Disk Operations", "operations/s", 2010, update_every, CHART_TYPE_LINE);
4530
- st->isdetail = 1;
4531
-
4532
- rrd_stats_dimension_add(st, "reads", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4533
- rrd_stats_dimension_add(st, "writes", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4534
- }
4535
- else rrd_stats_next(st);
4536
-
4537
- rrd_stats_dimension_set(st, "reads", reads_merged);
4538
- rrd_stats_dimension_set(st, "writes", writes_merged);
4539
- rrd_stats_done(st);
4540
- }
4541
-
4542
- // --------------------------------------------------------------------
4543
-
4544
- if(do_iotime) {
4545
- st = rrd_stats_find_bytype("disk_iotime", disk);
4546
- if(!st) {
4547
- st = rrd_stats_create("disk_iotime", disk, NULL, disk, "Disk I/O Time", "milliseconds/s", 2005, update_every, CHART_TYPE_LINE);
4548
- st->isdetail = 1;
4549
-
4550
- rrd_stats_dimension_add(st, "reads", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4551
- rrd_stats_dimension_add(st, "writes", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4552
- rrd_stats_dimension_add(st, "latency", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4553
- rrd_stats_dimension_add(st, "weighted", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4554
- }
4555
- else rrd_stats_next(st);
4556
-
4557
- rrd_stats_dimension_set(st, "reads", readms);
4558
- rrd_stats_dimension_set(st, "writes", writems);
4559
- rrd_stats_dimension_set(st, "latency", iosms);
4560
- rrd_stats_dimension_set(st, "weighted", wiosms);
4561
- rrd_stats_done(st);
4562
- }
4563
-
4564
- // --------------------------------------------------------------------
4565
-
4566
- if(do_cur_ops) {
4567
- st = rrd_stats_find_bytype("disk_cur_ops", disk);
4568
- if(!st) {
4569
- st = rrd_stats_create("disk_cur_ops", disk, NULL, disk, "Current Disk I/O operations", "operations", 2004, update_every, CHART_TYPE_LINE);
4570
- st->isdetail = 1;
4571
-
4572
- rrd_stats_dimension_add(st, "operations", NULL, 1, 1, RRD_DIMENSION_ABSOLUTE);
4573
- }
4574
- else rrd_stats_next(st);
4575
-
4576
- rrd_stats_dimension_set(st, "operations", currentios);
4577
- rrd_stats_done(st);
4578
- }
4579
- }
4580
-
4581
- return 0;
4582
-}
4583
-
4584
-// ----------------------------------------------------------------------------
4585
-// /proc/net/snmp processor
4586
-
4587
-int do_proc_net_snmp() {
4588
- static int do_ip_packets = -1, do_ip_fragsout = -1, do_ip_fragsin = -1, do_ip_errors = -1,
4589
- do_tcp_sockets = -1, do_tcp_packets = -1, do_tcp_errors = -1, do_tcp_handshake = -1,
4590
- do_udp_packets = -1, do_udp_errors = -1;
4591
- static FILE *fp = NULL;
4592
-
4593
- if(do_ip_packets == -1) do_ip_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 packets", 1);
4594
- if(do_ip_fragsout == -1) do_ip_fragsout = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragrments sent", 1);
4595
- if(do_ip_fragsin == -1) do_ip_fragsin = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 fragments assembly", 1);
4596
- if(do_ip_errors == -1) do_ip_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 errors", 1);
4597
- if(do_tcp_sockets == -1) do_tcp_sockets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP connections", 1);
4598
- if(do_tcp_packets == -1) do_tcp_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP packets", 1);
4599
- if(do_tcp_errors == -1) do_tcp_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP errors", 1);
4600
- if(do_tcp_handshake == -1) do_tcp_handshake = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 TCP handshake issues", 1);
4601
- if(do_udp_packets == -1) do_udp_packets = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDP packets", 1);
4602
- if(do_udp_errors == -1) do_udp_errors = config_get_boolean("plugin:proc:/proc/net/snmp", "ipv4 UDP errors", 1);
4603
-
4604
- char buffer[MAX_PROC_NET_SNMP_LINE+1] = "";
4605
-
4606
- if(fp) {
4607
- if(fseek(fp, 0, SEEK_SET) == -1) {
4608
- error("Re-opening file /proc/net/snmp.");
4609
- fclose(fp);
4610
- fp = NULL;
4611
- }
4612
- }
4613
-
4614
- if(!fp) {
4615
- fp = fopen("/proc/net/snmp", "r");
4616
- if(!fp) {
4617
- error("Cannot read /proc/net/snmp.");
4618
- return 1;
4619
- }
4620
- }
4621
-
4622
- RRD_STATS *st;
4623
-
4624
- for(;1;) {
4625
- char *p = fgets(buffer, MAX_PROC_NET_SNMP_LINE, fp);
4626
- if(!p) break;
4627
-
4628
- if(strncmp(p, "Ip: ", 4) == 0) {
4629
- // skip the header line, read the data
4630
- p = fgets(buffer, MAX_PROC_NET_SNMP_LINE, fp);
4631
- if(!p) break;
4632
-
4633
- if(strncmp(p, "Ip: ", 4) != 0) {
4634
- error("Cannot read IP line from /proc/net/snmp.");
4635
- break;
4636
- }
4637
-
4638
- // see also http://net-snmp.sourceforge.net/docs/mibs/ip.html
4639
- unsigned long long Forwarding, DefaultTTL, InReceives, InHdrErrors, InAddrErrors, ForwDatagrams, InUnknownProtos, InDiscards, InDelivers,
4640
- OutRequests, OutDiscards, OutNoRoutes, ReasmTimeout, ReasmReqds, ReasmOKs, ReasmFails, FragOKs, FragFails, FragCreates;
4641
-
4642
- int r = sscanf(&buffer[4], "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
4643
- &Forwarding, &DefaultTTL, &InReceives, &InHdrErrors, &InAddrErrors, &ForwDatagrams, &InUnknownProtos, &InDiscards, &InDelivers,
4644
- &OutRequests, &OutDiscards, &OutNoRoutes, &ReasmTimeout, &ReasmReqds, &ReasmOKs, &ReasmFails, &FragOKs, &FragFails, &FragCreates);
4645
-
4646
- if(r == EOF) break;
4647
- if(r != 19) error("Cannot read /proc/net/snmp IP line. Expected 19 params, read %d.", r);
4648
-
4649
- // --------------------------------------------------------------------
4650
-
4651
- if(do_ip_packets) {
4652
- st = rrd_stats_find(RRD_TYPE_NET_SNMP ".packets");
4653
- if(!st) {
4654
- st = rrd_stats_create(RRD_TYPE_NET_SNMP, "packets", NULL, RRD_TYPE_NET_SNMP, "IPv4 Packets", "packets/s", 3000, update_every, CHART_TYPE_LINE);
4655
-
4656
- rrd_stats_dimension_add(st, "received", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4657
- rrd_stats_dimension_add(st, "sent", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4658
- rrd_stats_dimension_add(st, "forwarded", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4659
- }
4660
- else rrd_stats_next(st);
4661
-
4662
- rrd_stats_dimension_set(st, "sent", OutRequests);
4663
- rrd_stats_dimension_set(st, "received", InReceives);
4664
- rrd_stats_dimension_set(st, "forwarded", ForwDatagrams);
4665
- rrd_stats_done(st);
4666
- }
4667
-
4668
- // --------------------------------------------------------------------
4669
-
4670
- if(do_ip_fragsout) {
4671
- st = rrd_stats_find(RRD_TYPE_NET_SNMP ".fragsout");
4672
- if(!st) {
4673
- st = rrd_stats_create(RRD_TYPE_NET_SNMP, "fragsout", NULL, RRD_TYPE_NET_SNMP, "IPv4 Fragments Sent", "packets/s", 3010, update_every, CHART_TYPE_LINE);
4674
- st->isdetail = 1;
4675
-
4676
- rrd_stats_dimension_add(st, "ok", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4677
- rrd_stats_dimension_add(st, "failed", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4678
- rrd_stats_dimension_add(st, "all", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4679
- }
4680
- else rrd_stats_next(st);
4681
-
4682
- rrd_stats_dimension_set(st, "ok", FragOKs);
4683
- rrd_stats_dimension_set(st, "failed", FragFails);
4684
- rrd_stats_dimension_set(st, "all", FragCreates);
4685
- rrd_stats_done(st);
4686
- }
4687
-
4688
- // --------------------------------------------------------------------
4689
-
4690
- if(do_ip_fragsin) {
4691
- st = rrd_stats_find(RRD_TYPE_NET_SNMP ".fragsin");
4692
- if(!st) {
4693
- st = rrd_stats_create(RRD_TYPE_NET_SNMP, "fragsin", NULL, RRD_TYPE_NET_SNMP, "IPv4 Fragments Reassembly", "packets/s", 3011, update_every, CHART_TYPE_LINE);
4694
- st->isdetail = 1;
4695
-
4696
- rrd_stats_dimension_add(st, "ok", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4697
- rrd_stats_dimension_add(st, "failed", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4698
- rrd_stats_dimension_add(st, "all", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4699
- }
4700
- else rrd_stats_next(st);
4701
-
4702
- rrd_stats_dimension_set(st, "ok", ReasmOKs);
4703
- rrd_stats_dimension_set(st, "failed", ReasmFails);
4704
- rrd_stats_dimension_set(st, "all", ReasmReqds);
4705
- rrd_stats_done(st);
4706
- }
4707
-
4708
- // --------------------------------------------------------------------
4709
-
4710
- if(do_ip_errors) {
4711
- st = rrd_stats_find(RRD_TYPE_NET_SNMP ".errors");
4712
- if(!st) {
4713
- st = rrd_stats_create(RRD_TYPE_NET_SNMP, "errors", NULL, RRD_TYPE_NET_SNMP, "IPv4 Errors", "packets/s", 3002, update_every, CHART_TYPE_LINE);
4714
- st->isdetail = 1;
4715
-
4716
- rrd_stats_dimension_add(st, "InDiscards", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4717
- rrd_stats_dimension_add(st, "OutDiscards", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4718
-
4719
- rrd_stats_dimension_add(st, "InHdrErrors", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4720
- rrd_stats_dimension_add(st, "InAddrErrors", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4721
- rrd_stats_dimension_add(st, "InUnknownProtos", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4722
-
4723
- rrd_stats_dimension_add(st, "OutNoRoutes", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4724
- }
4725
- else rrd_stats_next(st);
4726
-
4727
- rrd_stats_dimension_set(st, "InDiscards", InDiscards);
4728
- rrd_stats_dimension_set(st, "OutDiscards", OutDiscards);
4729
- rrd_stats_dimension_set(st, "InHdrErrors", InHdrErrors);
4730
- rrd_stats_dimension_set(st, "InAddrErrors", InAddrErrors);
4731
- rrd_stats_dimension_set(st, "InUnknownProtos", InUnknownProtos);
4732
- rrd_stats_dimension_set(st, "OutNoRoutes", OutNoRoutes);
4733
- rrd_stats_done(st);
4734
- }
4735
- }
4736
- else if(strncmp(p, "Tcp: ", 5) == 0) {
4737
- // skip the header line, read the data
4738
- p = fgets(buffer, MAX_PROC_NET_SNMP_LINE, fp);
4739
- if(!p) break;
4740
-
4741
- if(strncmp(p, "Tcp: ", 5) != 0) {
4742
- error("Cannot read TCP line from /proc/net/snmp.");
4743
- break;
4744
- }
4745
-
4746
- unsigned long long RtoAlgorithm, RtoMin, RtoMax, MaxConn, ActiveOpens, PassiveOpens, AttemptFails, EstabResets,
4747
- CurrEstab, InSegs, OutSegs, RetransSegs, InErrs, OutRsts;
4748
-
4749
- int r = sscanf(&buffer[5], "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
4750
- &RtoAlgorithm, &RtoMin, &RtoMax, &MaxConn, &ActiveOpens, &PassiveOpens, &AttemptFails, &EstabResets, &CurrEstab, &InSegs, &OutSegs, &RetransSegs, &InErrs, &OutRsts);
4751
-
4752
- if(r == EOF) break;
4753
- if(r != 14) error("Cannot read /proc/net/snmp TCP line. Expected 14 params, read %d.", r);
4754
-
4755
- // --------------------------------------------------------------------
4756
-
4757
- // see http://net-snmp.sourceforge.net/docs/mibs/tcp.html
4758
- if(do_tcp_sockets) {
4759
- st = rrd_stats_find(RRD_TYPE_NET_SNMP ".tcpsock");
4760
- if(!st) {
4761
- st = rrd_stats_create(RRD_TYPE_NET_SNMP, "tcpsock", NULL, "tcp", "IPv4 TCP Connections", "active connections", 2500, update_every, CHART_TYPE_LINE);
4762
-
4763
- rrd_stats_dimension_add(st, "connections", NULL, 1, 1, RRD_DIMENSION_ABSOLUTE);
4764
- }
4765
- else rrd_stats_next(st);
4766
-
4767
- rrd_stats_dimension_set(st, "connections", CurrEstab);
4768
- rrd_stats_done(st);
4769
- }
4770
-
4771
- // --------------------------------------------------------------------
4772
-
4773
- if(do_tcp_packets) {
4774
- st = rrd_stats_find(RRD_TYPE_NET_SNMP ".tcppackets");
4775
- if(!st) {
4776
- st = rrd_stats_create(RRD_TYPE_NET_SNMP, "tcppackets", NULL, "tcp", "IPv4 TCP Packets", "packets/s", 2600, update_every, CHART_TYPE_LINE);
4777
-
4778
- rrd_stats_dimension_add(st, "received", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4779
- rrd_stats_dimension_add(st, "sent", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4780
- }
4781
- else rrd_stats_next(st);
4782
-
4783
- rrd_stats_dimension_set(st, "received", InSegs);
4784
- rrd_stats_dimension_set(st, "sent", OutSegs);
4785
- rrd_stats_done(st);
4786
- }
4787
-
4788
- // --------------------------------------------------------------------
4789
-
4790
- if(do_tcp_errors) {
4791
- st = rrd_stats_find(RRD_TYPE_NET_SNMP ".tcperrors");
4792
- if(!st) {
4793
- st = rrd_stats_create(RRD_TYPE_NET_SNMP, "tcperrors", NULL, "tcp", "IPv4 TCP Errors", "packets/s", 2700, update_every, CHART_TYPE_LINE);
4794
- st->isdetail = 1;
4795
-
4796
- rrd_stats_dimension_add(st, "InErrs", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4797
- rrd_stats_dimension_add(st, "RetransSegs", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4798
- }
4799
- else rrd_stats_next(st);
4800
-
4801
- rrd_stats_dimension_set(st, "InErrs", InErrs);
4802
- rrd_stats_dimension_set(st, "RetransSegs", RetransSegs);
4803
- rrd_stats_done(st);
4804
- }
4805
-
4806
- // --------------------------------------------------------------------
4807
-
4808
- if(do_tcp_handshake) {
4809
- st = rrd_stats_find(RRD_TYPE_NET_SNMP ".tcphandshake");
4810
- if(!st) {
4811
- st = rrd_stats_create(RRD_TYPE_NET_SNMP, "tcphandshake", NULL, "tcp", "IPv4 TCP Handshake Issues", "events/s", 2900, update_every, CHART_TYPE_LINE);
4812
- st->isdetail = 1;
4813
-
4814
- rrd_stats_dimension_add(st, "EstabResets", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4815
- rrd_stats_dimension_add(st, "OutRsts", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4816
- rrd_stats_dimension_add(st, "ActiveOpens", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4817
- rrd_stats_dimension_add(st, "PassiveOpens", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4818
- rrd_stats_dimension_add(st, "AttemptFails", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4819
- }
4820
- else rrd_stats_next(st);
4821
-
4822
- rrd_stats_dimension_set(st, "EstabResets", EstabResets);
4823
- rrd_stats_dimension_set(st, "OutRsts", OutRsts);
4824
- rrd_stats_dimension_set(st, "ActiveOpens", ActiveOpens);
4825
- rrd_stats_dimension_set(st, "PassiveOpens", PassiveOpens);
4826
- rrd_stats_dimension_set(st, "AttemptFails", AttemptFails);
4827
- rrd_stats_done(st);
4828
- }
4829
- }
4830
- else if(strncmp(p, "Udp: ", 5) == 0) {
4831
- // skip the header line, read the data
4832
- p = fgets(buffer, MAX_PROC_NET_SNMP_LINE, fp);
4833
- if(!p) break;
4834
-
4835
- if(strncmp(p, "Udp: ", 5) != 0) {
4836
- error("Cannot read UDP line from /proc/net/snmp.");
4837
- break;
4838
- }
4839
-
4840
- unsigned long long InDatagrams, NoPorts, InErrors, OutDatagrams, RcvbufErrors, SndbufErrors;
4841
-
4842
- int r = sscanf(&buffer[5], "%llu %llu %llu %llu %llu %llu\n",
4843
- &InDatagrams, &NoPorts, &InErrors, &OutDatagrams, &RcvbufErrors, &SndbufErrors);
4844
-
4845
- if(r == EOF) break;
4846
- if(r != 6) error("Cannot read /proc/net/snmp UDP line. Expected 6 params, read %d.", r);
4847
-
4848
- // --------------------------------------------------------------------
4849
-
4850
- // see http://net-snmp.sourceforge.net/docs/mibs/udp.html
4851
- if(do_udp_packets) {
4852
- st = rrd_stats_find(RRD_TYPE_NET_SNMP ".udppackets");
4853
- if(!st) {
4854
- st = rrd_stats_create(RRD_TYPE_NET_SNMP, "udppackets", NULL, "udp", "IPv4 UDP Packets", "packets/s", 2601, update_every, CHART_TYPE_LINE);
4855
-
4856
- rrd_stats_dimension_add(st, "received", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4857
- rrd_stats_dimension_add(st, "sent", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4858
- }
4859
- else rrd_stats_next(st);
4860
-
4861
- rrd_stats_dimension_set(st, "received", InDatagrams);
4862
- rrd_stats_dimension_set(st, "sent", OutDatagrams);
4863
- rrd_stats_done(st);
4864
- }
4865
-
4866
- // --------------------------------------------------------------------
4867
-
4868
- if(do_udp_errors) {
4869
- st = rrd_stats_find(RRD_TYPE_NET_SNMP ".udperrors");
4870
- if(!st) {
4871
- st = rrd_stats_create(RRD_TYPE_NET_SNMP, "udperrors", NULL, "udp", "IPv4 UDP Errors", "events/s", 2701, update_every, CHART_TYPE_LINE);
4872
- st->isdetail = 1;
4873
-
4874
- rrd_stats_dimension_add(st, "RcvbufErrors", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4875
- rrd_stats_dimension_add(st, "SndbufErrors", NULL, -1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4876
- rrd_stats_dimension_add(st, "InErrors", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4877
- rrd_stats_dimension_add(st, "NoPorts", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4878
- }
4879
- else rrd_stats_next(st);
4880
-
4881
- rrd_stats_dimension_set(st, "InErrors", InErrors);
4882
- rrd_stats_dimension_set(st, "NoPorts", NoPorts);
4883
- rrd_stats_dimension_set(st, "RcvbufErrors", RcvbufErrors);
4884
- rrd_stats_dimension_set(st, "SndbufErrors", SndbufErrors);
4885
- rrd_stats_done(st);
4886
- }
4887
- }
4888
- }
4889
-
4890
- return 0;
4891
-}
4892
-
4893
-// ----------------------------------------------------------------------------
4894
-// /proc/net/netstat processor
4895
-
4896
-int do_proc_net_netstat() {
4897
- static int do_bandwidth = -1, do_inerrors = -1, do_mcast = -1, do_bcast = -1, do_mcast_p = -1, do_bcast_p = -1;
4898
- static FILE *fp = NULL;
4899
-
4900
- if(do_bandwidth == -1) do_bandwidth = config_get_boolean("plugin:proc:/proc/net/netstat", "bandwidth", 1);
4901
- if(do_inerrors == -1) do_inerrors = config_get_boolean("plugin:proc:/proc/net/netstat", "input errors", 1);
4902
- if(do_mcast == -1) do_mcast = config_get_boolean("plugin:proc:/proc/net/netstat", "multicast bandwidth", 1);
4903
- if(do_bcast == -1) do_bcast = config_get_boolean("plugin:proc:/proc/net/netstat", "broadcast bandwidth", 1);
4904
- if(do_mcast_p == -1) do_mcast_p = config_get_boolean("plugin:proc:/proc/net/netstat", "multicast packets", 1);
4905
- if(do_bcast_p == -1) do_bcast_p = config_get_boolean("plugin:proc:/proc/net/netstat", "broadcast packets", 1);
4906
-
4907
- char buffer[MAX_PROC_NET_SNMP_LINE+1] = "";
4908
-
4909
- if(fp) {
4910
- if(fseek(fp, 0, SEEK_SET) == -1) {
4911
- error("Re-opening file /proc/net/netstat.");
4912
- fclose(fp);
4913
- fp = NULL;
4914
- }
4915
- }
4916
-
4917
- if(!fp) {
4918
- fp = fopen("/proc/net/netstat", "r");
4919
- if(!fp) {
4920
- error("Cannot read /proc/net/netstat.");
4921
- return 1;
4922
- }
4923
- }
4924
-
4925
- for(;1;) {
4926
- char *p = fgets(buffer, MAX_PROC_NET_SNMP_LINE, fp);
4927
- if(!p) break;
4928
-
4929
- if(strncmp(p, "IpExt: ", 7) == 0) {
4930
- // skip the header line, read the data
4931
- p = fgets(buffer, MAX_PROC_NET_SNMP_LINE, fp);
4932
- if(!p) break;
4933
-
4934
- if(strncmp(p, "IpExt: ", 7) != 0) {
4935
- error("Cannot read IpExt line from /proc/net/netstat.");
4936
- break;
4937
- }
4938
-
4939
- unsigned long long
4940
- InNoRoutes = 0, InTruncatedPkts = 0,
4941
- InOctets = 0, InMcastPkts = 0, InBcastPkts = 0, InMcastOctets = 0, InBcastOctets = 0,
4942
- OutOctets = 0, OutMcastPkts = 0, OutBcastPkts = 0, OutMcastOctets = 0, OutBcastOctets = 0;
4943
-
4944
- int r = sscanf(&buffer[7], "%llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu %llu\n",
4945
- &InNoRoutes, &InTruncatedPkts, &InMcastPkts, &OutMcastPkts, &InBcastPkts, &OutBcastPkts,
4946
- &InOctets, &OutOctets, &InMcastOctets, &OutMcastOctets, &InBcastOctets, &OutBcastOctets);
4947
-
4948
- if(r == EOF) break;
4949
- if(r != 12) {
4950
- error("Cannot read /proc/net/netstat IpExt line. Expected 12 params, read %d.", r);
4951
- continue;
4952
- }
4953
-
4954
- RRD_STATS *st;
4955
-
4956
- // --------------------------------------------------------------------
4957
-
4958
- if(do_bandwidth) {
4959
- st = rrd_stats_find("system.ipv4");
4960
- if(!st) {
4961
- st = rrd_stats_create("system", "ipv4", NULL, "ipv4", "IPv4 Bandwidth", "kilobits/s", 2000, update_every, CHART_TYPE_AREA);
4962
-
4963
- rrd_stats_dimension_add(st, "received", NULL, 8, 1024 * update_every, RRD_DIMENSION_INCREMENTAL);
4964
- rrd_stats_dimension_add(st, "sent", NULL, -8, 1024 * update_every, RRD_DIMENSION_INCREMENTAL);
4965
- }
4966
- else rrd_stats_next(st);
4967
-
4968
- rrd_stats_dimension_set(st, "sent", OutOctets);
4969
- rrd_stats_dimension_set(st, "received", InOctets);
4970
- rrd_stats_done(st);
4971
- }
4972
-
4973
- // --------------------------------------------------------------------
4974
-
4975
- if(do_inerrors) {
4976
- st = rrd_stats_find("ipv4.inerrors");
4977
- if(!st) {
4978
- st = rrd_stats_create("ipv4", "inerrors", NULL, "ipv4", "IPv4 Input Errors", "packets/s", 4000, update_every, CHART_TYPE_LINE);
4979
- st->isdetail = 1;
4980
-
4981
- rrd_stats_dimension_add(st, "noroutes", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4982
- rrd_stats_dimension_add(st, "trunkated", NULL, 1, 1 * update_every, RRD_DIMENSION_INCREMENTAL);
4983
- }
4984
- else rrd_stats_next(st);
4985
-
4986
- rrd_stats_dimension_set(st, "noroutes", InNoRoutes);
4987
- rrd_stats_dimension_set(st, "trunkated", InTruncatedPkts);
4988
- rrd_stats_done(st);
4989
- }
4990
-
4991
- // --------------------------------------------------------------------
4992
-
4993
- if(do_mcast) {
4994
- st = rrd_stats_find("ipv4.mcast");
4995
- if(!st) {
4996
- st = rrd_stats_create("ipv4", "mcast", NULL, "ipv4", "IPv4 Multicast Bandwidth", "kilobits/s", 9000, update_every, CHART_TYPE_AREA);
4997
- st->isdetail = 1;
4998
-
4999
- rrd_stats_dimension_add(st, "received", NULL, 8, 1024 * update_every, RRD_DIMENSION_INCREMENTAL);
This file is too large to show in full.
src/rrd2json.c
+29
-7
@@ -835,7 +835,7 @@ static void rrdr2json(RRDR *r, BUFFER *wb, uint32_t options, int datatable)
835
//info("RRD2JSON(): %s: END", r->st->id);
836
}
837
838
-static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startline, const char *separator, const char *endline)
838
+static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startline, const char *separator, const char *endline, const char *betweenlines)
839
{
840
//info("RRD2CSV(): %s: BEGIN", r->st->id);
841
long c, i;
@@ -848,10 +848,14 @@ static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startlin
848
849
if(!i) {
850
buffer_strcat(wb, startline);
851
+ if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
852
buffer_strcat(wb, "time");
853
+ if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
854
}
855
buffer_strcat(wb, separator);
856
+ if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
857
buffer_strcat(wb, d->name);
858
+ if(options & RRDR_OPTION_LABEL_QUOTES) buffer_strcat(wb, "\"");
859
i++;
860
}
861
buffer_strcat(wb, endline);
@@ -873,6 +877,7 @@ static void rrdr2csv(RRDR *r, BUFFER *wb, uint32_t options, const char *startlin
877
calculated_number *cn = &r->v[ i * r->d ];
878
uint8_t *co = &r->o[ i * r->d ];
879
880
+ buffer_strcat(wb, betweenlines);
881
buffer_strcat(wb, startline);
882
883
time_t now = r->t[i];
@@ -1470,12 +1475,29 @@ int rrd2format(RRDSET *st, BUFFER *wb, BUFFER *dimensions, uint32_t format, long
1475
if(options & RRDR_OPTION_JSON_WRAP) {
1476
wb->contenttype = CT_APPLICATION_JSON;
1477
rrdr_json_wrapper_begin(r, wb, format, options, 1);
1473
- rrdr2csv(r, wb, options, "", ",", "\\n");
1478
+ rrdr2csv(r, wb, options, "", ",", "\\n", "");
1479
rrdr_json_wrapper_end(r, wb, format, options, 1);
1480
}
1481
else {
1482
wb->contenttype = CT_TEXT_PLAIN;
1478
- rrdr2csv(r, wb, options, "", ",", "\r\n");
1483
+ rrdr2csv(r, wb, options, "", ",", "\r\n", "");
1484
+ }
1485
+ break;
1486
+
1487
+ case DATASOURCE_CSV_JSON_ARRAY:
1488
+ wb->contenttype = CT_APPLICATION_JSON;
1489
+ if(options & RRDR_OPTION_JSON_WRAP) {
1490
+ rrdr_json_wrapper_begin(r, wb, format, options, 0);
1491
+ buffer_strcat(wb, "[\n");
1492
+ rrdr2csv(r, wb, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n");
1493
+ buffer_strcat(wb, "\n]");
1494
+ rrdr_json_wrapper_end(r, wb, format, options, 0);
1495
+ }
1496
+ else {
1497
+ wb->contenttype = CT_TEXT_PLAIN;
1498
+ buffer_strcat(wb, "[\n");
1499
+ rrdr2csv(r, wb, options + RRDR_OPTION_LABEL_QUOTES, "[", ",", "]", ",\n");
1500
+ buffer_strcat(wb, "\n]");
1501
}
1502
break;
1503
@@ -1483,12 +1505,12 @@ int rrd2format(RRDSET *st, BUFFER *wb, BUFFER *dimensions, uint32_t format, long
1505
if(options & RRDR_OPTION_JSON_WRAP) {
1506
wb->contenttype = CT_APPLICATION_JSON;
1507
rrdr_json_wrapper_begin(r, wb, format, options, 1);
1486
- rrdr2csv(r, wb, options, "", "\t", "\\n");
1508
+ rrdr2csv(r, wb, options, "", "\t", "\\n", "");
1509
rrdr_json_wrapper_end(r, wb, format, options, 1);
1510
}
1511
else {
1512
wb->contenttype = CT_TEXT_PLAIN;
1491
- rrdr2csv(r, wb, options, "", "\t", "\r\n");
1513
+ rrdr2csv(r, wb, options, "", "\t", "\r\n", "");
1514
}
1515
break;
1516
@@ -1497,14 +1519,14 @@ int rrd2format(RRDSET *st, BUFFER *wb, BUFFER *dimensions, uint32_t format, long
1519
wb->contenttype = CT_APPLICATION_JSON;
1520
rrdr_json_wrapper_begin(r, wb, format, options, 1);
1521
buffer_strcat(wb, "<html>\\n<center>\\n<table border=\\\"0\\\" cellpadding=\\\"5\\\" cellspacing=\\\"5\\\">\\n");
1500
- rrdr2csv(r, wb, options, "<tr><td>", "</td><td>", "</td></tr>\\n");
1522
+ rrdr2csv(r, wb, options, "<tr><td>", "</td><td>", "</td></tr>\\n", "");
1523
buffer_strcat(wb, "</table>\\n</center>\\n</html>\\n");
1524
rrdr_json_wrapper_end(r, wb, format, options, 1);
1525
}
1526
else {
1527
wb->contenttype = CT_TEXT_HTML;
1528
buffer_strcat(wb, "<html>\n<center>\n<table border=\"0\" cellpadding=\"5\" cellspacing=\"5\">\n");
1507
- rrdr2csv(r, wb, options, "<tr><td>", "</td><td>", "</td></tr>\n");
1529
+ rrdr2csv(r, wb, options, "<tr><td>", "</td><td>", "</td></tr>\n", "");
1530
buffer_strcat(wb, "</table>\n</center>\n</html>\n");
1531
}
1532
break;
src/rrd2json.h
+3
@@ -21,6 +21,7 @@ extern char *hostname;
21
#define DATASOURCE_HTML 7
22
#define DATASOURCE_JS_ARRAY 8
23
#define DATASOURCE_SSV_COMMA 9
24
+#define DATASOURCE_CSV_JSON_ARRAY 10
25
26
#define DATASOURCE_FORMAT_JSON "json"
27
#define DATASOURCE_FORMAT_DATATABLE_JSON "datatable"
@@ -32,6 +33,7 @@ extern char *hostname;
33
#define DATASOURCE_FORMAT_HTML "html"
34
#define DATASOURCE_FORMAT_JS_ARRAY "array"
35
#define DATASOURCE_FORMAT_SSV_COMMA "ssvcomma"
36
+#define DATASOURCE_FORMAT_CSV_JSON_ARRAY "csvjsonarray"
37
38
#define GROUP_AVERAGE 0
39
#define GROUP_MAX 1
@@ -47,6 +49,7 @@ extern char *hostname;
49
#define RRDR_OPTION_OBJECTSROWS 0x00000080 // each row of values should be an object, not an array
50
#define RRDR_OPTION_GOOGLE_JSON 0x00000100 // comply with google JSON/JSONP specs
51
#define RRDR_OPTION_JSON_WRAP 0x00000200 // wrap the response in a JSON header with info about the result
52
+#define RRDR_OPTION_LABEL_QUOTES 0x00000400 // in CSV output, wrap header labels in double quotes
53
54
extern void rrd_stats_api_v1_chart(RRDSET *st, BUFFER *wb);
55
extern void rrd_stats_api_v1_charts(BUFFER *wb);
src/web_client.c
+3
@@ -468,6 +468,9 @@ uint32_t web_client_api_request_v1_data_format(char *name)
468
else if(!strcmp(name, DATASOURCE_FORMAT_SSV_COMMA)) // ssvcomma
469
return DATASOURCE_SSV_COMMA;
470
471
+ else if(!strcmp(name, DATASOURCE_FORMAT_CSV_JSON_ARRAY)) // csvjsonarray
472
+ return DATASOURCE_CSV_JSON_ARRAY;
473
+
474
return DATASOURCE_JSON;
475
}
476
web/Makefile.am
+3
@@ -38,6 +38,8 @@ dist_weblib_DATA = \
38
lib/ElementQueries.js \
39
lib/ResizeSensor.js \
40
lib/bootstrap-toggle.min.js \
41
+ lib/c3.min.js \
42
+ lib/d3.min.js \
43
$(NULL)
44
45
webcssdir=$(webdir)/css
@@ -47,6 +49,7 @@ dist_webcss_DATA = \
49
css/bootstrap-theme.min.css \
50
css/font-awesome.min.css \
51
css/bootstrap-toggle.min.css \
52
+ css/c3.min.css \
53
$(NULL)
54
55
webfontsdir=$(webdir)/fonts
web/css/c3.min.css
new
+1
@@ -0,0 +1 @@
1
+.c3 svg{font:10px sans-serif;-webkit-tap-highlight-color:transparent}.c3 line,.c3 path{fill:none;stroke:#000}.c3 text{-webkit-user-select:none;-moz-user-select:none;user-select:none}.c3-bars path,.c3-event-rect,.c3-legend-item-tile,.c3-xgrid-focus,.c3-ygrid{shape-rendering:crispEdges}.c3-chart-arc path{stroke:#fff}.c3-chart-arc text{fill:#fff;font-size:13px}.c3-grid line{stroke:#aaa}.c3-grid text{fill:#aaa}.c3-xgrid,.c3-ygrid{stroke-dasharray:3 3}.c3-text.c3-empty{fill:gray;font-size:2em}.c3-line{stroke-width:1px}.c3-circle._expanded_{stroke-width:1px;stroke:#fff}.c3-selected-circle{fill:#fff;stroke-width:2px}.c3-bar{stroke-width:0}.c3-bar._expanded_{fill-opacity:.75}.c3-target.c3-focused{opacity:1}.c3-target.c3-focused path.c3-line,.c3-target.c3-focused path.c3-step{stroke-width:2px}.c3-target.c3-defocused{opacity:.3!important}.c3-region{fill:#4682b4;fill-opacity:.1}.c3-brush .extent{fill-opacity:.1}.c3-legend-item{font-size:12px}.c3-legend-item-hidden{opacity:.15}.c3-legend-background{opacity:.75;fill:#fff;stroke:#d3d3d3;stroke-width:1}.c3-title{font:14px sans-serif}.c3-tooltip-container{z-index:10}.c3-tooltip{border-collapse:collapse;border-spacing:0;background-color:#fff;empty-cells:show;-webkit-box-shadow:7px 7px 12px -9px #777;-moz-box-shadow:7px 7px 12px -9px #777;box-shadow:7px 7px 12px -9px #777;opacity:.9}.c3-tooltip tr{border:1px solid #CCC}.c3-tooltip th{background-color:#aaa;font-size:14px;padding:2px 5px;text-align:left;color:#FFF}.c3-tooltip td{font-size:13px;padding:3px 6px;background-color:#fff;border-left:1px dotted #999}.c3-tooltip td>span{display:inline-block;width:10px;height:10px;margin-right:6px}.c3-tooltip td.value{text-align:right}.c3-area{stroke-width:0;opacity:.2}.c3-chart-arcs-title{dominant-baseline:middle;font-size:1.3em}.c3-chart-arcs .c3-chart-arcs-background{fill:#e0e0e0;stroke:none}.c3-chart-arcs .c3-chart-arcs-gauge-unit{fill:#000;font-size:16px}.c3-chart-arcs .c3-chart-arcs-gauge-max,.c3-chart-arcs .c3-chart-arcs-gauge-min{fill:#777}.c3-chart-arc .c3-gauge-value{fill:#000}
\ No newline at end of file
web/dashboard.css
+6
-4
@@ -340,18 +340,20 @@ html {
340
display: inline-block;
341
position: absolute;
342
float: left;
343
- width: 100%;
343
+ width: 64%;
344
+ margin-left: 18%;
345
text-align: center;
346
color: #999999;
346
- font-weight: bold;
347
+ font-weight: normal;
348
}
349
350
.easyPieChartUnits {
351
display: inline-block;
352
position: absolute;
353
float: left;
353
- width: 100%;
354
+ width: 60%;
355
+ margin-left: 20%;
356
text-align: center;
355
- color: #333333;
357
+ color: #999999;
358
font-weight: normal;
359
}
web/dashboard.html
+129
-1
@@ -340,6 +340,87 @@ Sparklines using dygraphs
340
341
342
343
+<hr>
344
+<h1>EasyPieChart</h1>
345
+<br/>
346
+<div style="width: 33%; display: inline-block;">
347
+ <div style="display: inline-block; position: relative;">
348
+ <div data-netdata="system.processes"
349
+ data-chart-library="easypiechart"
350
+ data-width="200"
351
+ data-height="200"
352
+ data-after="-300"
353
+ data-points="300"
354
+ data-dt-element-name="time601"
355
+ ></div>
356
+ <br/>
357
+ <small>rendered in <span id="time601">X</span> ms</small>
358
+ </div>
359
+ <div style="display: inline-block; position: relative;">
360
+ <div data-netdata="system.processes"
361
+ data-chart-library="easypiechart"
362
+ data-width="150"
363
+ data-height="150"
364
+ data-after="-300"
365
+ data-points="150"
366
+ data-dt-element-name="time601a"
367
+ ></div>
368
+ <br/>
369
+ <small>rendered in <span id="time601a">X</span> ms</small>
370
+ </div>
371
+</div>
372
+<div style="width: 33%; display: inline-block;">
373
+ <div style="display: inline-block; position: relative;">
374
+ <div data-netdata="system.ipv4"
375
+ data-chart-library="easypiechart"
376
+ data-width="200"
377
+ data-height="200"
378
+ data-after="-300"
379
+ data-points="300"
380
+ data-dt-element-name="time602"
381
+ ></div>
382
+ <br/>
383
+ <small>rendered in <span id="time602">X</span> ms</small>
384
+ </div>
385
+ <div style="display: inline-block; position: relative;">
386
+ <div data-netdata="system.ipv4"
387
+ data-chart-library="easypiechart"
388
+ data-width="100"
389
+ data-height="100"
390
+ data-after="-300"
391
+ data-points="150"
392
+ data-dt-element-name="time602a"
393
+ ></div>
394
+ <br/>
395
+ <small>rendered in <span id="time602a">X</span> ms</small>
396
+ </div>
397
+</div>
398
+<div style="width: 33%; display: inline-block;">
399
+ <div style="display: inline-block; position: relative;">
400
+ <div data-netdata="system.cpu"
401
+ data-chart-library="easypiechart"
402
+ data-width="200"
403
+ data-height="200"
404
+ data-after="-300"
405
+ data-points="300"
406
+ data-dt-element-name="time603"
407
+ ></div>
408
+ <br/>
409
+ <small>rendered in <span id="time603">X</span> ms</small>
410
+ </div>
411
+ <div style="display: inline-block; position: relative;">
412
+ <div data-netdata="system.cpu"
413
+ data-chart-library="easypiechart"
414
+ data-width="75"
415
+ data-height="75"
416
+ data-after="-300"
417
+ data-points="150"
418
+ data-dt-element-name="time603a"
419
+ ></div>
420
+ <br/>
421
+ <small>rendered in <span id="time603a">X</span> ms</small>
422
+ </div>
423
+</div>
424
425
<hr>
426
<h1>Google Charts</h1>
@@ -387,7 +468,7 @@ NetData is a complete Google Visualization API provider.
468
469
<hr>
470
<h1>Morris Charts</h1>
390
-Unfortunatelly, Morris Charts are veeeeeeeeeeeeeeeery slow! We force them to lower their detail to get acceptable results.
471
+Unfortunatelly, Morris Charts are very slow. Here we force them to lower their detail to get acceptable results.
472
<br/>
473
<div style="width: 33%; display: inline-block;">
474
<div data-netdata="system.processes"
@@ -424,6 +505,53 @@ Unfortunatelly, Morris Charts are veeeeeeeeeeeeeeeery slow! We force them to low
505
</div>
506
507
508
+<hr>
509
+<h1>C3 Charts</h1>
510
+C3 charts are not usable in large scale. They suffer from the following issues:
511
+<ul>
512
+ <li>extreme use of transitions (implemented with D3 instead of CSS, meaning they are javascript rendered) that cannot be disabled - even opacity is hardcoded in the javascript library</li>
513
+ <li>rendering is done with <code>SVG</code> instead of <code>canvas</code>, so they use DOM elements for every point, becomimg useless if more than 500 points are drawn</li>
514
+ <li>lack of a <code>raw</code> data format, so every time a chart is updated, data convertion in javascript is required</li>
515
+ <li>lack of <code>stacked</code> charts support</li>
516
+</ul>
517
+So, we avoid flashing the charts, here we destroy and re-create the charts on each update. Also, since they manipulate the data with javascript we were forced to lower the detail they render to get acceptable results.
518
+<br/>
519
+<div style="width: 33%; display: inline-block;">
520
+ <div data-netdata="system.processes"
521
+ data-chart-library="c3"
522
+ data-width="100%"
523
+ data-height="200"
524
+ data-after="-300"
525
+ data-dt-element-name="time701"
526
+ ></div>
527
+ <br/>
528
+ <small>rendered in <span id="time701">X</span> ms</small>
529
+</div>
530
+<div style="width: 33%; display: inline-block;">
531
+ <div data-netdata="system.ipv4"
532
+ data-chart-library="c3"
533
+ data-width="100%"
534
+ data-height="200"
535
+ data-after="-300"
536
+ data-dt-element-name="time702"
537
+ ></div>
538
+ <br/>
539
+ <small>rendered in <span id="time702">X</span> ms</small>
540
+</div>
541
+<div style="width: 33%; display: inline-block;">
542
+ <div data-netdata="system.cpu"
543
+ data-chart-library="c3"
544
+ data-width="100%"
545
+ data-height="200"
546
+ data-after="-300"
547
+ data-dt-element-name="time703"
548
+ ></div>
549
+ <br/>
550
+ <small>rendered in <span id="time703">X</span> ms</small>
551
+</div>
552
+
553
+
554
+
555
556
557
</div> <!-- 1st container -->
web/dashboard.js
+272
-26
@@ -6,6 +6,8 @@
6
// var netdataNoGoogleCharts = true; // do not use google
7
// var netdataNoMorris = true; // do not use morris
8
// var netdataNoEasyPieChart = true; // do not use easy pie chart
9
+// var netdataNoD3 = true; // do not use D3
10
+// var netdataNoC3 = true; // do not use C3
11
// var netdataNoBootstrap = true; // do not load bootstrap
12
// var netdataDontStart = true; // do not start the thread to process the charts
13
//
@@ -78,6 +80,9 @@
80
NETDATA.dygraph_smooth_js = NETDATA.serverDefault + 'lib/dygraph-smooth-plotter.js';
81
NETDATA.raphael_js = NETDATA.serverDefault + 'lib/raphael-min.js';
82
NETDATA.morris_js = NETDATA.serverDefault + 'lib/morris.min.js';
83
+ NETDATA.d3_js = NETDATA.serverDefault + 'lib/d3.min.js';
84
+ NETDATA.c3_js = NETDATA.serverDefault + 'lib/c3.min.js';
85
+ NETDATA.c3_css = NETDATA.serverDefault + 'css/c3.min.css';
86
NETDATA.morris_css = NETDATA.serverDefault + 'css/morris.css';
87
NETDATA.dashboard_css = NETDATA.serverDefault + 'dashboard.css';
88
NETDATA.google_js = 'https://www.google.com/jsapi';
@@ -1634,6 +1639,7 @@
1639
if(typeof value !== 'number') return value;
1640
1641
var abs = Math.abs(value);
1642
+ if(abs >= 100) return Math.round(value).toLocaleString();
1643
if(abs >= 1) return (Math.round(value * 100) / 100).toLocaleString();
1644
if(abs >= 0.1) return (Math.round(value * 1000) / 1000).toLocaleString();
1645
return (Math.round(value * 10000) / 10000).toLocaleString();
@@ -2173,46 +2179,58 @@
2179
2180
if(this.chart_created === true
2181
&& typeof this.library.update === 'function') {
2182
+ var status = false;
2183
2184
if(this.debug === true)
2185
this.log('updating chart...');
2186
2187
this.updates_since_last_creation++;
2188
if(NETDATA.options.debug.chart_errors === true) {
2182
- this.library.update(this, data);
2189
+ status = this.library.update(this, data);
2190
}
2191
else {
2192
try {
2186
- this.library.update(this, data);
2193
+ status = this.library.update(this, data);
2194
}
2195
catch(err) {
2196
+ status = false;
2197
error('chart failed to be updated as ' + this.library_name);
2198
}
2199
}
2200
+
2201
+ if(status === false)
2202
+ error('chart failed to be created as ' + this.library_name);
2203
}
2204
else {
2205
+ var status = false;
2206
+
2207
if(this.debug === true)
2208
this.log('creating chart...');
2209
2210
if(NETDATA.options.debug.chart_errors === true) {
2198
- this.library.create(this, data);
2211
+ status = this.library.create(this, data);
2212
this.chart_created = true;
2213
this.updates_since_last_creation = 0;
2214
}
2215
else {
2216
try {
2204
- this.library.create(this, data);
2217
+ status = this.library.create(this, data);
2218
this.chart_created = true;
2219
this.updates_since_last_creation = 0;
2220
}
2221
catch(err) {
2222
+ status = false;
2223
error('chart failed to be created as ' + this.library_name);
2224
}
2225
}
2226
+
2227
+ if(status === false)
2228
+ error('chart failed to be created as ' + this.library_name);
2229
}
2230
hideMessage();
2231
this.legendShowLatestValues();
2215
- NETDATA.globalSelectionSync.stop();
2232
+ if(this.selected === true)
2233
+ NETDATA.globalSelectionSync.stop();
2234
2235
// update the performance counters
2236
var now = new Date().getTime();
@@ -2880,6 +2898,7 @@
2898
}
2899
2900
$(state.peity_instance).peity('line', state.peity_options);
2901
+ return true;
2902
}
2903
2904
NETDATA.peityChartCreate = function(state, data) {
@@ -2896,6 +2915,7 @@
2915
};
2916
2917
NETDATA.peityChartUpdate(state, data);
2918
+ return true;
2919
}
2920
2921
// ----------------------------------------------------------------------------------------------------------------
@@ -2932,6 +2952,7 @@
2952
state.sparkline_options.height = state.chartHeight();
2953
2954
$(state.element_chart).sparkline(data.result, state.sparkline_options);
2955
+ return true;
2956
}
2957
2958
NETDATA.sparklineChartCreate = function(state, data) {
@@ -3035,6 +3056,7 @@
3056
};
3057
3058
$(state.element_chart).sparkline(data.result, state.sparkline_options);
3059
+ return true;
3060
};
3061
3062
// ----------------------------------------------------------------------------------------------------------------
@@ -3156,6 +3178,7 @@
3178
3179
dygraph.updateOptions(options);
3180
state.dygraph_last_rendered = new Date().getTime();
3181
+ return true;
3182
};
3183
3184
NETDATA.dygraphChartCreate = function(state, data) {
@@ -3635,6 +3658,7 @@
3658
data.result.data, state.dygraph_options);
3659
3660
state.dygraph_last_rendered = new Date().getTime();
3661
+ return true;
3662
};
3663
3664
// ----------------------------------------------------------------------------------------------------------------
@@ -3686,6 +3710,7 @@
3710
3711
NETDATA.morrisChartUpdate = function(state, data) {
3712
state.morris_instance.setData(data.result.data);
3713
+ return true;
3714
};
3715
3716
NETDATA.morrisChartCreate = function(state, data) {
@@ -3714,6 +3739,8 @@
3739
}
3740
else // stacked
3741
state.morris_instance = new Morris.Area(state.morris_options);
3742
+
3743
+ return true;
3744
};
3745
3746
// ----------------------------------------------------------------------------------------------------------------
@@ -3749,14 +3776,170 @@
3776
$(state.element_chart).raphael(data.result, {
3777
width: state.chartWidth(),
3778
height: state.chartHeight()
3752
- })
3779
+ });
3780
+
3781
+ return false;
3782
};
3783
3784
NETDATA.raphaelChartCreate = function(state, data) {
3785
$(state.element_chart).raphael(data.result, {
3786
width: state.chartWidth(),
3787
height: state.chartHeight()
3759
- })
3788
+ });
3789
+
3790
+ return false;
3791
+ };
3792
+
3793
+ // ----------------------------------------------------------------------------------------------------------------
3794
+ // C3
3795
+
3796
+ NETDATA.c3Initialize = function(callback) {
3797
+ if(typeof netdataNoC3 === 'undefined' || !netdataNoC3) {
3798
+
3799
+ // C3 requires D3
3800
+ if(!NETDATA.chartLibraries.d3.initialized) {
3801
+ if(NETDATA.chartLibraries.d3.enabled) {
3802
+ NETDATA.d3Initialize(function() {
3803
+ NETDATA.c3Initialize(callback);
3804
+ });
3805
+ }
3806
+ else {
3807
+ NETDATA.chartLibraries.c3.enabled = false;
3808
+ if(typeof callback === "function")
3809
+ callback();
3810
+ }
3811
+ }
3812
+ else {
3813
+ NETDATA._loadCSS(NETDATA.c3_css);
3814
+
3815
+ $.ajax({
3816
+ url: NETDATA.c3_js,
3817
+ cache: true,
3818
+ dataType: "script"
3819
+ })
3820
+ .done(function() {
3821
+ NETDATA.registerChartLibrary('c3', NETDATA.c3_js);
3822
+ })
3823
+ .fail(function() {
3824
+ NETDATA.chartLibraries.c3.enabled = false;
3825
+ NETDATA.error(100, NETDATA.c3_js);
3826
+ })
3827
+ .always(function() {
3828
+ if(typeof callback === "function")
3829
+ callback();
3830
+ });
3831
+ }
3832
+ }
3833
+ else {
3834
+ NETDATA.chartLibraries.c3.enabled = false;
3835
+ if(typeof callback === "function")
3836
+ callback();
3837
+ }
3838
+ };
3839
+
3840
+ NETDATA.c3ChartUpdate = function(state, data) {
3841
+ state.c3_instance.destroy();
3842
+ return NETDATA.c3ChartCreate(state, data);
3843
+
3844
+ //state.c3_instance.load({
3845
+ // rows: data.result,
3846
+ // unload: true
3847
+ //});
3848
+
3849
+ //return true;
3850
+ };
3851
+
3852
+ NETDATA.c3ChartCreate = function(state, data) {
3853
+
3854
+ state.element_chart.id = 'c3-' + state.uuid;
3855
+ // console.log('id = ' + state.element_chart.id);
3856
+
3857
+ state.c3_instance = c3.generate({
3858
+ bindto: '#' + state.element_chart.id,
3859
+ size: {
3860
+ width: state.chartWidth(),
3861
+ height: state.chartHeight()
3862
+ },
3863
+ color: {
3864
+ pattern: state.chartColors()
3865
+ },
3866
+ data: {
3867
+ x: 'time',
3868
+ rows: data.result,
3869
+ type: (state.chart.chart_type === 'line')?'spline':'area-spline'
3870
+ },
3871
+ axis: {
3872
+ x: {
3873
+ type: 'timeseries',
3874
+ tick: {
3875
+ format: function(x) {
3876
+ return NETDATA.zeropad(x.getHours()) + ":" + NETDATA.zeropad(x.getMinutes()) + ":" + NETDATA.zeropad(x.getSeconds());
3877
+ }
3878
+ }
3879
+ }
3880
+ },
3881
+ grid: {
3882
+ x: {
3883
+ show: true
3884
+ },
3885
+ y: {
3886
+ show: true
3887
+ }
3888
+ },
3889
+ point: {
3890
+ show: false
3891
+ },
3892
+ line: {
3893
+ connectNull: false
3894
+ },
3895
+ transition: {
3896
+ duration: 0
3897
+ },
3898
+ interaction: {
3899
+ enabled: true
3900
+ }
3901
+ });
3902
+
3903
+ // console.log(state.c3_instance);
3904
+
3905
+ return true;
3906
+ };
3907
+
3908
+ // ----------------------------------------------------------------------------------------------------------------
3909
+ // D3
3910
+
3911
+ NETDATA.d3Initialize = function(callback) {
3912
+ if(typeof netdataStopD3 === 'undefined' || !netdataStopD3) {
3913
+ $.ajax({
3914
+ url: NETDATA.d3_js,
3915
+ cache: true,
3916
+ dataType: "script"
3917
+ })
3918
+ .done(function() {
3919
+ NETDATA.registerChartLibrary('d3', NETDATA.d3_js);
3920
+ })
3921
+ .fail(function() {
3922
+ NETDATA.chartLibraries.d3.enabled = false;
3923
+ NETDATA.error(100, NETDATA.d3_js);
3924
+ })
3925
+ .always(function() {
3926
+ if(typeof callback === "function")
3927
+ callback();
3928
+ });
3929
+ }
3930
+ else {
3931
+ NETDATA.chartLibraries.d3.enabled = false;
3932
+ if(typeof callback === "function")
3933
+ callback();
3934
+ }
3935
+ };
3936
+
3937
+ NETDATA.d3ChartUpdate = function(state, data) {
3938
+ return false;
3939
+ };
3940
+
3941
+ NETDATA.d3ChartCreate = function(state, data) {
3942
+ return false;
3943
};
3944
3945
// ----------------------------------------------------------------------------------------------------------------
@@ -3793,6 +3976,7 @@
3976
NETDATA.googleChartUpdate = function(state, data) {
3977
var datatable = new google.visualization.DataTable(data.result);
3978
state.google_instance.draw(datatable, state.google_options);
3979
+ return true;
3980
};
3981
3982
NETDATA.googleChartCreate = function(state, data) {
@@ -3884,6 +4068,7 @@
4068
}
4069
4070
state.google_instance.draw(datatable, state.google_options);
4071
+ return true;
4072
};
4073
4074
// ----------------------------------------------------------------------------------------------------------------
@@ -3927,13 +4112,21 @@
4112
if(t < state.data_after || t > state.data_before)
4113
return NETDATA.easypiechartClearSelection(state);
4114
3930
- var slot = state.data.result.length - 1 - (t - state.data_after) / state.data_update_every;
4115
+ var slot = Math.floor(state.data.result.length - 1 - (t - state.data_after) / state.data_update_every);
4116
if(slot < 0 || slot >= state.data.result.length)
4117
return NETDATA.easypiechartClearSelection(state);
4118
4119
var value = state.data.result[slot];
3935
- var max = state.data.max;
3936
- var pcent = Math.round(value * 100 / max);
4120
+ if(value === null) value = 0;
4121
+
4122
+ var max = (state.easyPieChartMax === null)?state.data.max:state.easyPieChartMax;
4123
+ if(max < value) max = value;
4124
+
4125
+ var pcent = 0;
4126
+ if(max !== 0)
4127
+ pcent = Math.round(value * 100 / max);
4128
+
4129
+ // console.log('slot = ' + slot + ' value = ' + value + ' max = ' + max + ' pcent = ' + pcent);
4130
4131
state.easyPieChartLabel.innerHTML = state.legendFormatValue(value);
4132
chart.data('easyPieChart').update(pcent);
@@ -3945,13 +4138,18 @@
4138
var chart = $(state.element_chart);
4139
4140
var value = data.result[0];
3948
- var max = data.max;
3949
- var pcent = Math.round(value * 100 / max);
4141
+ if(value === null) value = 0;
4142
3951
- // console.log('value = ' + value + ' max = ' + max + ' pcent = ' + pcent);
4143
+ var max = (state.easyPieChartMax === null)?data.max:state.easyPieChartMax;
4144
+ if(max < value) max = value;
4145
+
4146
+ var pcent = 0;
4147
+ if(max !== 0)
4148
+ pcent = Math.round(value * 100 / max);
4149
4150
state.easyPieChartLabel.innerHTML = state.legendFormatValue(value);
4151
chart.data('easyPieChart').update(pcent);
4152
+ return true;
4153
};
4154
4155
NETDATA.easypiechartChartCreate = function(state, data) {
@@ -3959,18 +4157,31 @@
4157
var chart = $(state.element_chart);
4158
4159
var value = data.result[0];
3962
- var max = data.max;
3963
- var pcent = Math.round(value * 100 / max);
4160
+ if(value === null) value = 0;
4161
+
4162
+ var max = self.data('easypiechart-max-value') || null;
4163
+ if(max === null) {
4164
+ max = data.max;
4165
+ state.easyPieChartMax = null;
4166
+ }
4167
+ else {
4168
+ state.easyPieChartMax = max;
4169
+ }
4170
+ if(max < value) max = value;
4171
+
4172
+ var pcent = 0;
4173
+ if(max !== 0)
4174
+ pcent = Math.round(value * 100 / max);
4175
4176
// console.log('value = ' + value + ' max = ' + max + ' pcent = ' + pcent);
4177
chart.data('data-percent', pcent);
4178
4179
var size = Math.min(state.chartWidth(), state.chartHeight());
3969
- var stroke = size / 15;
3970
- if(stroke < 3) stroke = 3;
4180
+ var stroke = size / 15 - 2;
4181
+ if(stroke < 3) stroke = 2;
4182
3972
- var valuefontsize = Math.floor((size * 2 / 3) / 6);
3973
- var valuetop = Math.round((size - valuefontsize - 10) / 2);
4183
+ var valuefontsize = Math.floor((size * 2 / 3) / 5);
4184
+ var valuetop = Math.round((size - valuefontsize - (size / 40)) / 2);
4185
state.easyPieChartLabel = document.createElement('span');
4186
state.easyPieChartLabel.className = 'easyPieChartLabel';
4187
state.easyPieChartLabel.innerHTML = state.legendFormatValue(value);
@@ -3978,8 +4189,8 @@
4189
state.easyPieChartLabel.style.top = valuetop.toString() + 'px';
4190
state.element_chart.appendChild(state.easyPieChartLabel);
4191
3981
- var titlefontsize = Math.floor((size * 2 / 3) / 10);
3982
- var titletop = Math.round(valuetop - titlefontsize - (size / 20));
4192
+ var titlefontsize = Math.round(valuefontsize * 1.6 / 3);
4193
+ var titletop = Math.round(valuetop - (titlefontsize * 2) - (size / 40));
4194
state.easyPieChartTitle = document.createElement('span');
4195
state.easyPieChartTitle.className = 'easyPieChartTitle';
4196
state.easyPieChartTitle.innerHTML = state.title;
@@ -3988,8 +4199,8 @@
4199
state.easyPieChartTitle.style.top = titletop.toString() + 'px';
4200
state.element_chart.appendChild(state.easyPieChartTitle);
4201
3991
- var unitfontsize = Math.floor((size * 2 / 3) / 10);
3992
- var unittop = Math.round(valuetop + valuefontsize + (size / 20));
4202
+ var unitfontsize = Math.round(titlefontsize * 0.9);
4203
+ var unittop = Math.round(valuetop + (valuefontsize + unitfontsize) + (size / 40));
4204
state.easyPieChartUnits = document.createElement('span');
4205
state.easyPieChartUnits.className = 'easyPieChartUnits';
4206
state.easyPieChartUnits.innerHTML = state.chart.units;
@@ -4007,11 +4218,12 @@
4218
trackWidth: self.data('easypiechart-trackwidth') || undefined,
4219
size: self.data('easypiechart-size') || size,
4220
rotate: self.data('easypiechart-rotate') || 0,
4010
- animate: self.data('easypiechart-rotate') || {duration: data.view_update_every * 1000 / 2, enabled: true},
4221
+ animate: self.data('easypiechart-rotate') || {duration: data.view_update_every * 1000, enabled: true},
4222
easing: self.data('easypiechart-easing') || undefined
4223
});
4224
4225
chart.data('easyPieChart').update(pcent);
4226
+ return true;
4227
};
4228
4229
// ----------------------------------------------------------------------------------------------------------------
@@ -4144,13 +4356,47 @@
4356
track_colors: function(state) { return false; },
4357
pixels_per_point: function(state) { return 3; }
4358
},
4359
+ "c3": {
4360
+ initialize: NETDATA.c3Initialize,
4361
+ create: NETDATA.c3ChartCreate,
4362
+ update: NETDATA.c3ChartUpdate,
4363
+ resize: null,
4364
+ setSelection: undefined, // function(state, t) { return true; },
4365
+ clearSelection: undefined, // function(state) { return true; },
4366
+ initialized: false,
4367
+ enabled: true,
4368
+ format: function(state) { return 'csvjsonarray'; },
4369
+ options: function(state) { return 'milliseconds'; },
4370
+ legend: function(state) { return null; },
4371
+ autoresize: function(state) { return false; },
4372
+ max_updates_to_recreate: function(state) { return 5000; },
4373
+ track_colors: function(state) { return false; },
4374
+ pixels_per_point: function(state) { return 15; }
4375
+ },
4376
+ "d3": {
4377
+ initialize: NETDATA.d3Initialize,
4378
+ create: NETDATA.d3ChartCreate,
4379
+ update: NETDATA.d3ChartUpdate,
4380
+ resize: null,
4381
+ setSelection: undefined, // function(state, t) { return true; },
4382
+ clearSelection: undefined, // function(state) { return true; },
4383
+ initialized: false,
4384
+ enabled: true,
4385
+ format: function(state) { return 'json'; },
4386
+ options: function(state) { return ''; },
4387
+ legend: function(state) { return null; },
4388
+ autoresize: function(state) { return false; },
4389
+ max_updates_to_recreate: function(state) { return 5000; },
4390
+ track_colors: function(state) { return false; },
4391
+ pixels_per_point: function(state) { return 3; }
4392
+ },
4393
"easypiechart": {
4394
initialize: NETDATA.easypiechartInitialize,
4395
create: NETDATA.easypiechartChartCreate,
4396
update: NETDATA.easypiechartChartUpdate,
4397
resize: null,
4152
- setSelection: NETDATA.easypiechartSetSelection,
4153
- clearSelection: NETDATA.easypiechartClearSelection,
4398
+ setSelection: undefined, // NETDATA.easypiechartSetSelection,
4399
+ clearSelection: undefined, // NETDATA.easypiechartClearSelection,
4400
initialized: false,
4401
enabled: true,
4402
format: function(state) { return 'array'; },
web/index.html
+53
-7
@@ -357,16 +357,23 @@
357
<i class="fa fa-circle"></i> <a href="https://github.com/marcj/css-element-queries" target="_blank">CSS Element Queries</a>,
358
<i class="fa fa-copyright"></i> Copyright Marc J. Schmidt, <a href="https://github.com/marcj/css-element-queries/blob/master/LICENSE" target="_blank">MIT License</a>
359
360
+ <i class="fa fa-circle"></i> <a href="https://fortawesome.github.io/Font-Awesome/" target="_blank">FontAwesome</a>,
361
+ <i class="fa fa-copyright"></i> Created by Dave Gandy, Font: <a href="http://scripts.sil.org/OFL" target="_blank">SIL OFL 1.1 License</a>, CSS: <a href="http://opensource.org/licenses/mit-license.html" target="_blank">MIT License</a>
362
+
363
+ <i class="fa fa-circle"></i> <a href="http://www.iconsdb.com/soylent-red-icons/seo-performance-icon.html" target="_blank">IconsDB.com Icons</a>, Icons provided as CC0 1.0 Universal (CC0 1.0) Public Domain Dedication.
364
+
365
<i class="fa fa-circle"></i> <a href="http://morrisjs.github.io/morris.js/" target="_blank">morris.js</a>,
366
<i class="fa fa-copyright"></i> Copyright 2013, Olly Smith, <a href="http://morrisjs.github.io/morris.js/" target="_blank">Simplified BSD License</a>
367
368
<i class="fa fa-circle"></i> <a href="http://raphaeljs.com/" target="_blank">Raphaël</a>,
369
<i class="fa fa-copyright"></i> Copyright 2008, Dmitry Baranovskiy, <a href="http://raphaeljs.com/license.html" target="_blank">MIT License</a>
370
366
- <i class="fa fa-circle"></i> <a href="https://fortawesome.github.io/Font-Awesome/" target="_blank">FontAwesome</a>,
367
- <i class="fa fa-copyright"></i> Created by Dave Gandy, Font: <a href="http://scripts.sil.org/OFL" target="_blank">SIL OFL 1.1 License</a>, CSS: <a href="http://opensource.org/licenses/mit-license.html" target="_blank">MIT License</a>
371
+ <i class="fa fa-circle"></i> <a href="http://C3js.org/" target="_blank">C3</a>,
372
+ <i class="fa fa-copyright"></i> Copyright 2013, Masayuki Tanaka, <a href="https://github.com/masayuki0812/c3/blob/master/LICENSE" target="_blank">MIT License</a>
373
+
374
+ <i class="fa fa-circle"></i> <a href="http://D3js.org/" target="_blank">D3</a>,
375
+ <i class="fa fa-copyright"></i> Copyright 2015, Mike Bostock, <a href="http://opensource.org/licenses/BSD-3-Clause" target="_blank">BSD License</a>
376
369
- <i class="fa fa-circle"></i> <a href="http://www.iconsdb.com/soylent-red-icons/seo-performance-icon.html" target="_blank">IconsDB.com Icons</a>, Icons provided as CC0 1.0 Universal (CC0 1.0) Public Domain Dedication.
377
</small>
378
</div>
379
</div>
@@ -916,17 +923,55 @@ function prepareScreen(data) {
923
$.each(disks, function(j, c) {
924
sidebar += '<li class><a href="#' + name2id(c.name) + '">' + c.name + '</a></li>';
925
html += '<div class="netdata-group-container" id="disk_' + name2id(c.name) + '" style="display: inline-block; width: ' + pcent_width.toString() + '%"><h2 id="' + name2id(c.name) + '" class="netdata-chart-alignment" role="heading">' + c.name + '</h2>';
926
+ var head = '<div class="netdata-chart-alignment">';
927
+ var all = '';
928
$.each(c.values, function(x, f) {
929
var c = null;
930
var h = options.chartsHeight / 2;
931
switch(f.type) {
923
- case 'disk' : h = options.chartsHeight; break;
932
+ case 'disk' : h = options.chartsHeight;
933
+ head += '<div style="margin-right: 10px;" data-netdata="' + f.id + '"'
934
+ + ' data-dimensions="reads"'
935
+ + ' data-chart-library="easypiechart"'
936
+ + ' data-title="Read"'
937
+ + ' data-width="120px"'
938
+ + ' data-height="120px"'
939
+ + ' data-before="0"'
940
+ + ' data-after="-' + duration.toString() + '"'
941
+ + ' data-points="' + duration.toString() + '"'
942
+ + ' data-colors="' + NETDATA.colors[0] + '"'
943
+ + ' role="application"></div>';
944
+
945
+ head += '<div style="margin-right: 10px;" data-netdata="' + f.id + '"'
946
+ + ' data-dimensions="writes"'
947
+ + ' data-chart-library="easypiechart"'
948
+ + ' data-title="Write"'
949
+ + ' data-width="120px"'
950
+ + ' data-height="120px"'
951
+ + ' data-before="0"'
952
+ + ' data-after="-' + duration.toString() + '"'
953
+ + ' data-points="' + duration.toString() + '"'
954
+ + ' data-colors="' + NETDATA.colors[1] + '"'
955
+ + ' role="application"></div>';
956
+ break;
957
case 'disk_backlog': c = '#DD4477'; break;
925
- case 'disk_util' : c = '#109618'; break;
958
+ case 'disk_util' : c = '#109618';
959
+ head += '<div style="margin-right: 10px;" data-netdata="' + f.id + '"'
960
+ + ' data-chart-library="easypiechart"'
961
+ + ' data-title="Utilization"'
962
+ + ' data-easypiechart-max-value="100"'
963
+ + ' data-width="120px"'
964
+ + ' data-height="120px"'
965
+ + ' data-before="0"'
966
+ + ' data-after="-' + duration.toString() + '"'
967
+ + ' data-points="' + duration.toString() + '"'
968
+ + ' data-colors="' + c + '"'
969
+ + ' role="application"></div>';
970
+ break;
971
case 'disk_qops' : c = '#E67300'; break;
972
}
973
929
- html += getMessage(f.id) + '<div data-netdata="' + f.id + '"'
974
+ all += getMessage(f.id) + '<div data-netdata="' + f.id + '"'
975
+ ' data-width="100%"'
976
+ ' data-height="' + h.toString() + 'px"'
977
+ ' data-before="0"'
@@ -935,7 +980,8 @@ function prepareScreen(data) {
980
+ ' data-id="' + name2id(options.hostname + '/' + f.id) + '"'
981
+ ' role="application"></div>';
982
});
938
- html += '</div>'; // netdata-group-container
983
+ head += '</div>';
984
+ html += head + all + '</div>'; // netdata-group-container
985
});
986
sidebar += '</ul>';
987
}
web/lib/c3.min.js
new
+5
@@ -0,0 +1,5 @@
1
+!function(a){"use strict";function b(a){this.owner=a}function c(a,b){if(Object.create)b.prototype=Object.create(a.prototype);else{var c=function(){};c.prototype=a.prototype,b.prototype=new c}return b.prototype.constructor=b,b}function d(a){var b=this.internal=new e(this);b.loadConfig(a),b.beforeInit(a),b.init(),b.afterInit(a),function c(a,b,d){Object.keys(a).forEach(function(e){b[e]=a[e].bind(d),Object.keys(a[e]).length>0&&c(a[e],b[e],d)})}(h,this,this)}function e(b){var c=this;c.d3=a.d3?a.d3:"undefined"!=typeof require?require("d3"):void 0,c.api=b,c.config=c.getDefaultConfig(),c.data={},c.cache={},c.axes={}}function f(a){b.call(this,a)}function g(a,b){function c(a,b){a.attr("transform",function(a){return"translate("+Math.ceil(b(a)+u)+", 0)"})}function d(a,b){a.attr("transform",function(a){return"translate(0,"+Math.ceil(b(a))+")"})}function e(a){var b=a[0],c=a[a.length-1];return c>b?[b,c]:[c,b]}function f(a){var b,c,d=[];if(a.ticks)return a.ticks.apply(a,n);for(c=a.domain(),b=Math.ceil(c[0]);b<c[1];b++)d.push(b);return d.length>0&&d[0]>0&&d.unshift(d[0]-(d[1]-d[0])),d}function g(){var a,c=p.copy();return b.isCategory&&(a=p.domain(),c.domain([a[0],a[1]-1])),c}function h(a){var b=m?m(a):a;return"undefined"!=typeof b?b:""}function i(a){if(z)return z;var b={h:11.5,w:5.5};return a.select("text").text(h).each(function(a){var c=this.getBoundingClientRect(),d=h(a),e=c.height,f=d?c.width/d.length:void 0;e&&f&&(b.h=e,b.w=f)}).text(""),z=b,b}function j(c){return b.withoutTransition?c:a.transition(c)}function k(m){m.each(function(){function m(a,c){function d(a,b){f=void 0;for(var h=1;h<b.length;h++)if(" "===b.charAt(h)&&(f=h),e=b.substr(0,h+1),g=U.w*e.length,g>c)return d(a.concat(b.substr(0,f?f:h)),b.slice(f?f+1:h));return a.concat(b)}var e,f,g,i=h(a),j=[];return"[object Array]"===Object.prototype.toString.call(i)?i:((!c||0>=c)&&(c=X?95:b.isCategory?Math.ceil(F(G[1])-F(G[0]))-12:110),d(j,i+""))}function n(a,b){var c=U.h;return 0===b&&(c="left"===q||"right"===q?-((V[a.index]-1)*(U.h/2)-3):".71em"),c}function v(a){var b=p(a)+(o?0:u);return L[0]<b&&b<L[1]?r:0}function w(a){return a?a>0?"start":"end":"middle"}function x(a){return a?"rotate("+a+")":""}function y(a){return a?8*Math.sin(Math.PI*(a/180)):0}function z(a){return a?11.5-2.5*(a/15)*(a>0?1:-1):W}var A,B,C,D=k.g=a.select(this),E=this.__chart__||p,F=this.__chart__=g(),G=t?t:f(F),H=D.selectAll(".tick").data(G,F),I=H.enter().insert("g",".domain").attr("class","tick").style("opacity",1e-6),J=H.exit().remove(),K=j(H).style("opacity",1),L=p.rangeExtent?p.rangeExtent():e(p.range()),M=D.selectAll(".domain").data([0]),N=(M.enter().append("path").attr("class","domain"),j(M));I.append("line"),I.append("text");var O=I.select("line"),P=K.select("line"),Q=I.select("text"),R=K.select("text");b.isCategory?(u=Math.ceil((F(1)-F(0))/2),B=o?0:u,C=o?u:0):u=B=0;var S,T,U=i(D.select(".tick")),V=[],W=Math.max(r,0)+s,X="left"===q||"right"===q;S=H.select("text"),T=S.selectAll("tspan").data(function(a,c){var d=b.tickMultiline?m(a,b.tickWidth):[].concat(h(a));return V[c]=d.length,d.map(function(a){return{index:c,splitted:a}})}),T.enter().append("tspan"),T.exit().remove(),T.text(function(a){return a.splitted});var Y=b.tickTextRotate;switch(q){case"bottom":A=c,O.attr("y2",r),Q.attr("y",W),P.attr("x1",B).attr("x2",B).attr("y2",v),R.attr("x",0).attr("y",z(Y)).style("text-anchor",w(Y)).attr("transform",x(Y)),T.attr("x",0).attr("dy",n).attr("dx",y(Y)),N.attr("d","M"+L[0]+","+l+"V0H"+L[1]+"V"+l);break;case"top":A=c,O.attr("y2",-r),Q.attr("y",-W),P.attr("x2",0).attr("y2",-r),R.attr("x",0).attr("y",-W),S.style("text-anchor","middle"),T.attr("x",0).attr("dy","0em"),N.attr("d","M"+L[0]+","+-l+"V0H"+L[1]+"V"+-l);break;case"left":A=d,O.attr("x2",-r),Q.attr("x",-W),P.attr("x2",-r).attr("y1",C).attr("y2",C),R.attr("x",-W).attr("y",u),S.style("text-anchor","end"),T.attr("x",-W).attr("dy",n),N.attr("d","M"+-l+","+L[0]+"H0V"+L[1]+"H"+-l);break;case"right":A=d,O.attr("x2",r),Q.attr("x",W),P.attr("x2",r).attr("y2",0),R.attr("x",W).attr("y",0),S.style("text-anchor","start"),T.attr("x",W).attr("dy",n),N.attr("d","M"+l+","+L[0]+"H0V"+L[1]+"H"+l)}if(F.rangeBand){var Z=F,$=Z.rangeBand()/2;E=F=function(a){return Z(a)+$}}else E.rangeBand?E=F:J.call(A,F);I.call(A,E),K.call(A,F)})}var l,m,n,o,p=a.scale.linear(),q="bottom",r=6,s=3,t=null,u=0,v=!0;return b=b||{},l=b.withOuterTick?6:0,k.scale=function(a){return arguments.length?(p=a,k):p},k.orient=function(a){return arguments.length?(q=a in{top:1,right:1,bottom:1,left:1}?a+"":"bottom",k):q},k.tickFormat=function(a){return arguments.length?(m=a,k):m},k.tickCentered=function(a){return arguments.length?(o=a,k):o},k.tickOffset=function(){return u},k.tickInterval=function(){var a,c;return b.isCategory?a=2*u:(c=k.g.select("path.domain").node().getTotalLength()-2*l,a=c/k.g.selectAll("line").size()),a===1/0?0:a},k.ticks=function(){return arguments.length?(n=arguments,k):n},k.tickCulling=function(a){return arguments.length?(v=a,k):v},k.tickValues=function(a){if("function"==typeof a)t=function(){return a(p.domain())};else{if(!arguments.length)return t;t=a}return k},k}var h,i,j,k={version:"0.4.11-rc4"};k.generate=function(a){return new d(a)},k.chart={fn:d.prototype,internal:{fn:e.prototype,axis:{fn:f.prototype}}},h=k.chart.fn,i=k.chart.internal.fn,j=k.chart.internal.axis.fn,i.beforeInit=function(){},i.afterInit=function(){},i.init=function(){var a=this,b=a.config;if(a.initParams(),b.data_url)a.convertUrlToData(b.data_url,b.data_mimeType,b.data_keys,a.initWithData);else if(b.data_json)a.initWithData(a.convertJsonToData(b.data_json,b.data_keys));else if(b.data_rows)a.initWithData(a.convertRowsToData(b.data_rows));else{if(!b.data_columns)throw Error("url or json or rows or columns is required.");a.initWithData(a.convertColumnsToData(b.data_columns))}},i.initParams=function(){var a=this,b=a.d3,c=a.config;a.clipId="c3-"+ +new Date+"-clip",a.clipIdForXAxis=a.clipId+"-xaxis",a.clipIdForYAxis=a.clipId+"-yaxis",a.clipIdForGrid=a.clipId+"-grid",a.clipIdForSubchart=a.clipId+"-subchart",a.clipPath=a.getClipPath(a.clipId),a.clipPathForXAxis=a.getClipPath(a.clipIdForXAxis),a.clipPathForYAxis=a.getClipPath(a.clipIdForYAxis),a.clipPathForGrid=a.getClipPath(a.clipIdForGrid),a.clipPathForSubchart=a.getClipPath(a.clipIdForSubchart),a.dragStart=null,a.dragging=!1,a.flowing=!1,a.cancelClick=!1,a.mouseover=!1,a.transiting=!1,a.color=a.generateColor(),a.levelColor=a.generateLevelColor(),a.dataTimeFormat=c.data_xLocaltime?b.time.format:b.time.format.utc,a.axisTimeFormat=c.axis_x_localtime?b.time.format:b.time.format.utc,a.defaultAxisTimeFormat=a.axisTimeFormat.multi([[".%L",function(a){return a.getMilliseconds()}],[":%S",function(a){return a.getSeconds()}],["%I:%M",function(a){return a.getMinutes()}],["%I %p",function(a){return a.getHours()}],["%-m/%-d",function(a){return a.getDay()&&1!==a.getDate()}],["%-m/%-d",function(a){return 1!==a.getDate()}],["%-m/%-d",function(a){return a.getMonth()}],["%Y/%-m/%-d",function(){return!0}]]),a.hiddenTargetIds=[],a.hiddenLegendIds=[],a.focusedTargetIds=[],a.defocusedTargetIds=[],a.xOrient=c.axis_rotated?"left":"bottom",a.yOrient=c.axis_rotated?c.axis_y_inner?"top":"bottom":c.axis_y_inner?"right":"left",a.y2Orient=c.axis_rotated?c.axis_y2_inner?"bottom":"top":c.axis_y2_inner?"left":"right",a.subXOrient=c.axis_rotated?"left":"bottom",a.isLegendRight="right"===c.legend_position,a.isLegendInset="inset"===c.legend_position,a.isLegendTop="top-left"===c.legend_inset_anchor||"top-right"===c.legend_inset_anchor,a.isLegendLeft="top-left"===c.legend_inset_anchor||"bottom-left"===c.legend_inset_anchor,a.legendStep=0,a.legendItemWidth=0,a.legendItemHeight=0,a.currentMaxTickWidths={x:0,y:0,y2:0},a.rotated_padding_left=30,a.rotated_padding_right=c.axis_rotated&&!c.axis_x_show?0:30,a.rotated_padding_top=5,a.withoutFadeIn={},a.intervalForObserveInserted=void 0,a.axes.subx=b.selectAll([])},i.initChartElements=function(){this.initBar&&this.initBar(),this.initLine&&this.initLine(),this.initArc&&this.initArc(),this.initGauge&&this.initGauge(),this.initText&&this.initText()},i.initWithData=function(a){var b,c,d=this,e=d.d3,g=d.config,h=!0;d.axis=new f(d),d.initPie&&d.initPie(),d.initBrush&&d.initBrush(),d.initZoom&&d.initZoom(),g.bindto?"function"==typeof g.bindto.node?d.selectChart=g.bindto:d.selectChart=e.select(g.bindto):d.selectChart=e.selectAll([]),d.selectChart.empty()&&(d.selectChart=e.select(document.createElement("div")).style("opacity",0),d.observeInserted(d.selectChart),h=!1),d.selectChart.html("").classed("c3",!0),d.data.xs={},d.data.targets=d.convertDataToTargets(a),g.data_filter&&(d.data.targets=d.data.targets.filter(g.data_filter)),g.data_hide&&d.addHiddenTargetIds(g.data_hide===!0?d.mapToIds(d.data.targets):g.data_hide),g.legend_hide&&d.addHiddenLegendIds(g.legend_hide===!0?d.mapToIds(d.data.targets):g.legend_hide),d.hasType("gauge")&&(g.legend_show=!1),d.updateSizes(),d.updateScales(),d.x.domain(e.extent(d.getXDomain(d.data.targets))),d.y.domain(d.getYDomain(d.data.targets,"y")),d.y2.domain(d.getYDomain(d.data.targets,"y2")),d.subX.domain(d.x.domain()),d.subY.domain(d.y.domain()),d.subY2.domain(d.y2.domain()),d.orgXDomain=d.x.domain(),d.brush&&d.brush.scale(d.subX),g.zoom_enabled&&d.zoom.scale(d.x),d.svg=d.selectChart.append("svg").style("overflow","hidden").on("mouseenter",function(){return g.onmouseover.call(d)}).on("mouseleave",function(){return g.onmouseout.call(d)}),d.config.svg_classname&&d.svg.attr("class",d.config.svg_classname),b=d.svg.append("defs"),d.clipChart=d.appendClip(b,d.clipId),d.clipXAxis=d.appendClip(b,d.clipIdForXAxis),d.clipYAxis=d.appendClip(b,d.clipIdForYAxis),d.clipGrid=d.appendClip(b,d.clipIdForGrid),d.clipSubchart=d.appendClip(b,d.clipIdForSubchart),d.updateSvgSize(),c=d.main=d.svg.append("g").attr("transform",d.getTranslate("main")),d.initSubchart&&d.initSubchart(),d.initTooltip&&d.initTooltip(),d.initLegend&&d.initLegend(),d.initTitle&&d.initTitle(),c.append("text").attr("class",l.text+" "+l.empty).attr("text-anchor","middle").attr("dominant-baseline","middle"),d.initRegion(),d.initGrid(),c.append("g").attr("clip-path",d.clipPath).attr("class",l.chart),g.grid_lines_front&&d.initGridLines(),d.initEventRect(),d.initChartElements(),c.insert("rect",g.zoom_privileged?null:"g."+l.regions).attr("class",l.zoomRect).attr("width",d.width).attr("height",d.height).style("opacity",0).on("dblclick.zoom",null),g.axis_x_extent&&d.brush.extent(d.getDefaultExtent()),d.axis.init(),d.updateTargets(d.data.targets),h&&(d.updateDimension(),d.config.oninit.call(d),d.redraw({withTransition:!1,withTransform:!0,withUpdateXDomain:!0,withUpdateOrgXDomain:!0,withTransitionForAxis:!1})),d.bindResize(),d.api.element=d.selectChart.node()},i.smoothLines=function(a,b){var c=this;"grid"===b&&a.each(function(){var a=c.d3.select(this),b=a.attr("x1"),d=a.attr("x2"),e=a.attr("y1"),f=a.attr("y2");a.attr({x1:Math.ceil(b),x2:Math.ceil(d),y1:Math.ceil(e),y2:Math.ceil(f)})})},i.updateSizes=function(){var a=this,b=a.config,c=a.legend?a.getLegendHeight():0,d=a.legend?a.getLegendWidth():0,e=a.isLegendRight||a.isLegendInset?0:c,f=a.hasArcType(),g=b.axis_rotated||f?0:a.getHorizontalAxisHeight("x"),h=b.subchart_show&&!f?b.subchart_size_height+g:0;a.currentWidth=a.getCurrentWidth(),a.currentHeight=a.getCurrentHeight(),a.margin=b.axis_rotated?{top:a.getHorizontalAxisHeight("y2")+a.getCurrentPaddingTop(),right:f?0:a.getCurrentPaddingRight(),bottom:a.getHorizontalAxisHeight("y")+e+a.getCurrentPaddingBottom(),left:h+(f?0:a.getCurrentPaddingLeft())}:{top:4+a.getCurrentPaddingTop(),right:f?0:a.getCurrentPaddingRight(),bottom:g+h+e+a.getCurrentPaddingBottom(),left:f?0:a.getCurrentPaddingLeft()},a.margin2=b.axis_rotated?{top:a.margin.top,right:NaN,bottom:20+e,left:a.rotated_padding_left}:{top:a.currentHeight-h-e,right:NaN,bottom:g+e,left:a.margin.left},a.margin3={top:0,right:NaN,bottom:0,left:0},a.updateSizeForLegend&&a.updateSizeForLegend(c,d),a.width=a.currentWidth-a.margin.left-a.margin.right,a.height=a.currentHeight-a.margin.top-a.margin.bottom,a.width<0&&(a.width=0),a.height<0&&(a.height=0),a.width2=b.axis_rotated?a.margin.left-a.rotated_padding_left-a.rotated_padding_right:a.width,a.height2=b.axis_rotated?a.height:a.currentHeight-a.margin2.top-a.margin2.bottom,a.width2<0&&(a.width2=0),a.height2<0&&(a.height2=0),a.arcWidth=a.width-(a.isLegendRight?d+10:0),a.arcHeight=a.height-(a.isLegendRight?0:10),a.hasType("gauge")&&(a.arcHeight+=a.height-a.getGaugeLabelHeight()),a.updateRadius&&a.updateRadius(),a.isLegendRight&&f&&(a.margin3.left=a.arcWidth/2+1.1*a.radiusExpanded)},i.updateTargets=function(a){var b=this;b.updateTargetsForText(a),b.updateTargetsForBar(a),b.updateTargetsForLine(a),b.hasArcType()&&b.updateTargetsForArc&&b.updateTargetsForArc(a),b.updateTargetsForSubchart&&b.updateTargetsForSubchart(a),b.showTargets()},i.showTargets=function(){var a=this;a.svg.selectAll("."+l.target).filter(function(b){return a.isTargetToShow(b.id)}).transition().duration(a.config.transition_duration).style("opacity",1)},i.redraw=function(a,b){var c,d,e,f,g,h,i,j,k,m,n,o,p,q,r,s,t,u,v,x,y,z,A,B,C,D,E,F,G,H=this,I=H.main,J=H.d3,K=H.config,L=H.getShapeIndices(H.isAreaType),M=H.getShapeIndices(H.isBarType),N=H.getShapeIndices(H.isLineType),O=H.hasArcType(),P=H.filterTargetsToShow(H.data.targets),Q=H.xv.bind(H);if(a=a||{},c=w(a,"withY",!0),d=w(a,"withSubchart",!0),e=w(a,"withTransition",!0),h=w(a,"withTransform",!1),i=w(a,"withUpdateXDomain",!1),j=w(a,"withUpdateOrgXDomain",!1),k=w(a,"withTrimXDomain",!0),p=w(a,"withUpdateXAxis",i),m=w(a,"withLegend",!1),n=w(a,"withEventRect",!0),o=w(a,"withDimension",!0),f=w(a,"withTransitionForExit",e),g=w(a,"withTransitionForAxis",e),v=e?K.transition_duration:0,x=f?v:0,y=g?v:0,b=b||H.axis.generateTransitions(y),m&&K.legend_show?H.updateLegend(H.mapToIds(H.data.targets),a,b):o&&H.updateDimension(!0),H.isCategorized()&&0===P.length&&H.x.domain([0,H.axes.x.selectAll(".tick").size()]),P.length?(H.updateXDomain(P,i,j,k),K.axis_x_tick_values||(B=H.axis.updateXAxisTickValues(P))):(H.xAxis.tickValues([]),H.subXAxis.tickValues([])),K.zoom_rescale&&!a.flow&&(E=H.x.orgDomain()),H.y.domain(H.getYDomain(P,"y",E)),H.y2.domain(H.getYDomain(P,"y2",E)),!K.axis_y_tick_values&&K.axis_y_tick_count&&H.yAxis.tickValues(H.axis.generateTickValues(H.y.domain(),K.axis_y_tick_count)),!K.axis_y2_tick_values&&K.axis_y2_tick_count&&H.y2Axis.tickValues(H.axis.generateTickValues(H.y2.domain(),K.axis_y2_tick_count)),H.axis.redraw(b,O),H.axis.updateLabels(e),(i||p)&&P.length)if(K.axis_x_tick_culling&&B){for(C=1;C<B.length;C++)if(B.length/C<K.axis_x_tick_culling_max){D=C;break}H.svg.selectAll("."+l.axisX+" .tick text").each(function(a){var b=B.indexOf(a);b>=0&&J.select(this).style("display",b%D?"none":"block")})}else H.svg.selectAll("."+l.axisX+" .tick text").style("display","block");q=H.generateDrawArea?H.generateDrawArea(L,!1):void 0,r=H.generateDrawBar?H.generateDrawBar(M):void 0,s=H.generateDrawLine?H.generateDrawLine(N,!1):void 0,t=H.generateXYForText(L,M,N,!0),u=H.generateXYForText(L,M,N,!1),c&&(H.subY.domain(H.getYDomain(P,"y")),H.subY2.domain(H.getYDomain(P,"y2"))),H.updateXgridFocus(),I.select("text."+l.text+"."+l.empty).attr("x",H.width/2).attr("y",H.height/2).text(K.data_empty_label_text).transition().style("opacity",P.length?0:1),H.updateGrid(v),H.updateRegion(v),H.updateBar(x),H.updateLine(x),H.updateArea(x),H.updateCircle(),H.hasDataLabel()&&H.updateText(x),H.redrawTitle&&H.redrawTitle(),H.redrawArc&&H.redrawArc(v,x,h),H.redrawSubchart&&H.redrawSubchart(d,b,v,x,L,M,N),I.selectAll("."+l.selectedCircles).filter(H.isBarType.bind(H)).selectAll("circle").remove(),K.interaction_enabled&&!a.flow&&n&&(H.redrawEventRect(),H.updateZoom&&H.updateZoom()),H.updateCircleY(),F=(H.config.axis_rotated?H.circleY:H.circleX).bind(H),G=(H.config.axis_rotated?H.circleX:H.circleY).bind(H),a.flow&&(A=H.generateFlow({targets:P,flow:a.flow,duration:a.flow.duration,drawBar:r,drawLine:s,drawArea:q,cx:F,cy:G,xv:Q,xForText:t,yForText:u})),(v||A)&&H.isTabVisible()?J.transition().duration(v).each(function(){var b=[];[H.redrawBar(r,!0),H.redrawLine(s,!0),H.redrawArea(q,!0),H.redrawCircle(F,G,!0),H.redrawText(t,u,a.flow,!0),H.redrawRegion(!0),H.redrawGrid(!0)].forEach(function(a){a.forEach(function(a){b.push(a)})}),z=H.generateWait(),b.forEach(function(a){z.add(a)})}).call(z,function(){A&&A(),K.onrendered&&K.onrendered.call(H)}):(H.redrawBar(r),H.redrawLine(s),H.redrawArea(q),H.redrawCircle(F,G),H.redrawText(t,u,a.flow),H.redrawRegion(),H.redrawGrid(),K.onrendered&&K.onrendered.call(H)),H.mapToIds(H.data.targets).forEach(function(a){H.withoutFadeIn[a]=!0})},i.updateAndRedraw=function(a){var b,c=this,d=c.config;a=a||{},a.withTransition=w(a,"withTransition",!0),a.withTransform=w(a,"withTransform",!1),a.withLegend=w(a,"withLegend",!1),a.withUpdateXDomain=!0,a.withUpdateOrgXDomain=!0,a.withTransitionForExit=!1,a.withTransitionForTransform=w(a,"withTransitionForTransform",a.withTransition),c.updateSizes(),a.withLegend&&d.legend_show||(b=c.axis.generateTransitions(a.withTransitionForAxis?d.transition_duration:0),c.updateScales(),c.updateSvgSize(),c.transformAll(a.withTransitionForTransform,b)),c.redraw(a,b)},i.redrawWithoutRescale=function(){this.redraw({withY:!1,withSubchart:!1,withEventRect:!1,withTransitionForAxis:!1})},i.isTimeSeries=function(){return"timeseries"===this.config.axis_x_type},i.isCategorized=function(){return this.config.axis_x_type.indexOf("categor")>=0},i.isCustomX=function(){var a=this,b=a.config;return!a.isTimeSeries()&&(b.data_x||v(b.data_xs))},i.isTimeSeriesY=function(){return"timeseries"===this.config.axis_y_type},i.getTranslate=function(a){var b,c,d=this,e=d.config;return"main"===a?(b=s(d.margin.left),c=s(d.margin.top)):"context"===a?(b=s(d.margin2.left),c=s(d.margin2.top)):"legend"===a?(b=d.margin3.left,c=d.margin3.top):"x"===a?(b=0,c=e.axis_rotated?0:d.height):"y"===a?(b=0,c=e.axis_rotated?d.height:0):"y2"===a?(b=e.axis_rotated?0:d.width,c=e.axis_rotated?1:0):"subx"===a?(b=0,c=e.axis_rotated?0:d.height2):"arc"===a&&(b=d.arcWidth/2,c=d.arcHeight/2),"translate("+b+","+c+")"},i.initialOpacity=function(a){return null!==a.value&&this.withoutFadeIn[a.id]?1:0},i.initialOpacityForCircle=function(a){return null!==a.value&&this.withoutFadeIn[a.id]?this.opacityForCircle(a):0},i.opacityForCircle=function(a){var b=this.config.point_show?1:0;return m(a.value)?this.isScatterType(a)?.5:b:0},i.opacityForText=function(){return this.hasDataLabel()?1:0},i.xx=function(a){return a?this.x(a.x):null},i.xv=function(a){var b=this,c=a.value;return b.isTimeSeries()?c=b.parseDate(a.value):b.isCategorized()&&"string"==typeof a.value&&(c=b.config.axis_x_categories.indexOf(a.value)),Math.ceil(b.x(c))},i.yv=function(a){var b=this,c=a.axis&&"y2"===a.axis?b.y2:b.y;return Math.ceil(c(a.value))},i.subxx=function(a){return a?this.subX(a.x):null},i.transformMain=function(a,b){var c,d,e,f=this;b&&b.axisX?c=b.axisX:(c=f.main.select("."+l.axisX),a&&(c=c.transition())),b&&b.axisY?d=b.axisY:(d=f.main.select("."+l.axisY),a&&(d=d.transition())),b&&b.axisY2?e=b.axisY2:(e=f.main.select("."+l.axisY2),a&&(e=e.transition())),(a?f.main.transition():f.main).attr("transform",f.getTranslate("main")),c.attr("transform",f.getTranslate("x")),d.attr("transform",f.getTranslate("y")),e.attr("transform",f.getTranslate("y2")),f.main.select("."+l.chartArcs).attr("transform",f.getTranslate("arc"))},i.transformAll=function(a,b){var c=this;c.transformMain(a,b),c.config.subchart_show&&c.transformContext(a,b),c.legend&&c.transformLegend(a)},i.updateSvgSize=function(){var a=this,b=a.svg.select(".c3-brush .background");a.svg.attr("width",a.currentWidth).attr("height",a.currentHeight),a.svg.selectAll(["#"+a.clipId,"#"+a.clipIdForGrid]).select("rect").attr("width",a.width).attr("height",a.height),a.svg.select("#"+a.clipIdForXAxis).select("rect").attr("x",a.getXAxisClipX.bind(a)).attr("y",a.getXAxisClipY.bind(a)).attr("width",a.getXAxisClipWidth.bind(a)).attr("height",a.getXAxisClipHeight.bind(a)),a.svg.select("#"+a.clipIdForYAxis).select("rect").attr("x",a.getYAxisClipX.bind(a)).attr("y",a.getYAxisClipY.bind(a)).attr("width",a.getYAxisClipWidth.bind(a)).attr("height",a.getYAxisClipHeight.bind(a)),a.svg.select("#"+a.clipIdForSubchart).select("rect").attr("width",a.width).attr("height",b.size()?b.attr("height"):0),a.svg.select("."+l.zoomRect).attr("width",a.width).attr("height",a.height),a.selectChart.style("max-height",a.currentHeight+"px")},i.updateDimension=function(a){var b=this;a||(b.config.axis_rotated?(b.axes.x.call(b.xAxis),b.axes.subx.call(b.subXAxis)):(b.axes.y.call(b.yAxis),b.axes.y2.call(b.y2Axis))),b.updateSizes(),b.updateScales(),b.updateSvgSize(),b.transformAll(!1)},i.observeInserted=function(b){var c,d=this;return"undefined"==typeof MutationObserver?void a.console.error("MutationObserver not defined."):(c=new MutationObserver(function(e){e.forEach(function(e){"childList"===e.type&&e.previousSibling&&(c.disconnect(),d.intervalForObserveInserted=a.setInterval(function(){b.node().parentNode&&(a.clearInterval(d.intervalForObserveInserted),d.updateDimension(),d.brush&&d.brush.update(),d.config.oninit.call(d),d.redraw({withTransform:!0,withUpdateXDomain:!0,withUpdateOrgXDomain:!0,withTransition:!1,withTransitionForTransform:!1,withLegend:!0}),b.transition().style("opacity",1))},10))})}),void c.observe(b.node(),{attributes:!0,childList:!0,characterData:!0}))},i.bindResize=function(){var b=this,c=b.config;if(b.resizeFunction=b.generateResize(),b.resizeFunction.add(function(){c.onresize.call(b)}),c.resize_auto&&b.resizeFunction.add(function(){void 0!==b.resizeTimeout&&a.clearTimeout(b.resizeTimeout),b.resizeTimeout=a.setTimeout(function(){delete b.resizeTimeout,b.api.flush()},100)}),b.resizeFunction.add(function(){c.onresized.call(b)}),a.attachEvent)a.attachEvent("onresize",b.resizeFunction);else if(a.addEventListener)a.addEventListener("resize",b.resizeFunction,!1);else{var d=a.onresize;d?d.add&&d.remove||(d=b.generateResize(),d.add(a.onresize)):d=b.generateResize(),d.add(b.resizeFunction),a.onresize=d}},i.generateResize=function(){function a(){b.forEach(function(a){a()})}var b=[];return a.add=function(a){b.push(a)},a.remove=function(a){for(var c=0;c<b.length;c++)if(b[c]===a){b.splice(c,1);break}},a},i.endall=function(a,b){var c=0;a.each(function(){++c}).each("end",function(){--c||b.apply(this,arguments)})},i.generateWait=function(){var a=[],b=function(b,c){var d=setInterval(function(){var b=0;a.forEach(function(a){if(a.empty())return void(b+=1);try{a.transition()}catch(c){b+=1}}),b===a.length&&(clearInterval(d),c&&c())},10)};return b.add=function(b){a.push(b)},b},i.parseDate=function(b){var c,d=this;return b instanceof Date?c=b:"string"==typeof b?c=d.dataTimeFormat(d.config.data_xFormat).parse(b):"number"!=typeof b||isNaN(b)||(c=new Date(+b)),(!c||isNaN(+c))&&a.console.error("Failed to parse x '"+b+"' to Date object"),c},i.isTabVisible=function(){var a;return"undefined"!=typeof document.hidden?a="hidden":"undefined"!=typeof document.mozHidden?a="mozHidden":"undefined"!=typeof document.msHidden?a="msHidden":"undefined"!=typeof document.webkitHidden&&(a="webkitHidden"),document[a]?!1:!0},i.getDefaultConfig=function(){var a={bindto:"#chart",svg_classname:void 0,size_width:void 0,size_height:void 0,padding_left:void 0,padding_right:void 0,padding_top:void 0,padding_bottom:void 0,resize_auto:!0,zoom_enabled:!1,zoom_extent:void 0,zoom_privileged:!1,zoom_rescale:!1,zoom_onzoom:function(){},zoom_onzoomstart:function(){},zoom_onzoomend:function(){},zoom_x_min:void 0,zoom_x_max:void 0,interaction_enabled:!0,onmouseover:function(){},onmouseout:function(){},onresize:function(){},onresized:function(){},oninit:function(){},onrendered:function(){},transition_duration:350,data_x:void 0,data_xs:{},data_xFormat:"%Y-%m-%d",data_xLocaltime:!0,data_xSort:!0,data_idConverter:function(a){return a},data_names:{},data_classes:{},data_groups:[],data_axes:{},data_type:void 0,data_types:{},data_labels:{},data_order:"desc",data_regions:{},data_color:void 0,data_colors:{},data_hide:!1,data_filter:void 0,data_selection_enabled:!1,data_selection_grouped:!1,data_selection_isselectable:function(){return!0},data_selection_multiple:!0,data_selection_draggable:!1,data_onclick:function(){},data_onmouseover:function(){},data_onmouseout:function(){},data_onselected:function(){},data_onunselected:function(){},data_url:void 0,data_json:void 0,data_rows:void 0,data_columns:void 0,data_mimeType:void 0,data_keys:void 0,data_empty_label_text:"",subchart_show:!1,subchart_size_height:60,subchart_axis_x_show:!0,subchart_onbrush:function(){},color_pattern:[],color_threshold:{},legend_show:!0,legend_hide:!1,legend_position:"bottom",legend_inset_anchor:"top-left",legend_inset_x:10,legend_inset_y:0,legend_inset_step:void 0,legend_item_onclick:void 0,legend_item_onmouseover:void 0,legend_item_onmouseout:void 0,legend_equally:!1,legend_padding:0,legend_item_tile_width:10,legend_item_tile_height:10,axis_rotated:!1,axis_x_show:!0,axis_x_type:"indexed",axis_x_localtime:!0,axis_x_categories:[],axis_x_tick_centered:!1,axis_x_tick_format:void 0,axis_x_tick_culling:{},axis_x_tick_culling_max:10,axis_x_tick_count:void 0,axis_x_tick_fit:!0,axis_x_tick_values:null,axis_x_tick_rotate:0,axis_x_tick_outer:!0,axis_x_tick_multiline:!0,axis_x_tick_width:null,axis_x_max:void 0,axis_x_min:void 0,axis_x_padding:{},axis_x_height:void 0,axis_x_extent:void 0,axis_x_label:{},axis_y_show:!0,axis_y_type:void 0,axis_y_max:void 0,axis_y_min:void 0,axis_y_inverted:!1,axis_y_center:void 0,axis_y_inner:void 0,axis_y_label:{},axis_y_tick_format:void 0,axis_y_tick_outer:!0,axis_y_tick_values:null,axis_y_tick_count:void 0,axis_y_tick_time_value:void 0,axis_y_tick_time_interval:void 0,axis_y_padding:{},axis_y_default:void 0,axis_y2_show:!1,axis_y2_max:void 0,axis_y2_min:void 0,axis_y2_inverted:!1,axis_y2_center:void 0,axis_y2_inner:void 0,axis_y2_label:{},axis_y2_tick_format:void 0,axis_y2_tick_outer:!0,axis_y2_tick_values:null,axis_y2_tick_count:void 0,axis_y2_padding:{},axis_y2_default:void 0,grid_x_show:!1,grid_x_type:"tick",grid_x_lines:[],grid_y_show:!1,grid_y_lines:[],grid_y_ticks:10,grid_focus_show:!0,grid_lines_front:!0,point_show:!0,point_r:2.5,point_sensitivity:10,point_focus_expand_enabled:!0,point_focus_expand_r:void 0,point_select_r:void 0,line_connectNull:!1,line_step_type:"step",bar_width:void 0,bar_width_ratio:.6,bar_width_max:void 0,bar_zerobased:!0,area_zerobased:!0,pie_label_show:!0,pie_label_format:void 0,pie_label_threshold:.05,pie_expand:{},pie_expand_duration:50,gauge_label_show:!0,gauge_label_format:void 0,gauge_min:0,gauge_max:100,gauge_units:void 0,gauge_width:void 0,gauge_expand:{},gauge_expand_duration:50,donut_label_show:!0,donut_label_format:void 0,donut_label_threshold:.05,donut_width:void 0,donut_title:"",donut_expand:{},donut_expand_duration:50,spline_interpolation_type:"cardinal",regions:[],tooltip_show:!0,tooltip_grouped:!0,tooltip_format_title:void 0,tooltip_format_name:void 0,tooltip_format_value:void 0,tooltip_position:void 0,tooltip_contents:function(a,b,c,d){return this.getTooltipContent?this.getTooltipContent(a,b,c,d):""},tooltip_init_show:!1,tooltip_init_x:0,tooltip_init_position:{top:"0px",left:"50px"},tooltip_onshow:function(){},tooltip_onhide:function(){},title_text:void 0,title_padding:{top:0,right:0,bottom:0,left:0},title_position:"top-center"};return Object.keys(this.additionalConfig).forEach(function(b){a[b]=this.additionalConfig[b]},this),a},i.additionalConfig={},i.loadConfig=function(a){function b(){var a=d.shift();return a&&c&&"object"==typeof c&&a in c?(c=c[a],b()):a?void 0:c}var c,d,e,f=this.config;Object.keys(f).forEach(function(g){c=a,d=g.split("_"),e=b(),q(e)&&(f[g]=e)})},i.getScale=function(a,b,c){return(c?this.d3.time.scale():this.d3.scale.linear()).range([a,b])},i.getX=function(a,b,c,d){var e,f=this,g=f.getScale(a,b,f.isTimeSeries()),h=c?g.domain(c):g;f.isCategorized()?(d=d||function(){return 0},g=function(a,b){var c=h(a)+d(a);return b?c:Math.ceil(c)}):g=function(a,b){var c=h(a);return b?c:Math.ceil(c)};for(e in h)g[e]=h[e];return g.orgDomain=function(){return h.domain()},f.isCategorized()&&(g.domain=function(a){return arguments.length?(h.domain(a),g):(a=this.orgDomain(),[a[0],a[1]+1])}),g},i.getY=function(a,b,c){var d=this.getScale(a,b,this.isTimeSeriesY());return c&&d.domain(c),d},i.getYScale=function(a){return"y2"===this.axis.getId(a)?this.y2:this.y},i.getSubYScale=function(a){return"y2"===this.axis.getId(a)?this.subY2:this.subY},i.updateScales=function(){var a=this,b=a.config,c=!a.x;a.xMin=b.axis_rotated?1:0,a.xMax=b.axis_rotated?a.height:a.width,a.yMin=b.axis_rotated?0:a.height,a.yMax=b.axis_rotated?a.width:1,a.subXMin=a.xMin,a.subXMax=a.xMax,a.subYMin=b.axis_rotated?0:a.height2,a.subYMax=b.axis_rotated?a.width2:1,a.x=a.getX(a.xMin,a.xMax,c?void 0:a.x.orgDomain(),function(){return a.xAxis.tickOffset()}),a.y=a.getY(a.yMin,a.yMax,c?b.axis_y_default:a.y.domain()),a.y2=a.getY(a.yMin,a.yMax,c?b.axis_y2_default:a.y2.domain()),a.subX=a.getX(a.xMin,a.xMax,a.orgXDomain,function(b){return b%1?0:a.subXAxis.tickOffset()}),a.subY=a.getY(a.subYMin,a.subYMax,c?b.axis_y_default:a.subY.domain()),a.subY2=a.getY(a.subYMin,a.subYMax,c?b.axis_y2_default:a.subY2.domain()),a.xAxisTickFormat=a.axis.getXAxisTickFormat(),a.xAxisTickValues=a.axis.getXAxisTickValues(),a.yAxisTickValues=a.axis.getYAxisTickValues(),a.y2AxisTickValues=a.axis.getY2AxisTickValues(),a.xAxis=a.axis.getXAxis(a.x,a.xOrient,a.xAxisTickFormat,a.xAxisTickValues,b.axis_x_tick_outer),a.subXAxis=a.axis.getXAxis(a.subX,a.subXOrient,a.xAxisTickFormat,a.xAxisTickValues,b.axis_x_tick_outer),a.yAxis=a.axis.getYAxis(a.y,a.yOrient,b.axis_y_tick_format,a.yAxisTickValues,b.axis_y_tick_outer),a.y2Axis=a.axis.getYAxis(a.y2,a.y2Orient,b.axis_y2_tick_format,a.y2AxisTickValues,b.axis_y2_tick_outer),c||(a.brush&&a.brush.scale(a.subX),b.zoom_enabled&&a.zoom.scale(a.x)),a.updateArc&&a.updateArc()},i.getYDomainMin=function(a){var b,c,d,e,f,g,h=this,i=h.config,j=h.mapToIds(a),k=h.getValuesAsIdKeyed(a);if(i.data_groups.length>0)for(g=h.hasNegativeValueInTargets(a),b=0;b<i.data_groups.length;b++)if(e=i.data_groups[b].filter(function(a){return j.indexOf(a)>=0}),0!==e.length)for(d=e[0],g&&k[d]&&k[d].forEach(function(a,b){k[d][b]=0>a?a:0}),c=1;c<e.length;c++)f=e[c],k[f]&&k[f].forEach(function(a,b){h.axis.getId(f)!==h.axis.getId(d)||!k[d]||g&&+a>0||(k[d][b]+=+a)});return h.d3.min(Object.keys(k).map(function(a){return h.d3.min(k[a])}))},i.getYDomainMax=function(a){var b,c,d,e,f,g,h=this,i=h.config,j=h.mapToIds(a),k=h.getValuesAsIdKeyed(a);if(i.data_groups.length>0)for(g=h.hasPositiveValueInTargets(a),b=0;b<i.data_groups.length;b++)if(e=i.data_groups[b].filter(function(a){return j.indexOf(a)>=0}),0!==e.length)for(d=e[0],g&&k[d]&&k[d].forEach(function(a,b){k[d][b]=a>0?a:0}),c=1;c<e.length;c++)f=e[c],k[f]&&k[f].forEach(function(a,b){h.axis.getId(f)!==h.axis.getId(d)||!k[d]||g&&0>+a||(k[d][b]+=+a)});return h.d3.max(Object.keys(k).map(function(a){return h.d3.max(k[a])}))},i.getYDomain=function(a,b,c){var d,e,f,g,h,i,j,k,l,n,o,p=this,q=p.config,r=a.filter(function(a){return p.axis.getId(a.id)===b}),s=c?p.filterByXDomain(r,c):r,u="y2"===b?q.axis_y2_min:q.axis_y_min,w="y2"===b?q.axis_y2_max:q.axis_y_max,x=p.getYDomainMin(s),y=p.getYDomainMax(s),z="y2"===b?q.axis_y2_center:q.axis_y_center,A=p.hasType("bar",s)&&q.bar_zerobased||p.hasType("area",s)&&q.area_zerobased,B="y2"===b?q.axis_y2_inverted:q.axis_y_inverted,C=p.hasDataLabel()&&q.axis_rotated,D=p.hasDataLabel()&&!q.axis_rotated;return x=m(u)?u:m(w)?w>x?x:w-10:x,y=m(w)?w:m(u)?y>u?y:u+10:y,0===s.length?"y2"===b?p.y2.domain():p.y.domain():(isNaN(x)&&(x=0),isNaN(y)&&(y=x),x===y&&(0>x?y=0:x=0),n=x>=0&&y>=0,o=0>=x&&0>=y,(m(u)&&n||m(w)&&o)&&(A=!1),A&&(n&&(x=0),o&&(y=0)),e=Math.abs(y-x),f=g=h=.1*e,"undefined"!=typeof z&&(i=Math.max(Math.abs(x),Math.abs(y)),y=z+i,x=z-i),C?(j=p.getDataLabelLength(x,y,"width"),k=t(p.y.range()),l=[j[0]/k,j[1]/k],g+=e*(l[1]/(1-l[0]-l[1])),h+=e*(l[0]/(1-l[0]-l[1]))):D&&(j=p.getDataLabelLength(x,y,"height"),g+=p.axis.convertPixelsToAxisPadding(j[1],e),h+=p.axis.convertPixelsToAxisPadding(j[0],e)),"y"===b&&v(q.axis_y_padding)&&(g=p.axis.getPadding(q.axis_y_padding,"top",g,e),
2
+h=p.axis.getPadding(q.axis_y_padding,"bottom",h,e)),"y2"===b&&v(q.axis_y2_padding)&&(g=p.axis.getPadding(q.axis_y2_padding,"top",g,e),h=p.axis.getPadding(q.axis_y2_padding,"bottom",h,e)),A&&(n&&(h=x),o&&(g=-y)),d=[x-h,y+g],B?d.reverse():d)},i.getXDomainMin=function(a){var b=this,c=b.config;return q(c.axis_x_min)?b.isTimeSeries()?this.parseDate(c.axis_x_min):c.axis_x_min:b.d3.min(a,function(a){return b.d3.min(a.values,function(a){return a.x})})},i.getXDomainMax=function(a){var b=this,c=b.config;return q(c.axis_x_max)?b.isTimeSeries()?this.parseDate(c.axis_x_max):c.axis_x_max:b.d3.max(a,function(a){return b.d3.max(a.values,function(a){return a.x})})},i.getXDomainPadding=function(a){var b,c,d,e,f=this,g=f.config,h=a[1]-a[0];return f.isCategorized()?c=0:f.hasType("bar")?(b=f.getMaxDataCount(),c=b>1?h/(b-1)/2:.5):c=.01*h,"object"==typeof g.axis_x_padding&&v(g.axis_x_padding)?(d=m(g.axis_x_padding.left)?g.axis_x_padding.left:c,e=m(g.axis_x_padding.right)?g.axis_x_padding.right:c):d=e="number"==typeof g.axis_x_padding?g.axis_x_padding:c,{left:d,right:e}},i.getXDomain=function(a){var b=this,c=[b.getXDomainMin(a),b.getXDomainMax(a)],d=c[0],e=c[1],f=b.getXDomainPadding(c),g=0,h=0;return d-e!==0||b.isCategorized()||(b.isTimeSeries()?(d=new Date(.5*d.getTime()),e=new Date(1.5*e.getTime())):(d=0===d?1:.5*d,e=0===e?-1:1.5*e)),(d||0===d)&&(g=b.isTimeSeries()?new Date(d.getTime()-f.left):d-f.left),(e||0===e)&&(h=b.isTimeSeries()?new Date(e.getTime()+f.right):e+f.right),[g,h]},i.updateXDomain=function(a,b,c,d,e){var f=this,g=f.config;return c&&(f.x.domain(e?e:f.d3.extent(f.getXDomain(a))),f.orgXDomain=f.x.domain(),g.zoom_enabled&&f.zoom.scale(f.x).updateScaleExtent(),f.subX.domain(f.x.domain()),f.brush&&f.brush.scale(f.subX)),b&&(f.x.domain(e?e:!f.brush||f.brush.empty()?f.orgXDomain:f.brush.extent()),g.zoom_enabled&&f.zoom.scale(f.x).updateScaleExtent()),d&&f.x.domain(f.trimXDomain(f.x.orgDomain())),f.x.domain()},i.trimXDomain=function(a){var b=this.getZoomDomain(),c=b[0],d=b[1];return a[0]<=c&&(a[1]=+a[1]+(c-a[0]),a[0]=c),d<=a[1]&&(a[0]=+a[0]-(a[1]-d),a[1]=d),a},i.isX=function(a){var b=this,c=b.config;return c.data_x&&a===c.data_x||v(c.data_xs)&&x(c.data_xs,a)},i.isNotX=function(a){return!this.isX(a)},i.getXKey=function(a){var b=this,c=b.config;return c.data_x?c.data_x:v(c.data_xs)?c.data_xs[a]:null},i.getXValuesOfXKey=function(a,b){var c,d=this,e=b&&v(b)?d.mapToIds(b):[];return e.forEach(function(b){d.getXKey(b)===a&&(c=d.data.xs[b])}),c},i.getIndexByX=function(a){var b=this,c=b.filterByX(b.data.targets,a);return c.length?c[0].index:null},i.getXValue=function(a,b){var c=this;return a in c.data.xs&&c.data.xs[a]&&m(c.data.xs[a][b])?c.data.xs[a][b]:b},i.getOtherTargetXs=function(){var a=this,b=Object.keys(a.data.xs);return b.length?a.data.xs[b[0]]:null},i.getOtherTargetX=function(a){var b=this.getOtherTargetXs();return b&&a<b.length?b[a]:null},i.addXs=function(a){var b=this;Object.keys(a).forEach(function(c){b.config.data_xs[c]=a[c]})},i.hasMultipleX=function(a){return this.d3.set(Object.keys(a).map(function(b){return a[b]})).size()>1},i.isMultipleX=function(){return v(this.config.data_xs)||!this.config.data_xSort||this.hasType("scatter")},i.addName=function(a){var b,c=this;return a&&(b=c.config.data_names[a.id],a.name=void 0!==b?b:a.id),a},i.getValueOnIndex=function(a,b){var c=a.filter(function(a){return a.index===b});return c.length?c[0]:null},i.updateTargetX=function(a,b){var c=this;a.forEach(function(a){a.values.forEach(function(d,e){d.x=c.generateTargetX(b[e],a.id,e)}),c.data.xs[a.id]=b})},i.updateTargetXs=function(a,b){var c=this;a.forEach(function(a){b[a.id]&&c.updateTargetX([a],b[a.id])})},i.generateTargetX=function(a,b,c){var d,e=this;return d=e.isTimeSeries()?a?e.parseDate(a):e.parseDate(e.getXValue(b,c)):e.isCustomX()&&!e.isCategorized()?m(a)?+a:e.getXValue(b,c):c},i.cloneTarget=function(a){return{id:a.id,id_org:a.id_org,values:a.values.map(function(a){return{x:a.x,value:a.value,id:a.id}})}},i.updateXs=function(){var a=this;a.data.targets.length&&(a.xs=[],a.data.targets[0].values.forEach(function(b){a.xs[b.index]=b.x}))},i.getPrevX=function(a){var b=this.xs[a-1];return"undefined"!=typeof b?b:null},i.getNextX=function(a){var b=this.xs[a+1];return"undefined"!=typeof b?b:null},i.getMaxDataCount=function(){var a=this;return a.d3.max(a.data.targets,function(a){return a.values.length})},i.getMaxDataCountTarget=function(a){var b,c=a.length,d=0;return c>1?a.forEach(function(a){a.values.length>d&&(b=a,d=a.values.length)}):b=c?a[0]:null,b},i.getEdgeX=function(a){var b=this;return a.length?[b.d3.min(a,function(a){return a.values[0].x}),b.d3.max(a,function(a){return a.values[a.values.length-1].x})]:[0,0]},i.mapToIds=function(a){return a.map(function(a){return a.id})},i.mapToTargetIds=function(a){var b=this;return a?[].concat(a):b.mapToIds(b.data.targets)},i.hasTarget=function(a,b){var c,d=this.mapToIds(a);for(c=0;c<d.length;c++)if(d[c]===b)return!0;return!1},i.isTargetToShow=function(a){return this.hiddenTargetIds.indexOf(a)<0},i.isLegendToShow=function(a){return this.hiddenLegendIds.indexOf(a)<0},i.filterTargetsToShow=function(a){var b=this;return a.filter(function(a){return b.isTargetToShow(a.id)})},i.mapTargetsToUniqueXs=function(a){var b=this,c=b.d3.set(b.d3.merge(a.map(function(a){return a.values.map(function(a){return+a.x})}))).values();return c=b.isTimeSeries()?c.map(function(a){return new Date(+a)}):c.map(function(a){return+a}),c.sort(function(a,b){return b>a?-1:a>b?1:a>=b?0:NaN})},i.addHiddenTargetIds=function(a){this.hiddenTargetIds=this.hiddenTargetIds.concat(a)},i.removeHiddenTargetIds=function(a){this.hiddenTargetIds=this.hiddenTargetIds.filter(function(b){return a.indexOf(b)<0})},i.addHiddenLegendIds=function(a){this.hiddenLegendIds=this.hiddenLegendIds.concat(a)},i.removeHiddenLegendIds=function(a){this.hiddenLegendIds=this.hiddenLegendIds.filter(function(b){return a.indexOf(b)<0})},i.getValuesAsIdKeyed=function(a){var b={};return a.forEach(function(a){b[a.id]=[],a.values.forEach(function(c){b[a.id].push(c.value)})}),b},i.checkValueInTargets=function(a,b){var c,d,e,f=Object.keys(a);for(c=0;c<f.length;c++)for(e=a[f[c]].values,d=0;d<e.length;d++)if(b(e[d].value))return!0;return!1},i.hasNegativeValueInTargets=function(a){return this.checkValueInTargets(a,function(a){return 0>a})},i.hasPositiveValueInTargets=function(a){return this.checkValueInTargets(a,function(a){return a>0})},i.isOrderDesc=function(){var a=this.config;return"string"==typeof a.data_order&&"desc"===a.data_order.toLowerCase()},i.isOrderAsc=function(){var a=this.config;return"string"==typeof a.data_order&&"asc"===a.data_order.toLowerCase()},i.orderTargets=function(a){var b=this,c=b.config,d=b.isOrderAsc(),e=b.isOrderDesc();return d||e?a.sort(function(a,b){var c=function(a,b){return a+Math.abs(b.value)},e=a.values.reduce(c,0),f=b.values.reduce(c,0);return d?f-e:e-f}):n(c.data_order)&&a.sort(c.data_order),a},i.filterByX=function(a,b){return this.d3.merge(a.map(function(a){return a.values})).filter(function(a){return a.x-b===0})},i.filterRemoveNull=function(a){return a.filter(function(a){return m(a.value)})},i.filterByXDomain=function(a,b){return a.map(function(a){return{id:a.id,id_org:a.id_org,values:a.values.filter(function(a){return b[0]<=a.x&&a.x<=b[1]})}})},i.hasDataLabel=function(){var a=this.config;return"boolean"==typeof a.data_labels&&a.data_labels?!0:"object"==typeof a.data_labels&&v(a.data_labels)?!0:!1},i.getDataLabelLength=function(a,b,c){var d=this,e=[0,0],f=1.3;return d.selectChart.select("svg").selectAll(".dummy").data([a,b]).enter().append("text").text(function(a){return d.dataLabelFormat(a.id)(a)}).each(function(a,b){e[b]=this.getBoundingClientRect()[c]*f}).remove(),e},i.isNoneArc=function(a){return this.hasTarget(this.data.targets,a.id)},i.isArc=function(a){return"data"in a&&this.hasTarget(this.data.targets,a.data.id)},i.findSameXOfValues=function(a,b){var c,d=a[b].x,e=[];for(c=b-1;c>=0&&d===a[c].x;c--)e.push(a[c]);for(c=b;c<a.length&&d===a[c].x;c++)e.push(a[c]);return e},i.findClosestFromTargets=function(a,b){var c,d=this;return c=a.map(function(a){return d.findClosest(a.values,b)}),d.findClosest(c,b)},i.findClosest=function(a,b){var c,d=this,e=d.config.point_sensitivity;return a.filter(function(a){return a&&d.isBarType(a.id)}).forEach(function(a){var b=d.main.select("."+l.bars+d.getTargetSelectorSuffix(a.id)+" ."+l.bar+"-"+a.index).node();!c&&d.isWithinBar(b)&&(c=a)}),a.filter(function(a){return a&&!d.isBarType(a.id)}).forEach(function(a){var f=d.dist(a,b);e>f&&(e=f,c=a)}),c},i.dist=function(a,b){var c=this,d=c.config,e=d.axis_rotated?1:0,f=d.axis_rotated?0:1,g=c.circleY(a,a.index),h=c.x(a.x);return Math.sqrt(Math.pow(h-b[e],2)+Math.pow(g-b[f],2))},i.convertValuesToStep=function(a){var b,c=[].concat(a);if(!this.isCategorized())return a;for(b=a.length+1;b>0;b--)c[b]=c[b-1];return c[0]={x:c[0].x-1,value:c[0].value,id:c[0].id},c[a.length+1]={x:c[a.length].x+1,value:c[a.length].value,id:c[a.length].id},c},i.updateDataAttributes=function(a,b){var c=this,d=c.config,e=d["data_"+a];return"undefined"==typeof b?e:(Object.keys(b).forEach(function(a){e[a]=b[a]}),c.redraw({withLegend:!0}),e)},i.convertUrlToData=function(a,b,c,d){var e=this,f=b?b:"csv";e.d3.xhr(a,function(a,b){var g;if(!b)throw new Error(a.responseURL+" "+a.status+" ("+a.statusText+")");g="json"===f?e.convertJsonToData(JSON.parse(b.response),c):"tsv"===f?e.convertTsvToData(b.response):e.convertCsvToData(b.response),d.call(e,g)})},i.convertXsvToData=function(a,b){var c,d=b.parseRows(a);return 1===d.length?(c=[{}],d[0].forEach(function(a){c[0][a]=null})):c=b.parse(a),c},i.convertCsvToData=function(a){return this.convertXsvToData(a,this.d3.csv)},i.convertTsvToData=function(a){return this.convertXsvToData(a,this.d3.tsv)},i.convertJsonToData=function(a,b){var c,d,e=this,f=[];return b?(b.x?(c=b.value.concat(b.x),e.config.data_x=b.x):c=b.value,f.push(c),a.forEach(function(a){var b=[];c.forEach(function(c){var d=p(a[c])?null:a[c];b.push(d)}),f.push(b)}),d=e.convertRowsToData(f)):(Object.keys(a).forEach(function(b){f.push([b].concat(a[b]))}),d=e.convertColumnsToData(f)),d},i.convertRowsToData=function(a){var b,c,d=a[0],e={},f=[];for(b=1;b<a.length;b++){for(e={},c=0;c<a[b].length;c++){if(p(a[b][c]))throw new Error("Source data is missing a component at ("+b+","+c+")!");e[d[c]]=a[b][c]}f.push(e)}return f},i.convertColumnsToData=function(a){var b,c,d,e=[];for(b=0;b<a.length;b++)for(d=a[b][0],c=1;c<a[b].length;c++){if(p(e[c-1])&&(e[c-1]={}),p(a[b][c]))throw new Error("Source data is missing a component at ("+b+","+c+")!");e[c-1][d]=a[b][c]}return e},i.convertDataToTargets=function(a,b){var c,d=this,e=d.config,f=d.d3.keys(a[0]).filter(d.isNotX,d),g=d.d3.keys(a[0]).filter(d.isX,d);return f.forEach(function(c){var f=d.getXKey(c);d.isCustomX()||d.isTimeSeries()?g.indexOf(f)>=0?d.data.xs[c]=(b&&d.data.xs[c]?d.data.xs[c]:[]).concat(a.map(function(a){return a[f]}).filter(m).map(function(a,b){return d.generateTargetX(a,c,b)})):e.data_x?d.data.xs[c]=d.getOtherTargetXs():v(e.data_xs)&&(d.data.xs[c]=d.getXValuesOfXKey(f,d.data.targets)):d.data.xs[c]=a.map(function(a,b){return b})}),f.forEach(function(a){if(!d.data.xs[a])throw new Error('x is not defined for id = "'+a+'".')}),c=f.map(function(b,c){var f=e.data_idConverter(b);return{id:f,id_org:b,values:a.map(function(a,g){var h=d.getXKey(b),i=a[h],j=d.generateTargetX(i,b,g),k=null===a[b]||isNaN(a[b])?null:+a[b];return d.isCustomX()&&d.isCategorized()&&0===c&&i&&(0===g&&(e.axis_x_categories=[]),e.axis_x_categories.push(i)),(p(a[b])||d.data.xs[b].length<=g)&&(j=void 0),{x:j,value:k,id:f}}).filter(function(a){return q(a.x)})}}),c.forEach(function(a){var b;e.data_xSort&&(a.values=a.values.sort(function(a,b){var c=a.x||0===a.x?a.x:1/0,d=b.x||0===b.x?b.x:1/0;return c-d})),b=0,a.values.forEach(function(a){a.index=b++}),d.data.xs[a.id].sort(function(a,b){return a-b})}),d.hasNegativeValue=d.hasNegativeValueInTargets(c),d.hasPositiveValue=d.hasPositiveValueInTargets(c),e.data_type&&d.setTargetType(d.mapToIds(c).filter(function(a){return!(a in e.data_types)}),e.data_type),c.forEach(function(a){d.addCache(a.id_org,a)}),c},i.load=function(a,b){var c=this;a&&(b.filter&&(a=a.filter(b.filter)),(b.type||b.types)&&a.forEach(function(a){var d=b.types&&b.types[a.id]?b.types[a.id]:b.type;c.setTargetType(a.id,d)}),c.data.targets.forEach(function(b){for(var c=0;c<a.length;c++)if(b.id===a[c].id){b.values=a[c].values,a.splice(c,1);break}}),c.data.targets=c.data.targets.concat(a)),c.updateTargets(c.data.targets),c.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0,withLegend:!0}),b.done&&b.done()},i.loadFromArgs=function(a){var b=this;a.data?b.load(b.convertDataToTargets(a.data),a):a.url?b.convertUrlToData(a.url,a.mimeType,a.keys,function(c){b.load(b.convertDataToTargets(c),a)}):a.json?b.load(b.convertDataToTargets(b.convertJsonToData(a.json,a.keys)),a):a.rows?b.load(b.convertDataToTargets(b.convertRowsToData(a.rows)),a):a.columns?b.load(b.convertDataToTargets(b.convertColumnsToData(a.columns)),a):b.load(null,a)},i.unload=function(a,b){var c=this;return b||(b=function(){}),a=a.filter(function(a){return c.hasTarget(c.data.targets,a)}),a&&0!==a.length?(c.svg.selectAll(a.map(function(a){return c.selectorTarget(a)})).transition().style("opacity",0).remove().call(c.endall,b),void a.forEach(function(a){c.withoutFadeIn[a]=!1,c.legend&&c.legend.selectAll("."+l.legendItem+c.getTargetSelectorSuffix(a)).remove(),c.data.targets=c.data.targets.filter(function(b){return b.id!==a})})):void b()},i.categoryName=function(a){var b=this.config;return a<b.axis_x_categories.length?b.axis_x_categories[a]:a},i.initEventRect=function(){var a=this;a.main.select("."+l.chart).append("g").attr("class",l.eventRects).style("fill-opacity",0)},i.redrawEventRect=function(){var a,b,c=this,d=c.config,e=c.isMultipleX(),f=c.main.select("."+l.eventRects).style("cursor",d.zoom_enabled?d.axis_rotated?"ns-resize":"ew-resize":null).classed(l.eventRectsMultiple,e).classed(l.eventRectsSingle,!e);f.selectAll("."+l.eventRect).remove(),c.eventRect=f.selectAll("."+l.eventRect),e?(a=c.eventRect.data([0]),c.generateEventRectsForMultipleXs(a.enter()),c.updateEventRect(a)):(b=c.getMaxDataCountTarget(c.data.targets),f.datum(b?b.values:[]),c.eventRect=f.selectAll("."+l.eventRect),a=c.eventRect.data(function(a){return a}),c.generateEventRectsForSingleX(a.enter()),c.updateEventRect(a),a.exit().remove())},i.updateEventRect=function(a){var b,c,d,e,f,g,h=this,i=h.config;a=a||h.eventRect.data(function(a){return a}),h.isMultipleX()?(b=0,c=0,d=h.width,e=h.height):(!h.isCustomX()&&!h.isTimeSeries()||h.isCategorized()?(f=h.getEventRectWidth(),g=function(a){return h.x(a.x)-f/2}):(h.updateXs(),f=function(a){var b=h.getPrevX(a.index),c=h.getNextX(a.index);return null===b&&null===c?i.axis_rotated?h.height:h.width:(null===b&&(b=h.x.domain()[0]),null===c&&(c=h.x.domain()[1]),Math.max(0,(h.x(c)-h.x(b))/2))},g=function(a){var b=h.getPrevX(a.index),c=h.getNextX(a.index),d=h.data.xs[a.id][a.index];return null===b&&null===c?0:(null===b&&(b=h.x.domain()[0]),(h.x(d)+h.x(b))/2)}),b=i.axis_rotated?0:g,c=i.axis_rotated?g:0,d=i.axis_rotated?h.width:f,e=i.axis_rotated?f:h.height),a.attr("class",h.classEvent.bind(h)).attr("x",b).attr("y",c).attr("width",d).attr("height",e)},i.generateEventRectsForSingleX=function(a){var b=this,c=b.d3,d=b.config;a.append("rect").attr("class",b.classEvent.bind(b)).style("cursor",d.data_selection_enabled&&d.data_selection_grouped?"pointer":null).on("mouseover",function(a){var c=a.index;b.dragging||b.flowing||b.hasArcType()||(d.point_focus_expand_enabled&&b.expandCircles(c,null,!0),b.expandBars(c,null,!0),b.main.selectAll("."+l.shape+"-"+c).each(function(a){d.data_onmouseover.call(b.api,a)}))}).on("mouseout",function(a){var c=a.index;b.config&&(b.hasArcType()||(b.hideXGridFocus(),b.hideTooltip(),b.unexpandCircles(),b.unexpandBars(),b.main.selectAll("."+l.shape+"-"+c).each(function(a){d.data_onmouseout.call(b.api,a)})))}).on("mousemove",function(a){var e,f=a.index,g=b.svg.select("."+l.eventRect+"-"+f);b.dragging||b.flowing||b.hasArcType()||(b.isStepType(a)&&"step-after"===b.config.line_step_type&&c.mouse(this)[0]<b.x(b.getXValue(a.id,f))&&(f-=1),e=b.filterTargetsToShow(b.data.targets).map(function(a){return b.addName(b.getValueOnIndex(a.values,f))}),d.tooltip_grouped&&(b.showTooltip(e,this),b.showXGridFocus(e)),(!d.tooltip_grouped||d.data_selection_enabled&&!d.data_selection_grouped)&&b.main.selectAll("."+l.shape+"-"+f).each(function(){c.select(this).classed(l.EXPANDED,!0),d.data_selection_enabled&&g.style("cursor",d.data_selection_grouped?"pointer":null),d.tooltip_grouped||(b.hideXGridFocus(),b.hideTooltip(),d.data_selection_grouped||(b.unexpandCircles(f),b.unexpandBars(f)))}).filter(function(a){return b.isWithinShape(this,a)}).each(function(a){d.data_selection_enabled&&(d.data_selection_grouped||d.data_selection_isselectable(a))&&g.style("cursor","pointer"),d.tooltip_grouped||(b.showTooltip([a],this),b.showXGridFocus([a]),d.point_focus_expand_enabled&&b.expandCircles(f,a.id,!0),b.expandBars(f,a.id,!0))}))}).on("click",function(a){var e=a.index;if(!b.hasArcType()&&b.toggleShape){if(b.cancelClick)return void(b.cancelClick=!1);b.isStepType(a)&&"step-after"===d.line_step_type&&c.mouse(this)[0]<b.x(b.getXValue(a.id,e))&&(e-=1),b.main.selectAll("."+l.shape+"-"+e).each(function(a){(d.data_selection_grouped||b.isWithinShape(this,a))&&(b.toggleShape(this,a,e),b.config.data_onclick.call(b.api,a,this))})}}).call(d.data_selection_draggable&&b.drag?c.behavior.drag().origin(Object).on("drag",function(){b.drag(c.mouse(this))}).on("dragstart",function(){b.dragstart(c.mouse(this))}).on("dragend",function(){b.dragend()}):function(){})},i.generateEventRectsForMultipleXs=function(a){function b(){c.svg.select("."+l.eventRect).style("cursor",null),c.hideXGridFocus(),c.hideTooltip(),c.unexpandCircles(),c.unexpandBars()}var c=this,d=c.d3,e=c.config;a.append("rect").attr("x",0).attr("y",0).attr("width",c.width).attr("height",c.height).attr("class",l.eventRect).on("mouseout",function(){c.config&&(c.hasArcType()||b())}).on("mousemove",function(){var a,f,g,h,i=c.filterTargetsToShow(c.data.targets);if(!c.dragging&&!c.hasArcType(i)){if(a=d.mouse(this),f=c.findClosestFromTargets(i,a),!c.mouseover||f&&f.id===c.mouseover.id||(e.data_onmouseout.call(c.api,c.mouseover),c.mouseover=void 0),!f)return void b();g=c.isScatterType(f)||!e.tooltip_grouped?[f]:c.filterByX(i,f.x),h=g.map(function(a){return c.addName(a)}),c.showTooltip(h,this),e.point_focus_expand_enabled&&c.expandCircles(f.index,f.id,!0),c.expandBars(f.index,f.id,!0),c.showXGridFocus(h),(c.isBarType(f.id)||c.dist(f,a)<e.point_sensitivity)&&(c.svg.select("."+l.eventRect).style("cursor","pointer"),c.mouseover||(e.data_onmouseover.call(c.api,f),c.mouseover=f))}}).on("click",function(){var a,b,f=c.filterTargetsToShow(c.data.targets);c.hasArcType(f)||(a=d.mouse(this),b=c.findClosestFromTargets(f,a),b&&(c.isBarType(b.id)||c.dist(b,a)<e.point_sensitivity)&&c.main.selectAll("."+l.shapes+c.getTargetSelectorSuffix(b.id)).selectAll("."+l.shape+"-"+b.index).each(function(){(e.data_selection_grouped||c.isWithinShape(this,b))&&(c.toggleShape(this,b,b.index),c.config.data_onclick.call(c.api,b,this))}))}).call(e.data_selection_draggable&&c.drag?d.behavior.drag().origin(Object).on("drag",function(){c.drag(d.mouse(this))}).on("dragstart",function(){c.dragstart(d.mouse(this))}).on("dragend",function(){c.dragend()}):function(){})},i.dispatchEvent=function(b,c,d){var e=this,f="."+l.eventRect+(e.isMultipleX()?"":"-"+c),g=e.main.select(f).node(),h=g.getBoundingClientRect(),i=h.left+(d?d[0]:0),j=h.top+(d?d[1]:0),k=document.createEvent("MouseEvents");k.initMouseEvent(b,!0,!0,a,0,i,j,i,j,!1,!1,!1,!1,0,null),g.dispatchEvent(k)},i.getCurrentWidth=function(){var a=this,b=a.config;return b.size_width?b.size_width:a.getParentWidth()},i.getCurrentHeight=function(){var a=this,b=a.config,c=b.size_height?b.size_height:a.getParentHeight();return c>0?c:320/(a.hasType("gauge")?2:1)},i.getCurrentPaddingTop=function(){var a=this,b=a.config,c=m(b.padding_top)?b.padding_top:0;return a.title&&a.title.node()&&(c+=a.getTitlePadding()),c},i.getCurrentPaddingBottom=function(){var a=this.config;return m(a.padding_bottom)?a.padding_bottom:0},i.getCurrentPaddingLeft=function(a){var b=this,c=b.config;return m(c.padding_left)?c.padding_left:c.axis_rotated?c.axis_x_show?Math.max(r(b.getAxisWidthByAxisId("x",a)),40):1:!c.axis_y_show||c.axis_y_inner?b.axis.getYAxisLabelPosition().isOuter?30:1:r(b.getAxisWidthByAxisId("y",a))},i.getCurrentPaddingRight=function(){var a=this,b=a.config,c=10,d=a.isLegendRight?a.getLegendWidth()+20:0;return m(b.padding_right)?b.padding_right+1:b.axis_rotated?c+d:!b.axis_y2_show||b.axis_y2_inner?2+d+(a.axis.getY2AxisLabelPosition().isOuter?20:0):r(a.getAxisWidthByAxisId("y2"))+d},i.getParentRectValue=function(a){for(var b,c=this.selectChart.node();c&&"BODY"!==c.tagName;){try{b=c.getBoundingClientRect()[a]}catch(d){"width"===a&&(b=c.offsetWidth)}if(b)break;c=c.parentNode}return b},i.getParentWidth=function(){return this.getParentRectValue("width")},i.getParentHeight=function(){var a=this.selectChart.style("height");return a.indexOf("px")>0?+a.replace("px",""):0},i.getSvgLeft=function(a){var b=this,c=b.config,d=c.axis_rotated||!c.axis_rotated&&!c.axis_y_inner,e=c.axis_rotated?l.axisX:l.axisY,f=b.main.select("."+e).node(),g=f&&d?f.getBoundingClientRect():{right:0},h=b.selectChart.node().getBoundingClientRect(),i=b.hasArcType(),j=g.right-h.left-(i?0:b.getCurrentPaddingLeft(a));return j>0?j:0},i.getAxisWidthByAxisId=function(a,b){var c=this,d=c.axis.getLabelPositionById(a);return c.axis.getMaxTickWidth(a,b)+(d.isInner?20:40)},i.getHorizontalAxisHeight=function(a){var b=this,c=b.config,d=30;return"x"!==a||c.axis_x_show?"x"===a&&c.axis_x_height?c.axis_x_height:"y"!==a||c.axis_y_show?"y2"!==a||c.axis_y2_show?("x"===a&&!c.axis_rotated&&c.axis_x_tick_rotate&&(d=30+b.axis.getMaxTickWidth(a)*Math.cos(Math.PI*(90-c.axis_x_tick_rotate)/180)),d+(b.axis.getLabelPositionById(a).isInner?0:10)+("y2"===a?-10:0)):b.rotated_padding_top:!c.legend_show||b.isLegendRight||b.isLegendInset?1:10:8},i.getEventRectWidth=function(){return Math.max(0,this.xAxis.tickInterval())},i.getShapeIndices=function(a){var b,c,d=this,e=d.config,f={},g=0;return d.filterTargetsToShow(d.data.targets.filter(a,d)).forEach(function(a){for(b=0;b<e.data_groups.length;b++)if(!(e.data_groups[b].indexOf(a.id)<0))for(c=0;c<e.data_groups[b].length;c++)if(e.data_groups[b][c]in f){f[a.id]=f[e.data_groups[b][c]];break}p(f[a.id])&&(f[a.id]=g++)}),f.__max__=g-1,f},i.getShapeX=function(a,b,c,d){var e=this,f=d?e.subX:e.x;return function(d){var e=d.id in c?c[d.id]:0;return d.x||0===d.x?f(d.x)-a*(b/2-e):0}},i.getShapeY=function(a){var b=this;return function(c){var d=a?b.getSubYScale(c.id):b.getYScale(c.id);return d(c.value)}},i.getShapeOffset=function(a,b,c){var d=this,e=d.orderTargets(d.filterTargetsToShow(d.data.targets.filter(a,d))),f=e.map(function(a){return a.id});return function(a,g){var h=c?d.getSubYScale(a.id):d.getYScale(a.id),i=h(0),j=i;return e.forEach(function(c){var e=d.isStepType(a)?d.convertValuesToStep(c.values):c.values;c.id!==a.id&&b[c.id]===b[a.id]&&f.indexOf(c.id)<f.indexOf(a.id)&&(("undefined"==typeof e[g]||+e[g].x!==+a.x)&&(g=-1,e.forEach(function(b,c){b.x===a.x&&(g=c)})),g in e&&e[g].value*a.value>=0&&(j+=h(e[g].value)-i))}),j}},i.isWithinShape=function(a,b){var c,d=this,e=d.d3.select(a);return d.isTargetToShow(b.id)?"circle"===a.nodeName?c=d.isStepType(b)?d.isWithinStep(a,d.getYScale(b.id)(b.value)):d.isWithinCircle(a,1.5*d.pointSelectR(b)):"path"===a.nodeName&&(c=e.classed(l.bar)?d.isWithinBar(a):!0):c=!1,c},i.getInterpolate=function(a){var b=this,c=b.isInterpolationType(b.config.spline_interpolation_type)?b.config.spline_interpolation_type:"cardinal";return b.isSplineType(a)?c:b.isStepType(a)?b.config.line_step_type:"linear"},i.initLine=function(){var a=this;a.main.select("."+l.chart).append("g").attr("class",l.chartLines)},i.updateTargetsForLine=function(a){var b,c,d=this,e=d.config,f=d.classChartLine.bind(d),g=d.classLines.bind(d),h=d.classAreas.bind(d),i=d.classCircles.bind(d),j=d.classFocus.bind(d);b=d.main.select("."+l.chartLines).selectAll("."+l.chartLine).data(a).attr("class",function(a){return f(a)+j(a)}),c=b.enter().append("g").attr("class",f).style("opacity",0).style("pointer-events","none"),c.append("g").attr("class",g),c.append("g").attr("class",h),c.append("g").attr("class",function(a){return d.generateClass(l.selectedCircles,a.id)}),c.append("g").attr("class",i).style("cursor",function(a){return e.data_selection_isselectable(a)?"pointer":null}),a.forEach(function(a){d.main.selectAll("."+l.selectedCircles+d.getTargetSelectorSuffix(a.id)).selectAll("."+l.selectedCircle).each(function(b){b.value=a.values[b.index].value})})},i.updateLine=function(a){var b=this;b.mainLine=b.main.selectAll("."+l.lines).selectAll("."+l.line).data(b.lineData.bind(b)),b.mainLine.enter().append("path").attr("class",b.classLine.bind(b)).style("stroke",b.color),b.mainLine.style("opacity",b.initialOpacity.bind(b)).style("shape-rendering",function(a){return b.isStepType(a)?"crispEdges":""}).attr("transform",null),b.mainLine.exit().transition().duration(a).style("opacity",0).remove()},i.redrawLine=function(a,b){return[(b?this.mainLine.transition(Math.random().toString()):this.mainLine).attr("d",a).style("stroke",this.color).style("opacity",1)]},i.generateDrawLine=function(a,b){var c=this,d=c.config,e=c.d3.svg.line(),f=c.generateGetLinePoints(a,b),g=b?c.getSubYScale:c.getYScale,h=function(a){return(b?c.subxx:c.xx).call(c,a)},i=function(a,b){return d.data_groups.length>0?f(a,b)[0][1]:g.call(c,a.id)(a.value)};return e=d.axis_rotated?e.x(i).y(h):e.x(h).y(i),d.line_connectNull||(e=e.defined(function(a){return null!=a.value})),function(a){var f,h=d.line_connectNull?c.filterRemoveNull(a.values):a.values,i=b?c.x:c.subX,j=g.call(c,a.id),k=0,l=0;return c.isLineType(a)?d.data_regions[a.id]?f=c.lineWithRegions(h,i,j,d.data_regions[a.id]):(c.isStepType(a)&&(h=c.convertValuesToStep(h)),f=e.interpolate(c.getInterpolate(a))(h)):(h[0]&&(k=i(h[0].x),l=j(h[0].value)),f=d.axis_rotated?"M "+l+" "+k:"M "+k+" "+l),f?f:"M 0 0"}},i.generateGetLinePoints=function(a,b){var c=this,d=c.config,e=a.__max__+1,f=c.getShapeX(0,e,a,!!b),g=c.getShapeY(!!b),h=c.getShapeOffset(c.isLineType,a,!!b),i=b?c.getSubYScale:c.getYScale;return function(a,b){var e=i.call(c,a.id)(0),j=h(a,b)||e,k=f(a),l=g(a);return d.axis_rotated&&(0<a.value&&e>l||a.value<0&&l>e)&&(l=e),[[k,l-(e-j)],[k,l-(e-j)],[k,l-(e-j)],[k,l-(e-j)]]}},i.lineWithRegions=function(a,b,c,d){function e(a,b){var c;for(c=0;c<b.length;c++)if(b[c].start<a&&a<=b[c].end)return!0;return!1}function f(a){return"M"+a[0][0]+" "+a[0][1]+" "+a[1][0]+" "+a[1][1]}var g,h,i,j,k,l,m,n,o,r,s,t,u=this,v=u.config,w=-1,x="M",y=u.isCategorized()?.5:0,z=[];if(q(d))for(g=0;g<d.length;g++)z[g]={},p(d[g].start)?z[g].start=a[0].x:z[g].start=u.isTimeSeries()?u.parseDate(d[g].start):d[g].start,p(d[g].end)?z[g].end=a[a.length-1].x:z[g].end=u.isTimeSeries()?u.parseDate(d[g].end):d[g].end;for(s=v.axis_rotated?function(a){return c(a.value)}:function(a){return b(a.x)},t=v.axis_rotated?function(a){return b(a.x)}:function(a){return c(a.value)},i=u.isTimeSeries()?function(a,d,e,g){var h,i=a.x.getTime(),j=d.x-a.x,l=new Date(i+j*e),m=new Date(i+j*(e+g));return h=v.axis_rotated?[[c(k(e)),b(l)],[c(k(e+g)),b(m)]]:[[b(l),c(k(e))],[b(m),c(k(e+g))]],f(h)}:function(a,d,e,g){var h;return h=v.axis_rotated?[[c(k(e),!0),b(j(e))],[c(k(e+g),!0),b(j(e+g))]]:[[b(j(e),!0),c(k(e))],[b(j(e+g),!0),c(k(e+g))]],f(h)},g=0;g<a.length;g++){if(p(z)||!e(a[g].x,z))x+=" "+s(a[g])+" "+t(a[g]);else for(j=u.getScale(a[g-1].x+y,a[g].x+y,u.isTimeSeries()),k=u.getScale(a[g-1].value,a[g].value),l=b(a[g].x)-b(a[g-1].x),m=c(a[g].value)-c(a[g-1].value),n=Math.sqrt(Math.pow(l,2)+Math.pow(m,2)),o=2/n,r=2*o,h=o;1>=h;h+=r)x+=i(a[g-1],a[g],h,o);w=a[g].x}return x},i.updateArea=function(a){var b=this,c=b.d3;b.mainArea=b.main.selectAll("."+l.areas).selectAll("."+l.area).data(b.lineData.bind(b)),b.mainArea.enter().append("path").attr("class",b.classArea.bind(b)).style("fill",b.color).style("opacity",function(){return b.orgAreaOpacity=+c.select(this).style("opacity"),0}),b.mainArea.style("opacity",b.orgAreaOpacity),b.mainArea.exit().transition().duration(a).style("opacity",0).remove()},i.redrawArea=function(a,b){return[(b?this.mainArea.transition(Math.random().toString()):this.mainArea).attr("d",a).style("fill",this.color).style("opacity",this.orgAreaOpacity)]},i.generateDrawArea=function(a,b){var c=this,d=c.config,e=c.d3.svg.area(),f=c.generateGetAreaPoints(a,b),g=b?c.getSubYScale:c.getYScale,h=function(a){return(b?c.subxx:c.xx).call(c,a)},i=function(a,b){return d.data_groups.length>0?f(a,b)[0][1]:g.call(c,a.id)(c.getAreaBaseValue(a.id))},j=function(a,b){return d.data_groups.length>0?f(a,b)[1][1]:g.call(c,a.id)(a.value)};return e=d.axis_rotated?e.x0(i).x1(j).y(h):e.x(h).y0(i).y1(j),d.line_connectNull||(e=e.defined(function(a){return null!==a.value})),function(a){var b,f=d.line_connectNull?c.filterRemoveNull(a.values):a.values,g=0,h=0;return c.isAreaType(a)?(c.isStepType(a)&&(f=c.convertValuesToStep(f)),b=e.interpolate(c.getInterpolate(a))(f)):(f[0]&&(g=c.x(f[0].x),h=c.getYScale(a.id)(f[0].value)),b=d.axis_rotated?"M "+h+" "+g:"M "+g+" "+h),b?b:"M 0 0"}},i.getAreaBaseValue=function(){return 0},i.generateGetAreaPoints=function(a,b){var c=this,d=c.config,e=a.__max__+1,f=c.getShapeX(0,e,a,!!b),g=c.getShapeY(!!b),h=c.getShapeOffset(c.isAreaType,a,!!b),i=b?c.getSubYScale:c.getYScale;return function(a,b){var e=i.call(c,a.id)(0),j=h(a,b)||e,k=f(a),l=g(a);return d.axis_rotated&&(0<a.value&&e>l||a.value<0&&l>e)&&(l=e),[[k,j],[k,l-(e-j)],[k,l-(e-j)],[k,j]]}},i.updateCircle=function(){var a=this;a.mainCircle=a.main.selectAll("."+l.circles).selectAll("."+l.circle).data(a.lineOrScatterData.bind(a)),a.mainCircle.enter().append("circle").attr("class",a.classCircle.bind(a)).attr("r",a.pointR.bind(a)).style("fill",a.color),a.mainCircle.style("opacity",a.initialOpacityForCircle.bind(a)),a.mainCircle.exit().remove()},i.redrawCircle=function(a,b,c){var d=this.main.selectAll("."+l.selectedCircle);return[(c?this.mainCircle.transition(Math.random().toString()):this.mainCircle).style("opacity",this.opacityForCircle.bind(this)).style("fill",this.color).attr("cx",a).attr("cy",b),(c?d.transition(Math.random().toString()):d).attr("cx",a).attr("cy",b)]},i.circleX=function(a){return a.x||0===a.x?this.x(a.x):null},i.updateCircleY=function(){var a,b,c=this;c.config.data_groups.length>0?(a=c.getShapeIndices(c.isLineType),b=c.generateGetLinePoints(a),c.circleY=function(a,c){return b(a,c)[0][1]}):c.circleY=function(a){return c.getYScale(a.id)(a.value)}},i.getCircles=function(a,b){var c=this;return(b?c.main.selectAll("."+l.circles+c.getTargetSelectorSuffix(b)):c.main).selectAll("."+l.circle+(m(a)?"-"+a:""))},i.expandCircles=function(a,b,c){var d=this,e=d.pointExpandedR.bind(d);c&&d.unexpandCircles(),d.getCircles(a,b).classed(l.EXPANDED,!0).attr("r",e)},i.unexpandCircles=function(a){var b=this,c=b.pointR.bind(b);b.getCircles(a).filter(function(){return b.d3.select(this).classed(l.EXPANDED)}).classed(l.EXPANDED,!1).attr("r",c)},i.pointR=function(a){var b=this,c=b.config;return b.isStepType(a)?0:n(c.point_r)?c.point_r(a):c.point_r},i.pointExpandedR=function(a){var b=this,c=b.config;return c.point_focus_expand_enabled?c.point_focus_expand_r?c.point_focus_expand_r:1.75*b.pointR(a):b.pointR(a)},i.pointSelectR=function(a){var b=this,c=b.config;return c.point_select_r?c.point_select_r:4*b.pointR(a)},i.isWithinCircle=function(a,b){var c=this.d3,d=c.mouse(a),e=c.select(a),f=+e.attr("cx"),g=+e.attr("cy");return Math.sqrt(Math.pow(f-d[0],2)+Math.pow(g-d[1],2))<b},i.isWithinStep=function(a,b){return Math.abs(b-this.d3.mouse(a)[1])<30},i.initBar=function(){var a=this;a.main.select("."+l.chart).append("g").attr("class",l.chartBars)},i.updateTargetsForBar=function(a){var b,c,d=this,e=d.config,f=d.classChartBar.bind(d),g=d.classBars.bind(d),h=d.classFocus.bind(d);b=d.main.select("."+l.chartBars).selectAll("."+l.chartBar).data(a).attr("class",function(a){
3
+return f(a)+h(a)}),c=b.enter().append("g").attr("class",f).style("opacity",0).style("pointer-events","none"),c.append("g").attr("class",g).style("cursor",function(a){return e.data_selection_isselectable(a)?"pointer":null})},i.updateBar=function(a){var b=this,c=b.barData.bind(b),d=b.classBar.bind(b),e=b.initialOpacity.bind(b),f=function(a){return b.color(a.id)};b.mainBar=b.main.selectAll("."+l.bars).selectAll("."+l.bar).data(c),b.mainBar.enter().append("path").attr("class",d).style("stroke",f).style("fill",f),b.mainBar.style("opacity",e),b.mainBar.exit().transition().duration(a).style("opacity",0).remove()},i.redrawBar=function(a,b){return[(b?this.mainBar.transition(Math.random().toString()):this.mainBar).attr("d",a).style("fill",this.color).style("opacity",1)]},i.getBarW=function(a,b){var c=this,d=c.config,e="number"==typeof d.bar_width?d.bar_width:b?a.tickInterval()*d.bar_width_ratio/b:0;return d.bar_width_max&&e>d.bar_width_max?d.bar_width_max:e},i.getBars=function(a,b){var c=this;return(b?c.main.selectAll("."+l.bars+c.getTargetSelectorSuffix(b)):c.main).selectAll("."+l.bar+(m(a)?"-"+a:""))},i.expandBars=function(a,b,c){var d=this;c&&d.unexpandBars(),d.getBars(a,b).classed(l.EXPANDED,!0)},i.unexpandBars=function(a){var b=this;b.getBars(a).classed(l.EXPANDED,!1)},i.generateDrawBar=function(a,b){var c=this,d=c.config,e=c.generateGetBarPoints(a,b);return function(a,b){var c=e(a,b),f=d.axis_rotated?1:0,g=d.axis_rotated?0:1,h="M "+c[0][f]+","+c[0][g]+" L"+c[1][f]+","+c[1][g]+" L"+c[2][f]+","+c[2][g]+" L"+c[3][f]+","+c[3][g]+" z";return h}},i.generateGetBarPoints=function(a,b){var c=this,d=b?c.subXAxis:c.xAxis,e=a.__max__+1,f=c.getBarW(d,e),g=c.getShapeX(f,e,a,!!b),h=c.getShapeY(!!b),i=c.getShapeOffset(c.isBarType,a,!!b),j=b?c.getSubYScale:c.getYScale;return function(a,b){var d=j.call(c,a.id)(0),e=i(a,b)||d,k=g(a),l=h(a);return c.config.axis_rotated&&(0<a.value&&d>l||a.value<0&&l>d)&&(l=d),[[k,e],[k,l-(d-e)],[k+f,l-(d-e)],[k+f,e]]}},i.isWithinBar=function(a){var b=this.d3.mouse(a),c=a.getBoundingClientRect(),d=a.pathSegList.getItem(0),e=a.pathSegList.getItem(1),f=Math.min(d.x,e.x),g=Math.min(d.y,e.y),h=c.width,i=c.height,j=2,k=f-j,l=f+h+j,m=g+i+j,n=g-j;return k<b[0]&&b[0]<l&&n<b[1]&&b[1]<m},i.initText=function(){var a=this;a.main.select("."+l.chart).append("g").attr("class",l.chartTexts),a.mainText=a.d3.selectAll([])},i.updateTargetsForText=function(a){var b,c,d=this,e=d.classChartText.bind(d),f=d.classTexts.bind(d),g=d.classFocus.bind(d);b=d.main.select("."+l.chartTexts).selectAll("."+l.chartText).data(a).attr("class",function(a){return e(a)+g(a)}),c=b.enter().append("g").attr("class",e).style("opacity",0).style("pointer-events","none"),c.append("g").attr("class",f)},i.updateText=function(a){var b=this,c=b.config,d=b.barOrLineData.bind(b),e=b.classText.bind(b);b.mainText=b.main.selectAll("."+l.texts).selectAll("."+l.text).data(d),b.mainText.enter().append("text").attr("class",e).attr("text-anchor",function(a){return c.axis_rotated?a.value<0?"end":"start":"middle"}).style("stroke","none").style("fill",function(a){return b.color(a)}).style("fill-opacity",0),b.mainText.text(function(a,c,d){return b.dataLabelFormat(a.id)(a.value,a.id,c,d)}),b.mainText.exit().transition().duration(a).style("fill-opacity",0).remove()},i.redrawText=function(a,b,c,d){return[(d?this.mainText.transition():this.mainText).attr("x",a).attr("y",b).style("fill",this.color).style("fill-opacity",c?0:this.opacityForText.bind(this))]},i.getTextRect=function(a,b,c){var d,e=this.d3.select("body").append("div").classed("c3",!0),f=e.append("svg").style("visibility","hidden").style("position","fixed").style("top",0).style("left",0),g=this.d3.select(c).style("font");return f.selectAll(".dummy").data([a]).enter().append("text").classed(b?b:"",!0).style("font",g).text(a).each(function(){d=this.getBoundingClientRect()}),e.remove(),d},i.generateXYForText=function(a,b,c,d){var e=this,f=e.generateGetAreaPoints(a,!1),g=e.generateGetBarPoints(b,!1),h=e.generateGetLinePoints(c,!1),i=d?e.getXForText:e.getYForText;return function(a,b){var c=e.isAreaType(a)?f:e.isBarType(a)?g:h;return i.call(e,c(a,b),a,this)}},i.getXForText=function(a,b,c){var d,e,f=this,g=c.getBoundingClientRect();return f.config.axis_rotated?(e=f.isBarType(b)?4:6,d=a[2][1]+e*(b.value<0?-1:1)):d=f.hasType("bar")?(a[2][0]+a[0][0])/2:a[0][0],null===b.value&&(d>f.width?d=f.width-g.width:0>d&&(d=4)),d},i.getYForText=function(a,b,c){var d,e=this,f=c.getBoundingClientRect();return e.config.axis_rotated?d=(a[0][0]+a[2][0]+.6*f.height)/2:(d=a[2][1],b.value<0||0===b.value&&!e.hasPositiveValue?(d+=f.height,e.isBarType(b)&&e.isSafari()?d-=3:!e.isBarType(b)&&e.isChrome()&&(d+=3)):d+=e.isBarType(b)?-3:-6),null!==b.value||e.config.axis_rotated||(d<f.height?d=f.height:d>this.height&&(d=this.height-4)),d},i.setTargetType=function(a,b){var c=this,d=c.config;c.mapToTargetIds(a).forEach(function(a){c.withoutFadeIn[a]=b===d.data_types[a],d.data_types[a]=b}),a||(d.data_type=b)},i.hasType=function(a,b){var c=this,d=c.config.data_types,e=!1;return b=b||c.data.targets,b&&b.length?b.forEach(function(b){var c=d[b.id];(c&&c.indexOf(a)>=0||!c&&"line"===a)&&(e=!0)}):Object.keys(d).length?Object.keys(d).forEach(function(b){d[b]===a&&(e=!0)}):e=c.config.data_type===a,e},i.hasArcType=function(a){return this.hasType("pie",a)||this.hasType("donut",a)||this.hasType("gauge",a)},i.isLineType=function(a){var b=this.config,c=o(a)?a:a.id;return!b.data_types[c]||["line","spline","area","area-spline","step","area-step"].indexOf(b.data_types[c])>=0},i.isStepType=function(a){var b=o(a)?a:a.id;return["step","area-step"].indexOf(this.config.data_types[b])>=0},i.isSplineType=function(a){var b=o(a)?a:a.id;return["spline","area-spline"].indexOf(this.config.data_types[b])>=0},i.isAreaType=function(a){var b=o(a)?a:a.id;return["area","area-spline","area-step"].indexOf(this.config.data_types[b])>=0},i.isBarType=function(a){var b=o(a)?a:a.id;return"bar"===this.config.data_types[b]},i.isScatterType=function(a){var b=o(a)?a:a.id;return"scatter"===this.config.data_types[b]},i.isPieType=function(a){var b=o(a)?a:a.id;return"pie"===this.config.data_types[b]},i.isGaugeType=function(a){var b=o(a)?a:a.id;return"gauge"===this.config.data_types[b]},i.isDonutType=function(a){var b=o(a)?a:a.id;return"donut"===this.config.data_types[b]},i.isArcType=function(a){return this.isPieType(a)||this.isDonutType(a)||this.isGaugeType(a)},i.lineData=function(a){return this.isLineType(a)?[a]:[]},i.arcData=function(a){return this.isArcType(a.data)?[a]:[]},i.barData=function(a){return this.isBarType(a)?a.values:[]},i.lineOrScatterData=function(a){return this.isLineType(a)||this.isScatterType(a)?a.values:[]},i.barOrLineData=function(a){return this.isBarType(a)||this.isLineType(a)?a.values:[]},i.isInterpolationType=function(a){return["linear","linear-closed","basis","basis-open","basis-closed","bundle","cardinal","cardinal-open","cardinal-closed","monotone"].indexOf(a)>=0},i.initGrid=function(){var a=this,b=a.config,c=a.d3;a.grid=a.main.append("g").attr("clip-path",a.clipPathForGrid).attr("class",l.grid),b.grid_x_show&&a.grid.append("g").attr("class",l.xgrids),b.grid_y_show&&a.grid.append("g").attr("class",l.ygrids),b.grid_focus_show&&a.grid.append("g").attr("class",l.xgridFocus).append("line").attr("class",l.xgridFocus),a.xgrid=c.selectAll([]),b.grid_lines_front||a.initGridLines()},i.initGridLines=function(){var a=this,b=a.d3;a.gridLines=a.main.append("g").attr("clip-path",a.clipPathForGrid).attr("class",l.grid+" "+l.gridLines),a.gridLines.append("g").attr("class",l.xgridLines),a.gridLines.append("g").attr("class",l.ygridLines),a.xgridLines=b.selectAll([])},i.updateXGrid=function(a){var b=this,c=b.config,d=b.d3,e=b.generateGridData(c.grid_x_type,b.x),f=b.isCategorized()?b.xAxis.tickOffset():0;b.xgridAttr=c.axis_rotated?{x1:0,x2:b.width,y1:function(a){return b.x(a)-f},y2:function(a){return b.x(a)-f}}:{x1:function(a){return b.x(a)+f},x2:function(a){return b.x(a)+f},y1:0,y2:b.height},b.xgrid=b.main.select("."+l.xgrids).selectAll("."+l.xgrid).data(e),b.xgrid.enter().append("line").attr("class",l.xgrid),a||b.xgrid.attr(b.xgridAttr).style("opacity",function(){return+d.select(this).attr(c.axis_rotated?"y1":"x1")===(c.axis_rotated?b.height:0)?0:1}),b.xgrid.exit().remove()},i.updateYGrid=function(){var a=this,b=a.config,c=a.yAxis.tickValues()||a.y.ticks(b.grid_y_ticks);a.ygrid=a.main.select("."+l.ygrids).selectAll("."+l.ygrid).data(c),a.ygrid.enter().append("line").attr("class",l.ygrid),a.ygrid.attr("x1",b.axis_rotated?a.y:0).attr("x2",b.axis_rotated?a.y:a.width).attr("y1",b.axis_rotated?0:a.y).attr("y2",b.axis_rotated?a.height:a.y),a.ygrid.exit().remove(),a.smoothLines(a.ygrid,"grid")},i.gridTextAnchor=function(a){return a.position?a.position:"end"},i.gridTextDx=function(a){return"start"===a.position?4:"middle"===a.position?0:-4},i.xGridTextX=function(a){return"start"===a.position?-this.height:"middle"===a.position?-this.height/2:0},i.yGridTextX=function(a){return"start"===a.position?0:"middle"===a.position?this.width/2:this.width},i.updateGrid=function(a){var b,c,d,e=this,f=e.main,g=e.config;e.grid.style("visibility",e.hasArcType()?"hidden":"visible"),f.select("line."+l.xgridFocus).style("visibility","hidden"),g.grid_x_show&&e.updateXGrid(),e.xgridLines=f.select("."+l.xgridLines).selectAll("."+l.xgridLine).data(g.grid_x_lines),b=e.xgridLines.enter().append("g").attr("class",function(a){return l.xgridLine+(a["class"]?" "+a["class"]:"")}),b.append("line").style("opacity",0),b.append("text").attr("text-anchor",e.gridTextAnchor).attr("transform",g.axis_rotated?"":"rotate(-90)").attr("dx",e.gridTextDx).attr("dy",-5).style("opacity",0),e.xgridLines.exit().transition().duration(a).style("opacity",0).remove(),g.grid_y_show&&e.updateYGrid(),e.ygridLines=f.select("."+l.ygridLines).selectAll("."+l.ygridLine).data(g.grid_y_lines),c=e.ygridLines.enter().append("g").attr("class",function(a){return l.ygridLine+(a["class"]?" "+a["class"]:"")}),c.append("line").style("opacity",0),c.append("text").attr("text-anchor",e.gridTextAnchor).attr("transform",g.axis_rotated?"rotate(-90)":"").attr("dx",e.gridTextDx).attr("dy",-5).style("opacity",0),d=e.yv.bind(e),e.ygridLines.select("line").transition().duration(a).attr("x1",g.axis_rotated?d:0).attr("x2",g.axis_rotated?d:e.width).attr("y1",g.axis_rotated?0:d).attr("y2",g.axis_rotated?e.height:d).style("opacity",1),e.ygridLines.select("text").transition().duration(a).attr("x",g.axis_rotated?e.xGridTextX.bind(e):e.yGridTextX.bind(e)).attr("y",d).text(function(a){return a.text}).style("opacity",1),e.ygridLines.exit().transition().duration(a).style("opacity",0).remove()},i.redrawGrid=function(a){var b=this,c=b.config,d=b.xv.bind(b),e=b.xgridLines.select("line"),f=b.xgridLines.select("text");return[(a?e.transition():e).attr("x1",c.axis_rotated?0:d).attr("x2",c.axis_rotated?b.width:d).attr("y1",c.axis_rotated?d:0).attr("y2",c.axis_rotated?d:b.height).style("opacity",1),(a?f.transition():f).attr("x",c.axis_rotated?b.yGridTextX.bind(b):b.xGridTextX.bind(b)).attr("y",d).text(function(a){return a.text}).style("opacity",1)]},i.showXGridFocus=function(a){var b=this,c=b.config,d=a.filter(function(a){return a&&m(a.value)}),e=b.main.selectAll("line."+l.xgridFocus),f=b.xx.bind(b);c.tooltip_show&&(b.hasType("scatter")||b.hasArcType()||(e.style("visibility","visible").data([d[0]]).attr(c.axis_rotated?"y1":"x1",f).attr(c.axis_rotated?"y2":"x2",f),b.smoothLines(e,"grid")))},i.hideXGridFocus=function(){this.main.select("line."+l.xgridFocus).style("visibility","hidden")},i.updateXgridFocus=function(){var a=this,b=a.config;a.main.select("line."+l.xgridFocus).attr("x1",b.axis_rotated?0:-10).attr("x2",b.axis_rotated?a.width:-10).attr("y1",b.axis_rotated?-10:0).attr("y2",b.axis_rotated?-10:a.height)},i.generateGridData=function(a,b){var c,d,e,f,g=this,h=[],i=g.main.select("."+l.axisX).selectAll(".tick").size();if("year"===a)for(c=g.getXDomain(),d=c[0].getFullYear(),e=c[1].getFullYear(),f=d;e>=f;f++)h.push(new Date(f+"-01-01 00:00:00"));else h=b.ticks(10),h.length>i&&(h=h.filter(function(a){return(""+a).indexOf(".")<0}));return h},i.getGridFilterToRemove=function(a){return a?function(b){var c=!1;return[].concat(a).forEach(function(a){("value"in a&&b.value===a.value||"class"in a&&b["class"]===a["class"])&&(c=!0)}),c}:function(){return!0}},i.removeGridLines=function(a,b){var c=this,d=c.config,e=c.getGridFilterToRemove(a),f=function(a){return!e(a)},g=b?l.xgridLines:l.ygridLines,h=b?l.xgridLine:l.ygridLine;c.main.select("."+g).selectAll("."+h).filter(e).transition().duration(d.transition_duration).style("opacity",0).remove(),b?d.grid_x_lines=d.grid_x_lines.filter(f):d.grid_y_lines=d.grid_y_lines.filter(f)},i.initTooltip=function(){var a,b=this,c=b.config;if(b.tooltip=b.selectChart.style("position","relative").append("div").attr("class",l.tooltipContainer).style("position","absolute").style("pointer-events","none").style("display","none"),c.tooltip_init_show){if(b.isTimeSeries()&&o(c.tooltip_init_x)){for(c.tooltip_init_x=b.parseDate(c.tooltip_init_x),a=0;a<b.data.targets[0].values.length&&b.data.targets[0].values[a].x-c.tooltip_init_x!==0;a++);c.tooltip_init_x=a}b.tooltip.html(c.tooltip_contents.call(b,b.data.targets.map(function(a){return b.addName(a.values[c.tooltip_init_x])}),b.axis.getXAxisTickFormat(),b.getYFormat(b.hasArcType()),b.color)),b.tooltip.style("top",c.tooltip_init_position.top).style("left",c.tooltip_init_position.left).style("display","block")}},i.getTooltipContent=function(a,b,c,d){var e,f,g,h,i,j,k=this,l=k.config,m=l.tooltip_format_title||b,n=l.tooltip_format_name||function(a){return a},o=l.tooltip_format_value||c,p=k.isOrderAsc();if(0===l.data_groups.length)a.sort(function(a,b){return p?a.value-b.value:b.value-a.value});else{var q=k.orderTargets(k.data.targets).map(function(a){return a.id});a.sort(function(a,b){return a.value>0&&b.value>0?p?q.indexOf(a.id)-q.indexOf(b.id):q.indexOf(b.id)-q.indexOf(a.id):p?a.value-b.value:b.value-a.value})}for(f=0;f<a.length;f++)if(a[f]&&(a[f].value||0===a[f].value)&&(e||(g=m?m(a[f].x):a[f].x,e="<table class='"+k.CLASS.tooltip+"'>"+(g||0===g?"<tr><th colspan='2'>"+g+"</th></tr>":"")),h=o(a[f].value,a[f].ratio,a[f].id,a[f].index),void 0!==h)){if(null===a[f].name)continue;i=n(a[f].name,a[f].ratio,a[f].id,a[f].index),j=k.levelColor?k.levelColor(a[f].value):d(a[f].id),e+="<tr class='"+k.CLASS.tooltipName+"-"+k.getTargetSelectorSuffix(a[f].id)+"'>",e+="<td class='name'><span style='background-color:"+j+"'></span>"+i+"</td>",e+="<td class='value'>"+h+"</td>",e+="</tr>"}return e+"</table>"},i.tooltipPosition=function(a,b,c,d){var e,f,g,h,i,j=this,k=j.config,l=j.d3,m=j.hasArcType(),n=l.mouse(d);return m?(f=(j.width-(j.isLegendRight?j.getLegendWidth():0))/2+n[0],h=j.height/2+n[1]+20):(e=j.getSvgLeft(!0),k.axis_rotated?(f=e+n[0]+100,g=f+b,i=j.currentWidth-j.getCurrentPaddingRight(),h=j.x(a[0].x)+20):(f=e+j.getCurrentPaddingLeft(!0)+j.x(a[0].x)+20,g=f+b,i=e+j.currentWidth-j.getCurrentPaddingRight(),h=n[1]+15),g>i&&(f-=g-i+20),h+c>j.currentHeight&&(h-=c+30)),0>h&&(h=0),{top:h,left:f}},i.showTooltip=function(a,b){var c,d,e,f=this,g=f.config,h=f.hasArcType(),j=a.filter(function(a){return a&&m(a.value)}),k=g.tooltip_position||i.tooltipPosition;0!==j.length&&g.tooltip_show&&(f.tooltip.html(g.tooltip_contents.call(f,a,f.axis.getXAxisTickFormat(),f.getYFormat(h),f.color)).style("display","block"),c=f.tooltip.property("offsetWidth"),d=f.tooltip.property("offsetHeight"),e=k.call(this,j,c,d,b),f.tooltip.style("top",e.top+"px").style("left",e.left+"px"))},i.hideTooltip=function(){this.tooltip.style("display","none")},i.initLegend=function(){var a=this;return a.legendItemTextBox={},a.legendHasRendered=!1,a.legend=a.svg.append("g").attr("transform",a.getTranslate("legend")),a.config.legend_show?void a.updateLegendWithDefaults():(a.legend.style("visibility","hidden"),void(a.hiddenLegendIds=a.mapToIds(a.data.targets)))},i.updateLegendWithDefaults=function(){var a=this;a.updateLegend(a.mapToIds(a.data.targets),{withTransform:!1,withTransitionForTransform:!1,withTransition:!1})},i.updateSizeForLegend=function(a,b){var c=this,d=c.config,e={top:c.isLegendTop?c.getCurrentPaddingTop()+d.legend_inset_y+5.5:c.currentHeight-a-c.getCurrentPaddingBottom()-d.legend_inset_y,left:c.isLegendLeft?c.getCurrentPaddingLeft()+d.legend_inset_x+.5:c.currentWidth-b-c.getCurrentPaddingRight()-d.legend_inset_x+.5};c.margin3={top:c.isLegendRight?0:c.isLegendInset?e.top:c.currentHeight-a,right:NaN,bottom:0,left:c.isLegendRight?c.currentWidth-b:c.isLegendInset?e.left:0}},i.transformLegend=function(a){var b=this;(a?b.legend.transition():b.legend).attr("transform",b.getTranslate("legend"))},i.updateLegendStep=function(a){this.legendStep=a},i.updateLegendItemWidth=function(a){this.legendItemWidth=a},i.updateLegendItemHeight=function(a){this.legendItemHeight=a},i.getLegendWidth=function(){var a=this;return a.config.legend_show?a.isLegendRight||a.isLegendInset?a.legendItemWidth*(a.legendStep+1):a.currentWidth:0},i.getLegendHeight=function(){var a=this,b=0;return a.config.legend_show&&(b=a.isLegendRight?a.currentHeight:Math.max(20,a.legendItemHeight)*(a.legendStep+1)),b},i.opacityForLegend=function(a){return a.classed(l.legendItemHidden)?null:1},i.opacityForUnfocusedLegend=function(a){return a.classed(l.legendItemHidden)?null:.3},i.toggleFocusLegend=function(a,b){var c=this;a=c.mapToTargetIds(a),c.legend.selectAll("."+l.legendItem).filter(function(b){return a.indexOf(b)>=0}).classed(l.legendItemFocused,b).transition().duration(100).style("opacity",function(){var a=b?c.opacityForLegend:c.opacityForUnfocusedLegend;return a.call(c,c.d3.select(this))})},i.revertLegend=function(){var a=this,b=a.d3;a.legend.selectAll("."+l.legendItem).classed(l.legendItemFocused,!1).transition().duration(100).style("opacity",function(){return a.opacityForLegend(b.select(this))})},i.showLegend=function(a){var b=this,c=b.config;c.legend_show||(c.legend_show=!0,b.legend.style("visibility","visible"),b.legendHasRendered||b.updateLegendWithDefaults()),b.removeHiddenLegendIds(a),b.legend.selectAll(b.selectorLegends(a)).style("visibility","visible").transition().style("opacity",function(){return b.opacityForLegend(b.d3.select(this))})},i.hideLegend=function(a){var b=this,c=b.config;c.legend_show&&u(a)&&(c.legend_show=!1,b.legend.style("visibility","hidden")),b.addHiddenLegendIds(a),b.legend.selectAll(b.selectorLegends(a)).style("opacity",0).style("visibility","hidden")},i.clearLegendItemTextBoxCache=function(){this.legendItemTextBox={}},i.updateLegend=function(a,b,c){function d(a,b){return y.legendItemTextBox[b]||(y.legendItemTextBox[b]=y.getTextRect(a.textContent,l.legendItem,a)),y.legendItemTextBox[b]}function e(b,c,e){function f(a,b){b||(g=(o-G-n)/2,E>g&&(g=(o-n)/2,G=0,M++)),L[a]=M,K[M]=y.isLegendInset?10:g,H[a]=G,G+=n}var g,h,i=0===e,j=e===a.length-1,k=d(b,c),l=k.width+F+(!j||y.isLegendRight||y.isLegendInset?B:0)+z.legend_padding,m=k.height+A,n=y.isLegendRight||y.isLegendInset?m:l,o=y.isLegendRight||y.isLegendInset?y.getLegendHeight():y.getLegendWidth();return i&&(G=0,M=0,C=0,D=0),z.legend_show&&!y.isLegendToShow(c)?void(I[c]=J[c]=L[c]=H[c]=0):(I[c]=l,J[c]=m,(!C||l>=C)&&(C=l),(!D||m>=D)&&(D=m),h=y.isLegendRight||y.isLegendInset?D:C,void(z.legend_equally?(Object.keys(I).forEach(function(a){I[a]=C}),Object.keys(J).forEach(function(a){J[a]=D}),g=(o-h*a.length)/2,E>g?(G=0,M=0,a.forEach(function(a){f(a)})):f(c,!0)):f(c)))}var f,g,h,i,j,k,m,n,o,p,r,s,t,u,v,x,y=this,z=y.config,A=4,B=10,C=0,D=0,E=10,F=z.legend_item_tile_width+5,G=0,H={},I={},J={},K=[0],L={},M=0;a=a.filter(function(a){return!q(z.data_names[a])||null!==z.data_names[a]}),b=b||{},r=w(b,"withTransition",!0),s=w(b,"withTransitionForTransform",!0),y.isLegendInset&&(M=z.legend_inset_step?z.legend_inset_step:a.length,y.updateLegendStep(M)),y.isLegendRight?(f=function(a){return C*L[a]},i=function(a){return K[L[a]]+H[a]}):y.isLegendInset?(f=function(a){return C*L[a]+10},i=function(a){return K[L[a]]+H[a]}):(f=function(a){return K[L[a]]+H[a]},i=function(a){return D*L[a]}),g=function(a,b){return f(a,b)+4+z.legend_item_tile_width},j=function(a,b){return i(a,b)+9},h=function(a,b){return f(a,b)},k=function(a,b){return i(a,b)-5},m=function(a,b){return f(a,b)-2},n=function(a,b){return f(a,b)-2+z.legend_item_tile_width},o=function(a,b){return i(a,b)+4},p=y.legend.selectAll("."+l.legendItem).data(a).enter().append("g").attr("class",function(a){return y.generateClass(l.legendItem,a)}).style("visibility",function(a){return y.isLegendToShow(a)?"visible":"hidden"}).style("cursor","pointer").on("click",function(a){z.legend_item_onclick?z.legend_item_onclick.call(y,a):y.d3.event.altKey?(y.api.hide(),y.api.show(a)):(y.api.toggle(a),y.isTargetToShow(a)?y.api.focus(a):y.api.revert())}).on("mouseover",function(a){z.legend_item_onmouseover?z.legend_item_onmouseover.call(y,a):(y.d3.select(this).classed(l.legendItemFocused,!0),!y.transiting&&y.isTargetToShow(a)&&y.api.focus(a))}).on("mouseout",function(a){z.legend_item_onmouseout?z.legend_item_onmouseout.call(y,a):(y.d3.select(this).classed(l.legendItemFocused,!1),y.api.revert())}),p.append("text").text(function(a){return q(z.data_names[a])?z.data_names[a]:a}).each(function(a,b){e(this,a,b)}).style("pointer-events","none").attr("x",y.isLegendRight||y.isLegendInset?g:-200).attr("y",y.isLegendRight||y.isLegendInset?-200:j),p.append("rect").attr("class",l.legendItemEvent).style("fill-opacity",0).attr("x",y.isLegendRight||y.isLegendInset?h:-200).attr("y",y.isLegendRight||y.isLegendInset?-200:k),p.append("line").attr("class",l.legendItemTile).style("stroke",y.color).style("pointer-events","none").attr("x1",y.isLegendRight||y.isLegendInset?m:-200).attr("y1",y.isLegendRight||y.isLegendInset?-200:o).attr("x2",y.isLegendRight||y.isLegendInset?n:-200).attr("y2",y.isLegendRight||y.isLegendInset?-200:o).attr("stroke-width",z.legend_item_tile_height),x=y.legend.select("."+l.legendBackground+" rect"),y.isLegendInset&&C>0&&0===x.size()&&(x=y.legend.insert("g","."+l.legendItem).attr("class",l.legendBackground).append("rect")),t=y.legend.selectAll("text").data(a).text(function(a){return q(z.data_names[a])?z.data_names[a]:a}).each(function(a,b){e(this,a,b)}),(r?t.transition():t).attr("x",g).attr("y",j),u=y.legend.selectAll("rect."+l.legendItemEvent).data(a),(r?u.transition():u).attr("width",function(a){return I[a]}).attr("height",function(a){return J[a]}).attr("x",h).attr("y",k),v=y.legend.selectAll("line."+l.legendItemTile).data(a),(r?v.transition():v).style("stroke",y.color).attr("x1",m).attr("y1",o).attr("x2",n).attr("y2",o),x&&(r?x.transition():x).attr("height",y.getLegendHeight()-12).attr("width",C*(M+1)+10),y.legend.selectAll("."+l.legendItem).classed(l.legendItemHidden,function(a){return!y.isTargetToShow(a)}),y.updateLegendItemWidth(C),y.updateLegendItemHeight(D),y.updateLegendStep(M),y.updateSizes(),y.updateScales(),y.updateSvgSize(),y.transformAll(s,c),y.legendHasRendered=!0},i.initTitle=function(){var a=this;a.title=a.svg.append("text").text(a.config.title_text).attr("class",a.CLASS.title)},i.redrawTitle=function(){var a=this;a.title.attr("x",a.xForTitle.bind(a)).attr("y",a.yForTitle.bind(a))},i.xForTitle=function(){var a,b=this,c=b.config,d=c.title_position||"left";return a=d.indexOf("right")>=0?b.currentWidth-b.getTextRect(b.title.node().textContent,b.CLASS.title,b.title.node()).width-c.title_padding.right:d.indexOf("center")>=0?(b.currentWidth-b.getTextRect(b.title.node().textContent,b.CLASS.title,b.title.node()).width)/2:c.title_padding.left},i.yForTitle=function(){var a=this;return a.config.title_padding.top+a.getTextRect(a.title.node().textContent,a.CLASS.title,a.title.node()).height},i.getTitlePadding=function(){var a=this;return a.yForTitle()+a.config.title_padding.bottom},c(b,f),f.prototype.init=function(){var a=this.owner,b=a.config,c=a.main;a.axes.x=c.append("g").attr("class",l.axis+" "+l.axisX).attr("clip-path",a.clipPathForXAxis).attr("transform",a.getTranslate("x")).style("visibility",b.axis_x_show?"visible":"hidden"),a.axes.x.append("text").attr("class",l.axisXLabel).attr("transform",b.axis_rotated?"rotate(-90)":"").style("text-anchor",this.textAnchorForXAxisLabel.bind(this)),a.axes.y=c.append("g").attr("class",l.axis+" "+l.axisY).attr("clip-path",b.axis_y_inner?"":a.clipPathForYAxis).attr("transform",a.getTranslate("y")).style("visibility",b.axis_y_show?"visible":"hidden"),a.axes.y.append("text").attr("class",l.axisYLabel).attr("transform",b.axis_rotated?"":"rotate(-90)").style("text-anchor",this.textAnchorForYAxisLabel.bind(this)),a.axes.y2=c.append("g").attr("class",l.axis+" "+l.axisY2).attr("transform",a.getTranslate("y2")).style("visibility",b.axis_y2_show?"visible":"hidden"),a.axes.y2.append("text").attr("class",l.axisY2Label).attr("transform",b.axis_rotated?"":"rotate(-90)").style("text-anchor",this.textAnchorForY2AxisLabel.bind(this))},f.prototype.getXAxis=function(a,b,c,d,e,f,h){var i=this.owner,j=i.config,k={isCategory:i.isCategorized(),withOuterTick:e,tickMultiline:j.axis_x_tick_multiline,tickWidth:j.axis_x_tick_width,tickTextRotate:h?0:j.axis_x_tick_rotate,withoutTransition:f},l=g(i.d3,k).scale(a).orient(b);return i.isTimeSeries()&&d&&"function"!=typeof d&&(d=d.map(function(a){return i.parseDate(a)})),l.tickFormat(c).tickValues(d),i.isCategorized()&&(l.tickCentered(j.axis_x_tick_centered),u(j.axis_x_tick_culling)&&(j.axis_x_tick_culling=!1)),l},f.prototype.updateXAxisTickValues=function(a,b){var c,d=this.owner,e=d.config;return(e.axis_x_tick_fit||e.axis_x_tick_count)&&(c=this.generateTickValues(d.mapTargetsToUniqueXs(a),e.axis_x_tick_count,d.isTimeSeries())),b?b.tickValues(c):(d.xAxis.tickValues(c),d.subXAxis.tickValues(c)),c},f.prototype.getYAxis=function(a,b,c,d,e,f){var h={withOuterTick:e,withoutTransition:f},i=this.owner,j=i.d3,k=i.config,l=g(j,h).scale(a).orient(b).tickFormat(c);return i.isTimeSeriesY()?l.ticks(j.time[k.axis_y_tick_time_value],k.axis_y_tick_time_interval):l.tickValues(d),l},f.prototype.getId=function(a){var b=this.owner.config;return a in b.data_axes?b.data_axes[a]:"y"},f.prototype.getXAxisTickFormat=function(){var a=this.owner,b=a.config,c=a.isTimeSeries()?a.defaultAxisTimeFormat:a.isCategorized()?a.categoryName:function(a){return 0>a?a.toFixed(0):a};return b.axis_x_tick_format&&(n(b.axis_x_tick_format)?c=b.axis_x_tick_format:a.isTimeSeries()&&(c=function(c){return c?a.axisTimeFormat(b.axis_x_tick_format)(c):""})),n(c)?function(b){return c.call(a,b)}:c},f.prototype.getTickValues=function(a,b){return a?a:b?b.tickValues():void 0},f.prototype.getXAxisTickValues=function(){return this.getTickValues(this.owner.config.axis_x_tick_values,this.owner.xAxis)},f.prototype.getYAxisTickValues=function(){return this.getTickValues(this.owner.config.axis_y_tick_values,this.owner.yAxis)},f.prototype.getY2AxisTickValues=function(){return this.getTickValues(this.owner.config.axis_y2_tick_values,this.owner.y2Axis)},f.prototype.getLabelOptionByAxisId=function(a){var b,c=this.owner,d=c.config;return"y"===a?b=d.axis_y_label:"y2"===a?b=d.axis_y2_label:"x"===a&&(b=d.axis_x_label),b},f.prototype.getLabelText=function(a){var b=this.getLabelOptionByAxisId(a);return o(b)?b:b?b.text:null},f.prototype.setLabelText=function(a,b){var c=this.owner,d=c.config,e=this.getLabelOptionByAxisId(a);o(e)?"y"===a?d.axis_y_label=b:"y2"===a?d.axis_y2_label=b:"x"===a&&(d.axis_x_label=b):e&&(e.text=b)},f.prototype.getLabelPosition=function(a,b){var c=this.getLabelOptionByAxisId(a),d=c&&"object"==typeof c&&c.position?c.position:b;return{isInner:d.indexOf("inner")>=0,isOuter:d.indexOf("outer")>=0,isLeft:d.indexOf("left")>=0,isCenter:d.indexOf("center")>=0,isRight:d.indexOf("right")>=0,isTop:d.indexOf("top")>=0,isMiddle:d.indexOf("middle")>=0,isBottom:d.indexOf("bottom")>=0}},f.prototype.getXAxisLabelPosition=function(){return this.getLabelPosition("x",this.owner.config.axis_rotated?"inner-top":"inner-right")},f.prototype.getYAxisLabelPosition=function(){return this.getLabelPosition("y",this.owner.config.axis_rotated?"inner-right":"inner-top")},f.prototype.getY2AxisLabelPosition=function(){return this.getLabelPosition("y2",this.owner.config.axis_rotated?"inner-right":"inner-top")},f.prototype.getLabelPositionById=function(a){return"y2"===a?this.getY2AxisLabelPosition():"y"===a?this.getYAxisLabelPosition():this.getXAxisLabelPosition()},f.prototype.textForXAxisLabel=function(){return this.getLabelText("x")},f.prototype.textForYAxisLabel=function(){return this.getLabelText("y")},f.prototype.textForY2AxisLabel=function(){return this.getLabelText("y2")},f.prototype.xForAxisLabel=function(a,b){var c=this.owner;return a?b.isLeft?0:b.isCenter?c.width/2:c.width:b.isBottom?-c.height:b.isMiddle?-c.height/2:0},f.prototype.dxForAxisLabel=function(a,b){return a?b.isLeft?"0.5em":b.isRight?"-0.5em":"0":b.isTop?"-0.5em":b.isBottom?"0.5em":"0"},f.prototype.textAnchorForAxisLabel=function(a,b){return a?b.isLeft?"start":b.isCenter?"middle":"end":b.isBottom?"start":b.isMiddle?"middle":"end"},f.prototype.xForXAxisLabel=function(){return this.xForAxisLabel(!this.owner.config.axis_rotated,this.getXAxisLabelPosition())},f.prototype.xForYAxisLabel=function(){return this.xForAxisLabel(this.owner.config.axis_rotated,this.getYAxisLabelPosition())},f.prototype.xForY2AxisLabel=function(){return this.xForAxisLabel(this.owner.config.axis_rotated,this.getY2AxisLabelPosition())},f.prototype.dxForXAxisLabel=function(){return this.dxForAxisLabel(!this.owner.config.axis_rotated,this.getXAxisLabelPosition())},f.prototype.dxForYAxisLabel=function(){return this.dxForAxisLabel(this.owner.config.axis_rotated,this.getYAxisLabelPosition())},f.prototype.dxForY2AxisLabel=function(){return this.dxForAxisLabel(this.owner.config.axis_rotated,this.getY2AxisLabelPosition())},f.prototype.dyForXAxisLabel=function(){var a=this.owner,b=a.config,c=this.getXAxisLabelPosition();return b.axis_rotated?c.isInner?"1.2em":-25-this.getMaxTickWidth("x"):c.isInner?"-0.5em":b.axis_x_height?b.axis_x_height-10:"3em"},f.prototype.dyForYAxisLabel=function(){var a=this.owner,b=this.getYAxisLabelPosition();return a.config.axis_rotated?b.isInner?"-0.5em":"3em":b.isInner?"1.2em":-10-(a.config.axis_y_inner?0:this.getMaxTickWidth("y")+10)},f.prototype.dyForY2AxisLabel=function(){var a=this.owner,b=this.getY2AxisLabelPosition();return a.config.axis_rotated?b.isInner?"1.2em":"-2.2em":b.isInner?"-0.5em":15+(a.config.axis_y2_inner?0:this.getMaxTickWidth("y2")+15)},f.prototype.textAnchorForXAxisLabel=function(){var a=this.owner;return this.textAnchorForAxisLabel(!a.config.axis_rotated,this.getXAxisLabelPosition())},f.prototype.textAnchorForYAxisLabel=function(){var a=this.owner;return this.textAnchorForAxisLabel(a.config.axis_rotated,this.getYAxisLabelPosition())},f.prototype.textAnchorForY2AxisLabel=function(){var a=this.owner;return this.textAnchorForAxisLabel(a.config.axis_rotated,this.getY2AxisLabelPosition())},f.prototype.getMaxTickWidth=function(a,b){var c,d,e,f,g,h=this.owner,i=h.config,j=0;return b&&h.currentMaxTickWidths[a]?h.currentMaxTickWidths[a]:(h.svg&&(c=h.filterTargetsToShow(h.data.targets),"y"===a?(d=h.y.copy().domain(h.getYDomain(c,"y")),e=this.getYAxis(d,h.yOrient,i.axis_y_tick_format,h.yAxisTickValues,!1,!0)):"y2"===a?(d=h.y2.copy().domain(h.getYDomain(c,"y2")),e=this.getYAxis(d,h.y2Orient,i.axis_y2_tick_format,h.y2AxisTickValues,!1,!0)):(d=h.x.copy().domain(h.getXDomain(c)),e=this.getXAxis(d,h.xOrient,h.xAxisTickFormat,h.xAxisTickValues,!1,!0,!0),this.updateXAxisTickValues(c,e)),f=h.d3.select("body").append("div").classed("c3",!0),g=f.append("svg").style("visibility","hidden").style("position","fixed").style("top",0).style("left",0),g.append("g").call(e).each(function(){h.d3.select(this).selectAll("text").each(function(){var a=this.getBoundingClientRect();j<a.width&&(j=a.width)}),f.remove()})),h.currentMaxTickWidths[a]=0>=j?h.currentMaxTickWidths[a]:j,h.currentMaxTickWidths[a])},f.prototype.updateLabels=function(a){var b=this.owner,c=b.main.select("."+l.axisX+" ."+l.axisXLabel),d=b.main.select("."+l.axisY+" ."+l.axisYLabel),e=b.main.select("."+l.axisY2+" ."+l.axisY2Label);(a?c.transition():c).attr("x",this.xForXAxisLabel.bind(this)).attr("dx",this.dxForXAxisLabel.bind(this)).attr("dy",this.dyForXAxisLabel.bind(this)).text(this.textForXAxisLabel.bind(this)),
4
+(a?d.transition():d).attr("x",this.xForYAxisLabel.bind(this)).attr("dx",this.dxForYAxisLabel.bind(this)).attr("dy",this.dyForYAxisLabel.bind(this)).text(this.textForYAxisLabel.bind(this)),(a?e.transition():e).attr("x",this.xForY2AxisLabel.bind(this)).attr("dx",this.dxForY2AxisLabel.bind(this)).attr("dy",this.dyForY2AxisLabel.bind(this)).text(this.textForY2AxisLabel.bind(this))},f.prototype.getPadding=function(a,b,c,d){var e="number"==typeof a?a:a[b];return m(e)?"ratio"===a.unit?a[b]*d:this.convertPixelsToAxisPadding(e,d):c},f.prototype.convertPixelsToAxisPadding=function(a,b){var c=this.owner,d=c.config.axis_rotated?c.width:c.height;return b*(a/d)},f.prototype.generateTickValues=function(a,b,c){var d,e,f,g,h,i,j,k=a;if(b)if(d=n(b)?b():b,1===d)k=[a[0]];else if(2===d)k=[a[0],a[a.length-1]];else if(d>2){for(g=d-2,e=a[0],f=a[a.length-1],h=(f-e)/(g+1),k=[e],i=0;g>i;i++)j=+e+h*(i+1),k.push(c?new Date(j):j);k.push(f)}return c||(k=k.sort(function(a,b){return a-b})),k},f.prototype.generateTransitions=function(a){var b=this.owner,c=b.axes;return{axisX:a?c.x.transition().duration(a):c.x,axisY:a?c.y.transition().duration(a):c.y,axisY2:a?c.y2.transition().duration(a):c.y2,axisSubX:a?c.subx.transition().duration(a):c.subx}},f.prototype.redraw=function(a,b){var c=this.owner;c.axes.x.style("opacity",b?0:1),c.axes.y.style("opacity",b?0:1),c.axes.y2.style("opacity",b?0:1),c.axes.subx.style("opacity",b?0:1),a.axisX.call(c.xAxis),a.axisY.call(c.yAxis),a.axisY2.call(c.y2Axis),a.axisSubX.call(c.subXAxis)},i.getClipPath=function(b){var c=a.navigator.appVersion.toLowerCase().indexOf("msie 9.")>=0;return"url("+(c?"":document.URL.split("#")[0])+"#"+b+")"},i.appendClip=function(a,b){return a.append("clipPath").attr("id",b).append("rect")},i.getAxisClipX=function(a){var b=Math.max(30,this.margin.left);return a?-(1+b):-(b-1)},i.getAxisClipY=function(a){return a?-20:-this.margin.top},i.getXAxisClipX=function(){var a=this;return a.getAxisClipX(!a.config.axis_rotated)},i.getXAxisClipY=function(){var a=this;return a.getAxisClipY(!a.config.axis_rotated)},i.getYAxisClipX=function(){var a=this;return a.config.axis_y_inner?-1:a.getAxisClipX(a.config.axis_rotated)},i.getYAxisClipY=function(){var a=this;return a.getAxisClipY(a.config.axis_rotated)},i.getAxisClipWidth=function(a){var b=this,c=Math.max(30,b.margin.left),d=Math.max(30,b.margin.right);return a?b.width+2+c+d:b.margin.left+20},i.getAxisClipHeight=function(a){return(a?this.margin.bottom:this.margin.top+this.height)+20},i.getXAxisClipWidth=function(){var a=this;return a.getAxisClipWidth(!a.config.axis_rotated)},i.getXAxisClipHeight=function(){var a=this;return a.getAxisClipHeight(!a.config.axis_rotated)},i.getYAxisClipWidth=function(){var a=this;return a.getAxisClipWidth(a.config.axis_rotated)+(a.config.axis_y_inner?20:0)},i.getYAxisClipHeight=function(){var a=this;return a.getAxisClipHeight(a.config.axis_rotated)},i.initPie=function(){var a=this,b=a.d3,c=a.config;a.pie=b.layout.pie().value(function(a){return a.values.reduce(function(a,b){return a+b.value},0)}),c.data_order||a.pie.sort(null)},i.updateRadius=function(){var a=this,b=a.config,c=b.gauge_width||b.donut_width;a.radiusExpanded=Math.min(a.arcWidth,a.arcHeight)/2,a.radius=.95*a.radiusExpanded,a.innerRadiusRatio=c?(a.radius-c)/a.radius:.6,a.innerRadius=a.hasType("donut")||a.hasType("gauge")?a.radius*a.innerRadiusRatio:0},i.updateArc=function(){var a=this;a.svgArc=a.getSvgArc(),a.svgArcExpanded=a.getSvgArcExpanded(),a.svgArcExpandedSub=a.getSvgArcExpanded(.98)},i.updateAngle=function(a){var b,c,d,e,f=this,g=f.config,h=!1,i=0;return g?(f.pie(f.filterTargetsToShow(f.data.targets)).forEach(function(b){h||b.data.id!==a.data.id||(h=!0,a=b,a.index=i),i++}),isNaN(a.startAngle)&&(a.startAngle=0),isNaN(a.endAngle)&&(a.endAngle=a.startAngle),f.isGaugeType(a.data)&&(b=g.gauge_min,c=g.gauge_max,d=Math.PI/(c-b),e=a.value<b?0:a.value<c?a.value-b:c-b,a.startAngle=-1*(Math.PI/2),a.endAngle=a.startAngle+d*e),h?a:null):null},i.getSvgArc=function(){var a=this,b=a.d3.svg.arc().outerRadius(a.radius).innerRadius(a.innerRadius),c=function(c,d){var e;return d?b(c):(e=a.updateAngle(c),e?b(e):"M 0 0")};return c.centroid=b.centroid,c},i.getSvgArcExpanded=function(a){var b=this,c=b.d3.svg.arc().outerRadius(b.radiusExpanded*(a?a:1)).innerRadius(b.innerRadius);return function(a){var d=b.updateAngle(a);return d?c(d):"M 0 0"}},i.getArc=function(a,b,c){return c||this.isArcType(a.data)?this.svgArc(a,b):"M 0 0"},i.transformForArcLabel=function(a){var b,c,d,e,f,g=this,h=g.updateAngle(a),i="";return h&&!g.hasType("gauge")&&(b=this.svgArc.centroid(h),c=isNaN(b[0])?0:b[0],d=isNaN(b[1])?0:b[1],e=Math.sqrt(c*c+d*d),f=g.radius&&e?(36/g.radius>.375?1.175-36/g.radius:.8)*g.radius/e:0,i="translate("+c*f+","+d*f+")"),i},i.getArcRatio=function(a){var b=this,c=b.hasType("gauge")?Math.PI:2*Math.PI;return a?(a.endAngle-a.startAngle)/c:null},i.convertToArcData=function(a){return this.addName({id:a.data.id,value:a.value,ratio:this.getArcRatio(a),index:a.index})},i.textForArcLabel=function(a){var b,c,d,e,f,g=this;return g.shouldShowArcLabel()?(b=g.updateAngle(a),c=b?b.value:null,d=g.getArcRatio(b),e=a.data.id,g.hasType("gauge")||g.meetsArcLabelThreshold(d)?(f=g.getArcLabelFormat(),f?f(c,d,e):g.defaultArcValueFormat(c,d)):""):""},i.expandArc=function(b){var c,d=this;return d.transiting?void(c=a.setInterval(function(){d.transiting||(a.clearInterval(c),d.legend.selectAll(".c3-legend-item-focused").size()>0&&d.expandArc(b))},10)):(b=d.mapToTargetIds(b),void d.svg.selectAll(d.selectorTargets(b,"."+l.chartArc)).each(function(a){d.shouldExpand(a.data.id)&&d.d3.select(this).selectAll("path").transition().duration(d.expandDuration(a.data.id)).attr("d",d.svgArcExpanded).transition().duration(2*d.expandDuration(a.data.id)).attr("d",d.svgArcExpandedSub).each(function(a){d.isDonutType(a.data)})}))},i.unexpandArc=function(a){var b=this;b.transiting||(a=b.mapToTargetIds(a),b.svg.selectAll(b.selectorTargets(a,"."+l.chartArc)).selectAll("path").transition().duration(function(a){return b.expandDuration(a.data.id)}).attr("d",b.svgArc),b.svg.selectAll("."+l.arc).style("opacity",1))},i.expandDuration=function(a){var b=this,c=b.config;return b.isDonutType(a)?c.donut_expand_duration:b.isGaugeType(a)?c.gauge_expand_duration:b.isPieType(a)?c.pie_expand_duration:50},i.shouldExpand=function(a){var b=this,c=b.config;return b.isDonutType(a)&&c.donut_expand||b.isGaugeType(a)&&c.gauge_expand||b.isPieType(a)&&c.pie_expand},i.shouldShowArcLabel=function(){var a=this,b=a.config,c=!0;return a.hasType("donut")?c=b.donut_label_show:a.hasType("pie")&&(c=b.pie_label_show),c},i.meetsArcLabelThreshold=function(a){var b=this,c=b.config,d=b.hasType("donut")?c.donut_label_threshold:c.pie_label_threshold;return a>=d},i.getArcLabelFormat=function(){var a=this,b=a.config,c=b.pie_label_format;return a.hasType("gauge")?c=b.gauge_label_format:a.hasType("donut")&&(c=b.donut_label_format),c},i.getArcTitle=function(){var a=this;return a.hasType("donut")?a.config.donut_title:""},i.updateTargetsForArc=function(a){var b,c,d=this,e=d.main,f=d.classChartArc.bind(d),g=d.classArcs.bind(d),h=d.classFocus.bind(d);b=e.select("."+l.chartArcs).selectAll("."+l.chartArc).data(d.pie(a)).attr("class",function(a){return f(a)+h(a.data)}),c=b.enter().append("g").attr("class",f),c.append("g").attr("class",g),c.append("text").attr("dy",d.hasType("gauge")?"-.1em":".35em").style("opacity",0).style("text-anchor","middle").style("pointer-events","none")},i.initArc=function(){var a=this;a.arcs=a.main.select("."+l.chart).append("g").attr("class",l.chartArcs).attr("transform",a.getTranslate("arc")),a.arcs.append("text").attr("class",l.chartArcsTitle).style("text-anchor","middle").text(a.getArcTitle())},i.redrawArc=function(a,b,c){var d,e=this,f=e.d3,g=e.config,h=e.main;d=h.selectAll("."+l.arcs).selectAll("."+l.arc).data(e.arcData.bind(e)),d.enter().append("path").attr("class",e.classArc.bind(e)).style("fill",function(a){return e.color(a.data)}).style("cursor",function(a){return g.interaction_enabled&&g.data_selection_isselectable(a)?"pointer":null}).style("opacity",0).each(function(a){e.isGaugeType(a.data)&&(a.startAngle=a.endAngle=-1*(Math.PI/2)),this._current=a}),d.attr("transform",function(a){return!e.isGaugeType(a.data)&&c?"scale(0)":""}).style("opacity",function(a){return a===this._current?0:1}).on("mouseover",g.interaction_enabled?function(a){var b,c;e.transiting||(b=e.updateAngle(a),b&&(c=e.convertToArcData(b),e.expandArc(b.data.id),e.api.focus(b.data.id),e.toggleFocusLegend(b.data.id,!0),e.config.data_onmouseover(c,this)))}:null).on("mousemove",g.interaction_enabled?function(a){var b,c,d=e.updateAngle(a);d&&(b=e.convertToArcData(d),c=[b],e.showTooltip(c,this))}:null).on("mouseout",g.interaction_enabled?function(a){var b,c;e.transiting||(b=e.updateAngle(a),b&&(c=e.convertToArcData(b),e.unexpandArc(b.data.id),e.api.revert(),e.revertLegend(),e.hideTooltip(),e.config.data_onmouseout(c,this)))}:null).on("click",g.interaction_enabled?function(a,b){var c,d=e.updateAngle(a);d&&(c=e.convertToArcData(d),e.toggleShape&&e.toggleShape(this,c,b),e.config.data_onclick.call(e.api,c,this))}:null).each(function(){e.transiting=!0}).transition().duration(a).attrTween("d",function(a){var b,c=e.updateAngle(a);return c?(isNaN(this._current.startAngle)&&(this._current.startAngle=0),isNaN(this._current.endAngle)&&(this._current.endAngle=this._current.startAngle),b=f.interpolate(this._current,c),this._current=b(0),function(c){var d=b(c);return d.data=a.data,e.getArc(d,!0)}):function(){return"M 0 0"}}).attr("transform",c?"scale(1)":"").style("fill",function(a){return e.levelColor?e.levelColor(a.data.values[0].value):e.color(a.data.id)}).style("opacity",1).call(e.endall,function(){e.transiting=!1}),d.exit().transition().duration(b).style("opacity",0).remove(),h.selectAll("."+l.chartArc).select("text").style("opacity",0).attr("class",function(a){return e.isGaugeType(a.data)?l.gaugeValue:""}).text(e.textForArcLabel.bind(e)).attr("transform",e.transformForArcLabel.bind(e)).style("font-size",function(a){return e.isGaugeType(a.data)?Math.round(e.radius/5)+"px":""}).transition().duration(a).style("opacity",function(a){return e.isTargetToShow(a.data.id)&&e.isArcType(a.data)?1:0}),h.select("."+l.chartArcsTitle).style("opacity",e.hasType("donut")||e.hasType("gauge")?1:0),e.hasType("gauge")&&(e.arcs.select("."+l.chartArcsBackground).attr("d",function(){var a={data:[{value:g.gauge_max}],startAngle:-1*(Math.PI/2),endAngle:Math.PI/2};return e.getArc(a,!0,!0)}),e.arcs.select("."+l.chartArcsGaugeUnit).attr("dy",".75em").text(g.gauge_label_show?g.gauge_units:""),e.arcs.select("."+l.chartArcsGaugeMin).attr("dx",-1*(e.innerRadius+(e.radius-e.innerRadius)/2)+"px").attr("dy","1.2em").text(g.gauge_label_show?g.gauge_min:""),e.arcs.select("."+l.chartArcsGaugeMax).attr("dx",e.innerRadius+(e.radius-e.innerRadius)/2+"px").attr("dy","1.2em").text(g.gauge_label_show?g.gauge_max:""))},i.initGauge=function(){var a=this.arcs;this.hasType("gauge")&&(a.append("path").attr("class",l.chartArcsBackground),a.append("text").attr("class",l.chartArcsGaugeUnit).style("text-anchor","middle").style("pointer-events","none"),a.append("text").attr("class",l.chartArcsGaugeMin).style("text-anchor","middle").style("pointer-events","none"),a.append("text").attr("class",l.chartArcsGaugeMax).style("text-anchor","middle").style("pointer-events","none"))},i.getGaugeLabelHeight=function(){return this.config.gauge_label_show?20:0},i.initRegion=function(){var a=this;a.region=a.main.append("g").attr("clip-path",a.clipPath).attr("class",l.regions)},i.updateRegion=function(a){var b=this,c=b.config;b.region.style("visibility",b.hasArcType()?"hidden":"visible"),b.mainRegion=b.main.select("."+l.regions).selectAll("."+l.region).data(c.regions),b.mainRegion.enter().append("g").attr("class",b.classRegion.bind(b)).append("rect").style("fill-opacity",0),b.mainRegion.exit().transition().duration(a).style("opacity",0).remove()},i.redrawRegion=function(a){var b=this,c=b.mainRegion.selectAll("rect"),d=b.regionX.bind(b),e=b.regionY.bind(b),f=b.regionWidth.bind(b),g=b.regionHeight.bind(b);return[(a?c.transition():c).attr("x",d).attr("y",e).attr("width",f).attr("height",g).style("fill-opacity",function(a){return m(a.opacity)?a.opacity:.1})]},i.regionX=function(a){var b,c=this,d=c.config,e="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated&&"start"in a?e(a.start):0:d.axis_rotated?0:"start"in a?c.x(c.isTimeSeries()?c.parseDate(a.start):a.start):0},i.regionY=function(a){var b,c=this,d=c.config,e="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated?0:"end"in a?e(a.end):0:d.axis_rotated&&"start"in a?c.x(c.isTimeSeries()?c.parseDate(a.start):a.start):0},i.regionWidth=function(a){var b,c=this,d=c.config,e=c.regionX(a),f="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated&&"end"in a?f(a.end):c.width:d.axis_rotated?c.width:"end"in a?c.x(c.isTimeSeries()?c.parseDate(a.end):a.end):c.width,e>b?0:b-e},i.regionHeight=function(a){var b,c=this,d=c.config,e=this.regionY(a),f="y"===a.axis?c.y:c.y2;return b="y"===a.axis||"y2"===a.axis?d.axis_rotated?c.height:"start"in a?f(a.start):c.height:d.axis_rotated&&"end"in a?c.x(c.isTimeSeries()?c.parseDate(a.end):a.end):c.height,e>b?0:b-e},i.isRegionOnX=function(a){return!a.axis||"x"===a.axis},i.drag=function(a){var b,c,d,e,f,g,h,i,j=this,k=j.config,m=j.main,n=j.d3;j.hasArcType()||k.data_selection_enabled&&(!k.zoom_enabled||j.zoom.altDomain)&&k.data_selection_multiple&&(b=j.dragStart[0],c=j.dragStart[1],d=a[0],e=a[1],f=Math.min(b,d),g=Math.max(b,d),h=k.data_selection_grouped?j.margin.top:Math.min(c,e),i=k.data_selection_grouped?j.height:Math.max(c,e),m.select("."+l.dragarea).attr("x",f).attr("y",h).attr("width",g-f).attr("height",i-h),m.selectAll("."+l.shapes).selectAll("."+l.shape).filter(function(a){return k.data_selection_isselectable(a)}).each(function(a,b){var c,d,e,k,m,o,p=n.select(this),q=p.classed(l.SELECTED),r=p.classed(l.INCLUDED),s=!1;if(p.classed(l.circle))c=1*p.attr("cx"),d=1*p.attr("cy"),m=j.togglePoint,s=c>f&&g>c&&d>h&&i>d;else{if(!p.classed(l.bar))return;o=y(this),c=o.x,d=o.y,e=o.width,k=o.height,m=j.togglePath,s=!(c>g||f>c+e||d>i||h>d+k)}s^r&&(p.classed(l.INCLUDED,!r),p.classed(l.SELECTED,!q),m.call(j,!q,p,a,b))}))},i.dragstart=function(a){var b=this,c=b.config;b.hasArcType()||c.data_selection_enabled&&(b.dragStart=a,b.main.select("."+l.chart).append("rect").attr("class",l.dragarea).style("opacity",.1),b.dragging=!0)},i.dragend=function(){var a=this,b=a.config;a.hasArcType()||b.data_selection_enabled&&(a.main.select("."+l.dragarea).transition().duration(100).style("opacity",0).remove(),a.main.selectAll("."+l.shape).classed(l.INCLUDED,!1),a.dragging=!1)},i.selectPoint=function(a,b,c){var d=this,e=d.config,f=(e.axis_rotated?d.circleY:d.circleX).bind(d),g=(e.axis_rotated?d.circleX:d.circleY).bind(d),h=d.pointSelectR.bind(d);e.data_onselected.call(d.api,b,a.node()),d.main.select("."+l.selectedCircles+d.getTargetSelectorSuffix(b.id)).selectAll("."+l.selectedCircle+"-"+c).data([b]).enter().append("circle").attr("class",function(){return d.generateClass(l.selectedCircle,c)}).attr("cx",f).attr("cy",g).attr("stroke",function(){return d.color(b)}).attr("r",function(a){return 1.4*d.pointSelectR(a)}).transition().duration(100).attr("r",h)},i.unselectPoint=function(a,b,c){var d=this;d.config.data_onunselected.call(d.api,b,a.node()),d.main.select("."+l.selectedCircles+d.getTargetSelectorSuffix(b.id)).selectAll("."+l.selectedCircle+"-"+c).transition().duration(100).attr("r",0).remove()},i.togglePoint=function(a,b,c,d){a?this.selectPoint(b,c,d):this.unselectPoint(b,c,d)},i.selectPath=function(a,b){var c=this;c.config.data_onselected.call(c,b,a.node()),a.transition().duration(100).style("fill",function(){return c.d3.rgb(c.color(b)).brighter(.75)})},i.unselectPath=function(a,b){var c=this;c.config.data_onunselected.call(c,b,a.node()),a.transition().duration(100).style("fill",function(){return c.color(b)})},i.togglePath=function(a,b,c,d){a?this.selectPath(b,c,d):this.unselectPath(b,c,d)},i.getToggle=function(a,b){var c,d=this;return"circle"===a.nodeName?c=d.isStepType(b)?function(){}:d.togglePoint:"path"===a.nodeName&&(c=d.togglePath),c},i.toggleShape=function(a,b,c){var d=this,e=d.d3,f=d.config,g=e.select(a),h=g.classed(l.SELECTED),i=d.getToggle(a,b).bind(d);f.data_selection_enabled&&f.data_selection_isselectable(b)&&(f.data_selection_multiple||d.main.selectAll("."+l.shapes+(f.data_selection_grouped?d.getTargetSelectorSuffix(b.id):"")).selectAll("."+l.shape).each(function(a,b){var c=e.select(this);c.classed(l.SELECTED)&&i(!1,c.classed(l.SELECTED,!1),a,b)}),g.classed(l.SELECTED,!h),i(!h,g,b,c))},i.initBrush=function(){var a=this,b=a.d3;a.brush=b.svg.brush().on("brush",function(){a.redrawForBrush()}),a.brush.update=function(){return a.context&&a.context.select("."+l.brush).call(this),this},a.brush.scale=function(b){return a.config.axis_rotated?this.y(b):this.x(b)}},i.initSubchart=function(){var a=this,b=a.config,c=a.context=a.svg.append("g").attr("transform",a.getTranslate("context")),d=b.subchart_show?"visible":"hidden";c.style("visibility",d),c.append("g").attr("clip-path",a.clipPathForSubchart).attr("class",l.chart),c.select("."+l.chart).append("g").attr("class",l.chartBars),c.select("."+l.chart).append("g").attr("class",l.chartLines),c.append("g").attr("clip-path",a.clipPath).attr("class",l.brush).call(a.brush),a.axes.subx=c.append("g").attr("class",l.axisX).attr("transform",a.getTranslate("subx")).attr("clip-path",b.axis_rotated?"":a.clipPathForXAxis).style("visibility",b.subchart_axis_x_show?d:"hidden")},i.updateTargetsForSubchart=function(a){var b,c,d,e,f=this,g=f.context,h=f.config,i=f.classChartBar.bind(f),j=f.classBars.bind(f),k=f.classChartLine.bind(f),m=f.classLines.bind(f),n=f.classAreas.bind(f);h.subchart_show&&(e=g.select("."+l.chartBars).selectAll("."+l.chartBar).data(a).attr("class",i),d=e.enter().append("g").style("opacity",0).attr("class",i),d.append("g").attr("class",j),c=g.select("."+l.chartLines).selectAll("."+l.chartLine).data(a).attr("class",k),b=c.enter().append("g").style("opacity",0).attr("class",k),b.append("g").attr("class",m),b.append("g").attr("class",n),g.selectAll("."+l.brush+" rect").attr(h.axis_rotated?"width":"height",h.axis_rotated?f.width2:f.height2))},i.updateBarForSubchart=function(a){var b=this;b.contextBar=b.context.selectAll("."+l.bars).selectAll("."+l.bar).data(b.barData.bind(b)),b.contextBar.enter().append("path").attr("class",b.classBar.bind(b)).style("stroke","none").style("fill",b.color),b.contextBar.style("opacity",b.initialOpacity.bind(b)),b.contextBar.exit().transition().duration(a).style("opacity",0).remove()},i.redrawBarForSubchart=function(a,b,c){(b?this.contextBar.transition(Math.random().toString()).duration(c):this.contextBar).attr("d",a).style("opacity",1)},i.updateLineForSubchart=function(a){var b=this;b.contextLine=b.context.selectAll("."+l.lines).selectAll("."+l.line).data(b.lineData.bind(b)),b.contextLine.enter().append("path").attr("class",b.classLine.bind(b)).style("stroke",b.color),b.contextLine.style("opacity",b.initialOpacity.bind(b)),b.contextLine.exit().transition().duration(a).style("opacity",0).remove()},i.redrawLineForSubchart=function(a,b,c){(b?this.contextLine.transition(Math.random().toString()).duration(c):this.contextLine).attr("d",a).style("opacity",1)},i.updateAreaForSubchart=function(a){var b=this,c=b.d3;b.contextArea=b.context.selectAll("."+l.areas).selectAll("."+l.area).data(b.lineData.bind(b)),b.contextArea.enter().append("path").attr("class",b.classArea.bind(b)).style("fill",b.color).style("opacity",function(){return b.orgAreaOpacity=+c.select(this).style("opacity"),0}),b.contextArea.style("opacity",0),b.contextArea.exit().transition().duration(a).style("opacity",0).remove()},i.redrawAreaForSubchart=function(a,b,c){(b?this.contextArea.transition(Math.random().toString()).duration(c):this.contextArea).attr("d",a).style("fill",this.color).style("opacity",this.orgAreaOpacity)},i.redrawSubchart=function(a,b,c,d,e,f,g){var h,i,j,k=this,l=k.d3,m=k.config;k.context.style("visibility",m.subchart_show?"visible":"hidden"),m.subchart_show&&(l.event&&"zoom"===l.event.type&&k.brush.extent(k.x.orgDomain()).update(),a&&(k.brush.empty()||k.brush.extent(k.x.orgDomain()).update(),h=k.generateDrawArea(e,!0),i=k.generateDrawBar(f,!0),j=k.generateDrawLine(g,!0),k.updateBarForSubchart(c),k.updateLineForSubchart(c),k.updateAreaForSubchart(c),k.redrawBarForSubchart(i,c,c),k.redrawLineForSubchart(j,c,c),k.redrawAreaForSubchart(h,c,c)))},i.redrawForBrush=function(){var a=this,b=a.x;a.redraw({withTransition:!1,withY:a.config.zoom_rescale,withSubchart:!1,withUpdateXDomain:!0,withDimension:!1}),a.config.subchart_onbrush.call(a.api,b.orgDomain())},i.transformContext=function(a,b){var c,d=this;b&&b.axisSubX?c=b.axisSubX:(c=d.context.select("."+l.axisX),a&&(c=c.transition())),d.context.attr("transform",d.getTranslate("context")),c.attr("transform",d.getTranslate("subx"))},i.getDefaultExtent=function(){var a=this,b=a.config,c=n(b.axis_x_extent)?b.axis_x_extent(a.getXDomain(a.data.targets)):b.axis_x_extent;return a.isTimeSeries()&&(c=[a.parseDate(c[0]),a.parseDate(c[1])]),c},i.initZoom=function(){var a,b=this,c=b.d3,d=b.config;b.zoom=c.behavior.zoom().on("zoomstart",function(){a=c.event.sourceEvent,b.zoom.altDomain=c.event.sourceEvent.altKey?b.x.orgDomain():null,d.zoom_onzoomstart.call(b.api,c.event.sourceEvent)}).on("zoom",function(){b.redrawForZoom.call(b)}).on("zoomend",function(){var e=c.event.sourceEvent;e&&a.clientX===e.clientX&&a.clientY===e.clientY||(b.redrawEventRect(),b.updateZoom(),d.zoom_onzoomend.call(b.api,b.x.orgDomain()))}),b.zoom.scale=function(a){return d.axis_rotated?this.y(a):this.x(a)},b.zoom.orgScaleExtent=function(){var a=d.zoom_extent?d.zoom_extent:[1,10];return[a[0],Math.max(b.getMaxDataCount()/a[1],a[1])]},b.zoom.updateScaleExtent=function(){var a=t(b.x.orgDomain())/t(b.getZoomDomain()),c=this.orgScaleExtent();return this.scaleExtent([c[0]*a,c[1]*a]),this}},i.getZoomDomain=function(){var a=this,b=a.config,c=a.d3,d=c.min([a.orgXDomain[0],b.zoom_x_min]),e=c.max([a.orgXDomain[1],b.zoom_x_max]);return[d,e]},i.updateZoom=function(){var a=this,b=a.config.zoom_enabled?a.zoom:function(){};a.main.select("."+l.zoomRect).call(b).on("dblclick.zoom",null),a.main.selectAll("."+l.eventRect).call(b).on("dblclick.zoom",null)},i.redrawForZoom=function(){var a=this,b=a.d3,c=a.config,d=a.zoom,e=a.x;if(c.zoom_enabled&&0!==a.filterTargetsToShow(a.data.targets).length){if("mousemove"===b.event.sourceEvent.type&&d.altDomain)return e.domain(d.altDomain),void d.scale(e).updateScaleExtent();a.isCategorized()&&e.orgDomain()[0]===a.orgXDomain[0]&&e.domain([a.orgXDomain[0]-1e-10,e.orgDomain()[1]]),a.redraw({withTransition:!1,withY:c.zoom_rescale,withSubchart:!1,withEventRect:!1,withDimension:!1}),"mousemove"===b.event.sourceEvent.type&&(a.cancelClick=!0),c.zoom_onzoom.call(a.api,e.orgDomain())}},i.generateColor=function(){var a=this,b=a.config,c=a.d3,d=b.data_colors,e=v(b.color_pattern)?b.color_pattern:c.scale.category10().range(),f=b.data_color,g=[];return function(a){var b,c=a.id||a.data&&a.data.id||a;return d[c]instanceof Function?b=d[c](a):d[c]?b=d[c]:(g.indexOf(c)<0&&g.push(c),b=e[g.indexOf(c)%e.length],d[c]=b),f instanceof Function?f(b,a):b}},i.generateLevelColor=function(){var a=this,b=a.config,c=b.color_pattern,d=b.color_threshold,e="value"===d.unit,f=d.values&&d.values.length?d.values:[],g=d.max||100;return v(b.color_threshold)?function(a){var b,d,h=c[c.length-1];for(b=0;b<f.length;b++)if(d=e?a:100*a/g,d<f[b]){h=c[b];break}return h}:null},i.getYFormat=function(a){var b=this,c=a&&!b.hasType("gauge")?b.defaultArcValueFormat:b.yFormat,d=a&&!b.hasType("gauge")?b.defaultArcValueFormat:b.y2Format;return function(a,e,f){var g="y2"===b.axis.getId(f)?d:c;return g.call(b,a,e)}},i.yFormat=function(a){var b=this,c=b.config,d=c.axis_y_tick_format?c.axis_y_tick_format:b.defaultValueFormat;return d(a)},i.y2Format=function(a){var b=this,c=b.config,d=c.axis_y2_tick_format?c.axis_y2_tick_format:b.defaultValueFormat;return d(a)},i.defaultValueFormat=function(a){return m(a)?+a:""},i.defaultArcValueFormat=function(a,b){return(100*b).toFixed(1)+"%"},i.dataLabelFormat=function(a){var b,c=this,d=c.config.data_labels,e=function(a){return m(a)?+a:""};return b="function"==typeof d.format?d.format:"object"==typeof d.format?d.format[a]?d.format[a]===!0?e:d.format[a]:function(){return""}:e},i.hasCaches=function(a){for(var b=0;b<a.length;b++)if(!(a[b]in this.cache))return!1;return!0},i.addCache=function(a,b){this.cache[a]=this.cloneTarget(b)},i.getCaches=function(a){var b,c=[];for(b=0;b<a.length;b++)a[b]in this.cache&&c.push(this.cloneTarget(this.cache[a[b]]));return c};var l=i.CLASS={target:"c3-target",chart:"c3-chart",chartLine:"c3-chart-line",chartLines:"c3-chart-lines",chartBar:"c3-chart-bar",chartBars:"c3-chart-bars",chartText:"c3-chart-text",chartTexts:"c3-chart-texts",chartArc:"c3-chart-arc",chartArcs:"c3-chart-arcs",chartArcsTitle:"c3-chart-arcs-title",chartArcsBackground:"c3-chart-arcs-background",chartArcsGaugeUnit:"c3-chart-arcs-gauge-unit",chartArcsGaugeMax:"c3-chart-arcs-gauge-max",chartArcsGaugeMin:"c3-chart-arcs-gauge-min",selectedCircle:"c3-selected-circle",selectedCircles:"c3-selected-circles",eventRect:"c3-event-rect",eventRects:"c3-event-rects",eventRectsSingle:"c3-event-rects-single",eventRectsMultiple:"c3-event-rects-multiple",zoomRect:"c3-zoom-rect",brush:"c3-brush",focused:"c3-focused",defocused:"c3-defocused",region:"c3-region",regions:"c3-regions",title:"c3-title",tooltipContainer:"c3-tooltip-container",tooltip:"c3-tooltip",tooltipName:"c3-tooltip-name",shape:"c3-shape",shapes:"c3-shapes",line:"c3-line",lines:"c3-lines",bar:"c3-bar",bars:"c3-bars",circle:"c3-circle",circles:"c3-circles",arc:"c3-arc",arcs:"c3-arcs",area:"c3-area",areas:"c3-areas",empty:"c3-empty",text:"c3-text",texts:"c3-texts",gaugeValue:"c3-gauge-value",grid:"c3-grid",gridLines:"c3-grid-lines",xgrid:"c3-xgrid",xgrids:"c3-xgrids",xgridLine:"c3-xgrid-line",xgridLines:"c3-xgrid-lines",xgridFocus:"c3-xgrid-focus",ygrid:"c3-ygrid",ygrids:"c3-ygrids",ygridLine:"c3-ygrid-line",ygridLines:"c3-ygrid-lines",axis:"c3-axis",axisX:"c3-axis-x",axisXLabel:"c3-axis-x-label",axisY:"c3-axis-y",axisYLabel:"c3-axis-y-label",axisY2:"c3-axis-y2",axisY2Label:"c3-axis-y2-label",legendBackground:"c3-legend-background",legendItem:"c3-legend-item",legendItemEvent:"c3-legend-item-event",legendItemTile:"c3-legend-item-tile",legendItemHidden:"c3-legend-item-hidden",legendItemFocused:"c3-legend-item-focused",dragarea:"c3-dragarea",EXPANDED:"_expanded_",SELECTED:"_selected_",INCLUDED:"_included_"};i.generateClass=function(a,b){return" "+a+" "+a+this.getTargetSelectorSuffix(b)},i.classText=function(a){return this.generateClass(l.text,a.index)},i.classTexts=function(a){return this.generateClass(l.texts,a.id)},i.classShape=function(a){return this.generateClass(l.shape,a.index)},i.classShapes=function(a){return this.generateClass(l.shapes,a.id)},i.classLine=function(a){return this.classShape(a)+this.generateClass(l.line,a.id)},i.classLines=function(a){return this.classShapes(a)+this.generateClass(l.lines,a.id)},i.classCircle=function(a){return this.classShape(a)+this.generateClass(l.circle,a.index)},i.classCircles=function(a){return this.classShapes(a)+this.generateClass(l.circles,a.id)},i.classBar=function(a){return this.classShape(a)+this.generateClass(l.bar,a.index)},i.classBars=function(a){return this.classShapes(a)+this.generateClass(l.bars,a.id)},i.classArc=function(a){return this.classShape(a.data)+this.generateClass(l.arc,a.data.id)},i.classArcs=function(a){return this.classShapes(a.data)+this.generateClass(l.arcs,a.data.id)},i.classArea=function(a){return this.classShape(a)+this.generateClass(l.area,a.id)},i.classAreas=function(a){return this.classShapes(a)+this.generateClass(l.areas,a.id)},i.classRegion=function(a,b){return this.generateClass(l.region,b)+" "+("class"in a?a["class"]:"")},i.classEvent=function(a){return this.generateClass(l.eventRect,a.index)},i.classTarget=function(a){var b=this,c=b.config.data_classes[a],d="";return c&&(d=" "+l.target+"-"+c),b.generateClass(l.target,a)+d},i.classFocus=function(a){return this.classFocused(a)+this.classDefocused(a)},i.classFocused=function(a){return" "+(this.focusedTargetIds.indexOf(a.id)>=0?l.focused:"")},i.classDefocused=function(a){return" "+(this.defocusedTargetIds.indexOf(a.id)>=0?l.defocused:"")},i.classChartText=function(a){return l.chartText+this.classTarget(a.id)},i.classChartLine=function(a){return l.chartLine+this.classTarget(a.id)},i.classChartBar=function(a){return l.chartBar+this.classTarget(a.id)},i.classChartArc=function(a){return l.chartArc+this.classTarget(a.data.id)},i.getTargetSelectorSuffix=function(a){return a||0===a?("-"+a).replace(/[\s?!@#$%^&*()_=+,.<>'":;\[\]\/|~`{}\\]/g,"-"):""},i.selectorTarget=function(a,b){return(b||"")+"."+l.target+this.getTargetSelectorSuffix(a)},i.selectorTargets=function(a,b){var c=this;return a=a||[],a.length?a.map(function(a){return c.selectorTarget(a,b)}):null},i.selectorLegend=function(a){return"."+l.legendItem+this.getTargetSelectorSuffix(a)},i.selectorLegends=function(a){var b=this;return a&&a.length?a.map(function(a){return b.selectorLegend(a)}):null};var m=i.isValue=function(a){return a||0===a},n=i.isFunction=function(a){return"function"==typeof a},o=i.isString=function(a){return"string"==typeof a},p=i.isUndefined=function(a){return"undefined"==typeof a},q=i.isDefined=function(a){return"undefined"!=typeof a},r=i.ceil10=function(a){return 10*Math.ceil(a/10)},s=i.asHalfPixel=function(a){return Math.ceil(a)+.5},t=i.diffDomain=function(a){return a[1]-a[0]},u=i.isEmpty=function(a){return"undefined"==typeof a||null===a||o(a)&&0===a.length||"object"==typeof a&&0===Object.keys(a).length},v=i.notEmpty=function(a){return!i.isEmpty(a)},w=i.getOption=function(a,b,c){return q(a[b])?a[b]:c},x=i.hasValue=function(a,b){var c=!1;return Object.keys(a).forEach(function(d){a[d]===b&&(c=!0)}),c},y=i.getPathBox=function(a){var b=a.getBoundingClientRect(),c=[a.pathSegList.getItem(0),a.pathSegList.getItem(1)],d=c[0].x,e=Math.min(c[0].y,c[1].y);return{x:d,y:e,width:b.width,height:b.height}};h.focus=function(a){var b,c=this.internal;a=c.mapToTargetIds(a),b=c.svg.selectAll(c.selectorTargets(a.filter(c.isTargetToShow,c))),this.revert(),this.defocus(),b.classed(l.focused,!0).classed(l.defocused,!1),c.hasArcType()&&c.expandArc(a),c.toggleFocusLegend(a,!0),c.focusedTargetIds=a,c.defocusedTargetIds=c.defocusedTargetIds.filter(function(b){return a.indexOf(b)<0})},h.defocus=function(a){var b,c=this.internal;a=c.mapToTargetIds(a),b=c.svg.selectAll(c.selectorTargets(a.filter(c.isTargetToShow,c))),b.classed(l.focused,!1).classed(l.defocused,!0),c.hasArcType()&&c.unexpandArc(a),c.toggleFocusLegend(a,!1),c.focusedTargetIds=c.focusedTargetIds.filter(function(b){return a.indexOf(b)<0}),c.defocusedTargetIds=a},h.revert=function(a){var b,c=this.internal;a=c.mapToTargetIds(a),b=c.svg.selectAll(c.selectorTargets(a)),b.classed(l.focused,!1).classed(l.defocused,!1),c.hasArcType()&&c.unexpandArc(a),c.config.legend_show&&(c.showLegend(a.filter(c.isLegendToShow.bind(c))),c.legend.selectAll(c.selectorLegends(a)).filter(function(){return c.d3.select(this).classed(l.legendItemFocused)}).classed(l.legendItemFocused,!1)),c.focusedTargetIds=[],c.defocusedTargetIds=[]},h.show=function(a,b){var c,d=this.internal;a=d.mapToTargetIds(a),b=b||{},d.removeHiddenTargetIds(a),c=d.svg.selectAll(d.selectorTargets(a)),c.transition().style("opacity",1,"important").call(d.endall,function(){c.style("opacity",null).style("opacity",1)}),b.withLegend&&d.showLegend(a),d.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0,withLegend:!0})},h.hide=function(a,b){var c,d=this.internal;a=d.mapToTargetIds(a),b=b||{},d.addHiddenTargetIds(a),c=d.svg.selectAll(d.selectorTargets(a)),c.transition().style("opacity",0,"important").call(d.endall,function(){c.style("opacity",null).style("opacity",0)}),b.withLegend&&d.hideLegend(a),d.redraw({
5
+withUpdateOrgXDomain:!0,withUpdateXDomain:!0,withLegend:!0})},h.toggle=function(a,b){var c=this,d=this.internal;d.mapToTargetIds(a).forEach(function(a){d.isTargetToShow(a)?c.hide(a,b):c.show(a,b)})},h.zoom=function(a){var b=this.internal;return a&&(b.isTimeSeries()&&(a=a.map(function(a){return b.parseDate(a)})),b.brush.extent(a),b.redraw({withUpdateXDomain:!0,withY:b.config.zoom_rescale}),b.config.zoom_onzoom.call(this,b.x.orgDomain())),b.brush.extent()},h.zoom.enable=function(a){var b=this.internal;b.config.zoom_enabled=a,b.updateAndRedraw()},h.unzoom=function(){var a=this.internal;a.brush.clear().update(),a.redraw({withUpdateXDomain:!0})},h.zoom.max=function(a){var b=this.internal,c=b.config,d=b.d3;return 0===a||a?void(c.zoom_x_max=d.max([b.orgXDomain[1],a])):c.zoom_x_max},h.zoom.min=function(a){var b=this.internal,c=b.config,d=b.d3;return 0===a||a?void(c.zoom_x_min=d.min([b.orgXDomain[0],a])):c.zoom_x_min},h.zoom.range=function(a){return arguments.length?(q(a.max)&&this.domain.max(a.max),void(q(a.min)&&this.domain.min(a.min))):{max:this.domain.max(),min:this.domain.min()}},h.load=function(a){var b=this.internal,c=b.config;return a.xs&&b.addXs(a.xs),"classes"in a&&Object.keys(a.classes).forEach(function(b){c.data_classes[b]=a.classes[b]}),"categories"in a&&b.isCategorized()&&(c.axis_x_categories=a.categories),"axes"in a&&Object.keys(a.axes).forEach(function(b){c.data_axes[b]=a.axes[b]}),"colors"in a&&Object.keys(a.colors).forEach(function(b){c.data_colors[b]=a.colors[b]}),"cacheIds"in a&&b.hasCaches(a.cacheIds)?void b.load(b.getCaches(a.cacheIds),a.done):void("unload"in a?b.unload(b.mapToTargetIds("boolean"==typeof a.unload&&a.unload?null:a.unload),function(){b.loadFromArgs(a)}):b.loadFromArgs(a))},h.unload=function(a){var b=this.internal;a=a||{},a instanceof Array?a={ids:a}:"string"==typeof a&&(a={ids:[a]}),b.unload(b.mapToTargetIds(a.ids),function(){b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0,withLegend:!0}),a.done&&a.done()})},h.flow=function(a){var b,c,d,e,f,g,h,i,j=this.internal,k=[],l=j.getMaxDataCount(),n=0,o=0;if(a.json)c=j.convertJsonToData(a.json,a.keys);else if(a.rows)c=j.convertRowsToData(a.rows);else{if(!a.columns)return;c=j.convertColumnsToData(a.columns)}b=j.convertDataToTargets(c,!0),j.data.targets.forEach(function(a){var c,d,e=!1;for(c=0;c<b.length;c++)if(a.id===b[c].id){for(e=!0,a.values[a.values.length-1]&&(o=a.values[a.values.length-1].index+1),n=b[c].values.length,d=0;n>d;d++)b[c].values[d].index=o+d,j.isTimeSeries()||(b[c].values[d].x=o+d);a.values=a.values.concat(b[c].values),b.splice(c,1);break}e||k.push(a.id)}),j.data.targets.forEach(function(a){var b,c;for(b=0;b<k.length;b++)if(a.id===k[b])for(o=a.values[a.values.length-1].index+1,c=0;n>c;c++)a.values.push({id:a.id,index:o+c,x:j.isTimeSeries()?j.getOtherTargetX(o+c):o+c,value:null})}),j.data.targets.length&&b.forEach(function(a){var b,c=[];for(b=j.data.targets[0].values[0].index;o>b;b++)c.push({id:a.id,index:b,x:j.isTimeSeries()?j.getOtherTargetX(b):b,value:null});a.values.forEach(function(a){a.index+=o,j.isTimeSeries()||(a.x+=o)}),a.values=c.concat(a.values)}),j.data.targets=j.data.targets.concat(b),d=j.getMaxDataCount(),f=j.data.targets[0],g=f.values[0],q(a.to)?(n=0,i=j.isTimeSeries()?j.parseDate(a.to):a.to,f.values.forEach(function(a){a.x<i&&n++})):q(a.length)&&(n=a.length),l?1===l&&j.isTimeSeries()&&(h=(f.values[f.values.length-1].x-g.x)/2,e=[new Date(+g.x-h),new Date(+g.x+h)],j.updateXDomain(null,!0,!0,!1,e)):(h=j.isTimeSeries()?f.values.length>1?f.values[f.values.length-1].x-g.x:g.x-j.getXDomain(j.data.targets)[0]:1,e=[g.x-h,g.x],j.updateXDomain(null,!0,!0,!1,e)),j.updateTargets(j.data.targets),j.redraw({flow:{index:g.index,length:n,duration:m(a.duration)?a.duration:j.config.transition_duration,done:a.done,orgDataCount:l},withLegend:!0,withTransition:l>1,withTrimXDomain:!1,withUpdateXAxis:!0})},i.generateFlow=function(a){var b=this,c=b.config,d=b.d3;return function(){var e,f,g,h=a.targets,i=a.flow,j=a.drawBar,k=a.drawLine,m=a.drawArea,n=a.cx,o=a.cy,p=a.xv,q=a.xForText,r=a.yForText,s=a.duration,u=1,v=i.index,w=i.length,x=b.getValueOnIndex(b.data.targets[0].values,v),y=b.getValueOnIndex(b.data.targets[0].values,v+w),z=b.x.domain(),A=i.duration||s,B=i.done||function(){},C=b.generateWait(),D=b.xgrid||d.selectAll([]),E=b.xgridLines||d.selectAll([]),F=b.mainRegion||d.selectAll([]),G=b.mainText||d.selectAll([]),H=b.mainBar||d.selectAll([]),I=b.mainLine||d.selectAll([]),J=b.mainArea||d.selectAll([]),K=b.mainCircle||d.selectAll([]);b.flowing=!0,b.data.targets.forEach(function(a){a.values.splice(0,w)}),g=b.updateXDomain(h,!0,!0),b.updateXGrid&&b.updateXGrid(!0),i.orgDataCount?e=1===i.orgDataCount||x.x===y.x?b.x(z[0])-b.x(g[0]):b.isTimeSeries()?b.x(z[0])-b.x(g[0]):b.x(x.x)-b.x(y.x):1!==b.data.targets[0].values.length?e=b.x(z[0])-b.x(g[0]):b.isTimeSeries()?(x=b.getValueOnIndex(b.data.targets[0].values,0),y=b.getValueOnIndex(b.data.targets[0].values,b.data.targets[0].values.length-1),e=b.x(x.x)-b.x(y.x)):e=t(g)/2,u=t(z)/t(g),f="translate("+e+",0) scale("+u+",1)",b.hideXGridFocus(),d.transition().ease("linear").duration(A).each(function(){C.add(b.axes.x.transition().call(b.xAxis)),C.add(H.transition().attr("transform",f)),C.add(I.transition().attr("transform",f)),C.add(J.transition().attr("transform",f)),C.add(K.transition().attr("transform",f)),C.add(G.transition().attr("transform",f)),C.add(F.filter(b.isRegionOnX).transition().attr("transform",f)),C.add(D.transition().attr("transform",f)),C.add(E.transition().attr("transform",f))}).call(C,function(){var a,d=[],e=[],f=[];if(w){for(a=0;w>a;a++)d.push("."+l.shape+"-"+(v+a)),e.push("."+l.text+"-"+(v+a)),f.push("."+l.eventRect+"-"+(v+a));b.svg.selectAll("."+l.shapes).selectAll(d).remove(),b.svg.selectAll("."+l.texts).selectAll(e).remove(),b.svg.selectAll("."+l.eventRects).selectAll(f).remove(),b.svg.select("."+l.xgrid).remove()}D.attr("transform",null).attr(b.xgridAttr),E.attr("transform",null),E.select("line").attr("x1",c.axis_rotated?0:p).attr("x2",c.axis_rotated?b.width:p),E.select("text").attr("x",c.axis_rotated?b.width:0).attr("y",p),H.attr("transform",null).attr("d",j),I.attr("transform",null).attr("d",k),J.attr("transform",null).attr("d",m),K.attr("transform",null).attr("cx",n).attr("cy",o),G.attr("transform",null).attr("x",q).attr("y",r).style("fill-opacity",b.opacityForText.bind(b)),F.attr("transform",null),F.select("rect").filter(b.isRegionOnX).attr("x",b.regionX.bind(b)).attr("width",b.regionWidth.bind(b)),c.interaction_enabled&&b.redrawEventRect(),B(),b.flowing=!1})}},h.selected=function(a){var b=this.internal,c=b.d3;return c.merge(b.main.selectAll("."+l.shapes+b.getTargetSelectorSuffix(a)).selectAll("."+l.shape).filter(function(){return c.select(this).classed(l.SELECTED)}).map(function(a){return a.map(function(a){var b=a.__data__;return b.data?b.data:b})}))},h.select=function(a,b,c){var d=this.internal,e=d.d3,f=d.config;f.data_selection_enabled&&d.main.selectAll("."+l.shapes).selectAll("."+l.shape).each(function(g,h){var i=e.select(this),j=g.data?g.data.id:g.id,k=d.getToggle(this,g).bind(d),m=f.data_selection_grouped||!a||a.indexOf(j)>=0,n=!b||b.indexOf(h)>=0,o=i.classed(l.SELECTED);i.classed(l.line)||i.classed(l.area)||(m&&n?f.data_selection_isselectable(g)&&!o&&k(!0,i.classed(l.SELECTED,!0),g,h):q(c)&&c&&o&&k(!1,i.classed(l.SELECTED,!1),g,h))})},h.unselect=function(a,b){var c=this.internal,d=c.d3,e=c.config;e.data_selection_enabled&&c.main.selectAll("."+l.shapes).selectAll("."+l.shape).each(function(f,g){var h=d.select(this),i=f.data?f.data.id:f.id,j=c.getToggle(this,f).bind(c),k=e.data_selection_grouped||!a||a.indexOf(i)>=0,m=!b||b.indexOf(g)>=0,n=h.classed(l.SELECTED);h.classed(l.line)||h.classed(l.area)||k&&m&&e.data_selection_isselectable(f)&&n&&j(!1,h.classed(l.SELECTED,!1),f,g)})},h.transform=function(a,b){var c=this.internal,d=["pie","donut"].indexOf(a)>=0?{withTransform:!0}:null;c.transformTo(b,a,d)},i.transformTo=function(a,b,c){var d=this,e=!d.hasArcType(),f=c||{withTransitionForAxis:e};f.withTransitionForTransform=!1,d.transiting=!1,d.setTargetType(a,b),d.updateTargets(d.data.targets),d.updateAndRedraw(f)},h.groups=function(a){var b=this.internal,c=b.config;return p(a)?c.data_groups:(c.data_groups=a,b.redraw(),c.data_groups)},h.xgrids=function(a){var b=this.internal,c=b.config;return a?(c.grid_x_lines=a,b.redrawWithoutRescale(),c.grid_x_lines):c.grid_x_lines},h.xgrids.add=function(a){var b=this.internal;return this.xgrids(b.config.grid_x_lines.concat(a?a:[]))},h.xgrids.remove=function(a){var b=this.internal;b.removeGridLines(a,!0)},h.ygrids=function(a){var b=this.internal,c=b.config;return a?(c.grid_y_lines=a,b.redrawWithoutRescale(),c.grid_y_lines):c.grid_y_lines},h.ygrids.add=function(a){var b=this.internal;return this.ygrids(b.config.grid_y_lines.concat(a?a:[]))},h.ygrids.remove=function(a){var b=this.internal;b.removeGridLines(a,!1)},h.regions=function(a){var b=this.internal,c=b.config;return a?(c.regions=a,b.redrawWithoutRescale(),c.regions):c.regions},h.regions.add=function(a){var b=this.internal,c=b.config;return a?(c.regions=c.regions.concat(a),b.redrawWithoutRescale(),c.regions):c.regions},h.regions.remove=function(a){var b,c,d,e=this.internal,f=e.config;return a=a||{},b=e.getOption(a,"duration",f.transition_duration),c=e.getOption(a,"classes",[l.region]),d=e.main.select("."+l.regions).selectAll(c.map(function(a){return"."+a})),(b?d.transition().duration(b):d).style("opacity",0).remove(),f.regions=f.regions.filter(function(a){var b=!1;return a["class"]?(a["class"].split(" ").forEach(function(a){c.indexOf(a)>=0&&(b=!0)}),!b):!0}),f.regions},h.data=function(a){var b=this.internal.data.targets;return"undefined"==typeof a?b:b.filter(function(b){return[].concat(a).indexOf(b.id)>=0})},h.data.shown=function(a){return this.internal.filterTargetsToShow(this.data(a))},h.data.values=function(a){var b,c=null;return a&&(b=this.data(a),c=b[0]?b[0].values.map(function(a){return a.value}):null),c},h.data.names=function(a){return this.internal.clearLegendItemTextBoxCache(),this.internal.updateDataAttributes("names",a)},h.data.colors=function(a){return this.internal.updateDataAttributes("colors",a)},h.data.axes=function(a){return this.internal.updateDataAttributes("axes",a)},h.category=function(a,b){var c=this.internal,d=c.config;return arguments.length>1&&(d.axis_x_categories[a]=b,c.redraw()),d.axis_x_categories[a]},h.categories=function(a){var b=this.internal,c=b.config;return arguments.length?(c.axis_x_categories=a,b.redraw(),c.axis_x_categories):c.axis_x_categories},h.color=function(a){var b=this.internal;return b.color(a)},h.x=function(a){var b=this.internal;return arguments.length&&(b.updateTargetX(b.data.targets,a),b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})),b.data.xs},h.xs=function(a){var b=this.internal;return arguments.length&&(b.updateTargetXs(b.data.targets,a),b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})),b.data.xs},h.axis=function(){},h.axis.labels=function(a){var b=this.internal;arguments.length&&(Object.keys(a).forEach(function(c){b.axis.setLabelText(c,a[c])}),b.axis.updateLabels())},h.axis.max=function(a){var b=this.internal,c=b.config;return arguments.length?("object"==typeof a?(m(a.x)&&(c.axis_x_max=a.x),m(a.y)&&(c.axis_y_max=a.y),m(a.y2)&&(c.axis_y2_max=a.y2)):c.axis_y_max=c.axis_y2_max=a,void b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})):{x:c.axis_x_max,y:c.axis_y_max,y2:c.axis_y2_max}},h.axis.min=function(a){var b=this.internal,c=b.config;return arguments.length?("object"==typeof a?(m(a.x)&&(c.axis_x_min=a.x),m(a.y)&&(c.axis_y_min=a.y),m(a.y2)&&(c.axis_y2_min=a.y2)):c.axis_y_min=c.axis_y2_min=a,void b.redraw({withUpdateOrgXDomain:!0,withUpdateXDomain:!0})):{x:c.axis_x_min,y:c.axis_y_min,y2:c.axis_y2_min}},h.axis.range=function(a){return arguments.length?(q(a.max)&&this.axis.max(a.max),void(q(a.min)&&this.axis.min(a.min))):{max:this.axis.max(),min:this.axis.min()}},h.legend=function(){},h.legend.show=function(a){var b=this.internal;b.showLegend(b.mapToTargetIds(a)),b.updateAndRedraw({withLegend:!0})},h.legend.hide=function(a){var b=this.internal;b.hideLegend(b.mapToTargetIds(a)),b.updateAndRedraw({withLegend:!0})},h.resize=function(a){var b=this.internal,c=b.config;c.size_width=a?a.width:null,c.size_height=a?a.height:null,this.flush()},h.flush=function(){var a=this.internal;a.updateAndRedraw({withLegend:!0,withTransition:!1,withTransitionForTransform:!1})},h.destroy=function(){var b=this.internal;if(a.clearInterval(b.intervalForObserveInserted),void 0!==b.resizeTimeout&&a.clearTimeout(b.resizeTimeout),a.detachEvent)a.detachEvent("onresize",b.resizeFunction);else if(a.removeEventListener)a.removeEventListener("resize",b.resizeFunction);else{var c=a.onresize;c&&c.add&&c.remove&&c.remove(b.resizeFunction)}return b.selectChart.classed("c3",!1).html(""),Object.keys(b).forEach(function(a){b[a]=null}),null},h.tooltip=function(){},h.tooltip.show=function(a){var b,c,d=this.internal;a.mouse&&(c=a.mouse),a.data?d.isMultipleX()?(c=[d.x(a.data.x),d.getYScale(a.data.id)(a.data.value)],b=null):b=m(a.data.index)?a.data.index:d.getIndexByX(a.data.x):"undefined"!=typeof a.x?b=d.getIndexByX(a.x):"undefined"!=typeof a.index&&(b=a.index),d.dispatchEvent("mouseover",b,c),d.dispatchEvent("mousemove",b,c),d.config.tooltip_onshow.call(d,a.data)},h.tooltip.hide=function(){this.internal.dispatchEvent("mouseout",0),this.internal.config.tooltip_onhide.call(this)};var z;i.isSafari=function(){var b=a.navigator.userAgent;return b.indexOf("Safari")>=0&&b.indexOf("Chrome")<0},i.isChrome=function(){var b=a.navigator.userAgent;return b.indexOf("Chrome")>=0},Function.prototype.bind||(Function.prototype.bind=function(a){if("function"!=typeof this)throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable");var b=Array.prototype.slice.call(arguments,1),c=this,d=function(){},e=function(){return c.apply(this instanceof d?this:a,b.concat(Array.prototype.slice.call(arguments)))};return d.prototype=this.prototype,e.prototype=new d,e}),"function"==typeof define&&define.amd?define("c3",["d3"],function(){return k}):"undefined"!=typeof exports&&"undefined"!=typeof module?module.exports=k:a.c3=k}(window);
\ No newline at end of file
web/lib/d3.min.js
new
+5
@@ -0,0 +1,5 @@
1
+!function(){function n(n){return n&&(n.ownerDocument||n.document||n).documentElement}function t(n){return n&&(n.ownerDocument&&n.ownerDocument.defaultView||n.document&&n||n.defaultView)}function e(n,t){return t>n?-1:n>t?1:n>=t?0:NaN}function r(n){return null===n?NaN:+n}function u(n){return!isNaN(n)}function i(n){return{left:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)<0?r=i+1:u=i}return r},right:function(t,e,r,u){for(arguments.length<3&&(r=0),arguments.length<4&&(u=t.length);u>r;){var i=r+u>>>1;n(t[i],e)>0?u=i:r=i+1}return r}}}function a(n){return n.length}function o(n){for(var t=1;n*t%1;)t*=10;return t}function l(n,t){for(var e in t)Object.defineProperty(n.prototype,e,{value:t[e],enumerable:!1})}function c(){this._=Object.create(null)}function s(n){return(n+="")===xa||n[0]===ba?ba+n:n}function f(n){return(n+="")[0]===ba?n.slice(1):n}function h(n){return s(n)in this._}function g(n){return(n=s(n))in this._&&delete this._[n]}function p(){var n=[];for(var t in this._)n.push(f(t));return n}function v(){var n=0;for(var t in this._)++n;return n}function d(){for(var n in this._)return!1;return!0}function m(){this._=Object.create(null)}function y(n){return n}function M(n,t,e){return function(){var r=e.apply(t,arguments);return r===t?n:r}}function x(n,t){if(t in n)return t;t=t.charAt(0).toUpperCase()+t.slice(1);for(var e=0,r=_a.length;r>e;++e){var u=_a[e]+t;if(u in n)return u}}function b(){}function _(){}function w(n){function t(){for(var t,r=e,u=-1,i=r.length;++u<i;)(t=r[u].on)&&t.apply(this,arguments);return n}var e=[],r=new c;return t.on=function(t,u){var i,a=r.get(t);return arguments.length<2?a&&a.on:(a&&(a.on=null,e=e.slice(0,i=e.indexOf(a)).concat(e.slice(i+1)),r.remove(t)),u&&e.push(r.set(t,{on:u})),n)},t}function S(){oa.event.preventDefault()}function k(){for(var n,t=oa.event;n=t.sourceEvent;)t=n;return t}function N(n){for(var t=new _,e=0,r=arguments.length;++e<r;)t[arguments[e]]=w(t);return t.of=function(e,r){return function(u){try{var i=u.sourceEvent=oa.event;u.target=n,oa.event=u,t[u.type].apply(e,r)}finally{oa.event=i}}},t}function E(n){return Sa(n,Aa),n}function A(n){return"function"==typeof n?n:function(){return ka(n,this)}}function C(n){return"function"==typeof n?n:function(){return Na(n,this)}}function z(n,t){function e(){this.removeAttribute(n)}function r(){this.removeAttributeNS(n.space,n.local)}function u(){this.setAttribute(n,t)}function i(){this.setAttributeNS(n.space,n.local,t)}function a(){var e=t.apply(this,arguments);null==e?this.removeAttribute(n):this.setAttribute(n,e)}function o(){var e=t.apply(this,arguments);null==e?this.removeAttributeNS(n.space,n.local):this.setAttributeNS(n.space,n.local,e)}return n=oa.ns.qualify(n),null==t?n.local?r:e:"function"==typeof t?n.local?o:a:n.local?i:u}function L(n){return n.trim().replace(/\s+/g," ")}function q(n){return new RegExp("(?:^|\\s+)"+oa.requote(n)+"(?:\\s+|$)","g")}function T(n){return(n+"").trim().split(/^|\s+/)}function R(n,t){function e(){for(var e=-1;++e<u;)n[e](this,t)}function r(){for(var e=-1,r=t.apply(this,arguments);++e<u;)n[e](this,r)}n=T(n).map(D);var u=n.length;return"function"==typeof t?r:e}function D(n){var t=q(n);return function(e,r){if(u=e.classList)return r?u.add(n):u.remove(n);var u=e.getAttribute("class")||"";r?(t.lastIndex=0,t.test(u)||e.setAttribute("class",L(u+" "+n))):e.setAttribute("class",L(u.replace(t," ")))}}function P(n,t,e){function r(){this.style.removeProperty(n)}function u(){this.style.setProperty(n,t,e)}function i(){var r=t.apply(this,arguments);null==r?this.style.removeProperty(n):this.style.setProperty(n,r,e)}return null==t?r:"function"==typeof t?i:u}function j(n,t){function e(){delete this[n]}function r(){this[n]=t}function u(){var e=t.apply(this,arguments);null==e?delete this[n]:this[n]=e}return null==t?e:"function"==typeof t?u:r}function U(n){function t(){var t=this.ownerDocument,e=this.namespaceURI;return e?t.createElementNS(e,n):t.createElement(n)}function e(){return this.ownerDocument.createElementNS(n.space,n.local)}return"function"==typeof n?n:(n=oa.ns.qualify(n)).local?e:t}function F(){var n=this.parentNode;n&&n.removeChild(this)}function H(n){return{__data__:n}}function O(n){return function(){return Ea(this,n)}}function I(n){return arguments.length||(n=e),function(t,e){return t&&e?n(t.__data__,e.__data__):!t-!e}}function Y(n,t){for(var e=0,r=n.length;r>e;e++)for(var u,i=n[e],a=0,o=i.length;o>a;a++)(u=i[a])&&t(u,a,e);return n}function Z(n){return Sa(n,za),n}function V(n){var t,e;return function(r,u,i){var a,o=n[i].update,l=o.length;for(i!=e&&(e=i,t=0),u>=t&&(t=u+1);!(a=o[t])&&++t<l;);return a}}function X(n,t,e){function r(){var t=this[a];t&&(this.removeEventListener(n,t,t.$),delete this[a])}function u(){var u=l(t,ca(arguments));r.call(this),this.addEventListener(n,this[a]=u,u.$=e),u._=t}function i(){var t,e=new RegExp("^__on([^.]+)"+oa.requote(n)+"$");for(var r in this)if(t=r.match(e)){var u=this[r];this.removeEventListener(t[1],u,u.$),delete this[r]}}var a="__on"+n,o=n.indexOf("."),l=$;o>0&&(n=n.slice(0,o));var c=La.get(n);return c&&(n=c,l=B),o?t?u:r:t?b:i}function $(n,t){return function(e){var r=oa.event;oa.event=e,t[0]=this.__data__;try{n.apply(this,t)}finally{oa.event=r}}}function B(n,t){var e=$(n,t);return function(n){var t=this,r=n.relatedTarget;r&&(r===t||8&r.compareDocumentPosition(t))||e.call(t,n)}}function W(e){var r=".dragsuppress-"+ ++Ta,u="click"+r,i=oa.select(t(e)).on("touchmove"+r,S).on("dragstart"+r,S).on("selectstart"+r,S);if(null==qa&&(qa="onselectstart"in e?!1:x(e.style,"userSelect")),qa){var a=n(e).style,o=a[qa];a[qa]="none"}return function(n){if(i.on(r,null),qa&&(a[qa]=o),n){var t=function(){i.on(u,null)};i.on(u,function(){S(),t()},!0),setTimeout(t,0)}}}function J(n,e){e.changedTouches&&(e=e.changedTouches[0]);var r=n.ownerSVGElement||n;if(r.createSVGPoint){var u=r.createSVGPoint();if(0>Ra){var i=t(n);if(i.scrollX||i.scrollY){r=oa.select("body").append("svg").style({position:"absolute",top:0,left:0,margin:0,padding:0,border:"none"},"important");var a=r[0][0].getScreenCTM();Ra=!(a.f||a.e),r.remove()}}return Ra?(u.x=e.pageX,u.y=e.pageY):(u.x=e.clientX,u.y=e.clientY),u=u.matrixTransform(n.getScreenCTM().inverse()),[u.x,u.y]}var o=n.getBoundingClientRect();return[e.clientX-o.left-n.clientLeft,e.clientY-o.top-n.clientTop]}function G(){return oa.event.changedTouches[0].identifier}function K(n){return n>0?1:0>n?-1:0}function Q(n,t,e){return(t[0]-n[0])*(e[1]-n[1])-(t[1]-n[1])*(e[0]-n[0])}function nn(n){return n>1?0:-1>n?ja:Math.acos(n)}function tn(n){return n>1?Ha:-1>n?-Ha:Math.asin(n)}function en(n){return((n=Math.exp(n))-1/n)/2}function rn(n){return((n=Math.exp(n))+1/n)/2}function un(n){return((n=Math.exp(2*n))-1)/(n+1)}function an(n){return(n=Math.sin(n/2))*n}function on(){}function ln(n,t,e){return this instanceof ln?(this.h=+n,this.s=+t,void(this.l=+e)):arguments.length<2?n instanceof ln?new ln(n.h,n.s,n.l):_n(""+n,wn,ln):new ln(n,t,e)}function cn(n,t,e){function r(n){return n>360?n-=360:0>n&&(n+=360),60>n?i+(a-i)*n/60:180>n?a:240>n?i+(a-i)*(240-n)/60:i}function u(n){return Math.round(255*r(n))}var i,a;return n=isNaN(n)?0:(n%=360)<0?n+360:n,t=isNaN(t)?0:0>t?0:t>1?1:t,e=0>e?0:e>1?1:e,a=.5>=e?e*(1+t):e+t-e*t,i=2*e-a,new yn(u(n+120),u(n),u(n-120))}function sn(n,t,e){return this instanceof sn?(this.h=+n,this.c=+t,void(this.l=+e)):arguments.length<2?n instanceof sn?new sn(n.h,n.c,n.l):n instanceof hn?pn(n.l,n.a,n.b):pn((n=Sn((n=oa.rgb(n)).r,n.g,n.b)).l,n.a,n.b):new sn(n,t,e)}function fn(n,t,e){return isNaN(n)&&(n=0),isNaN(t)&&(t=0),new hn(e,Math.cos(n*=Oa)*t,Math.sin(n)*t)}function hn(n,t,e){return this instanceof hn?(this.l=+n,this.a=+t,void(this.b=+e)):arguments.length<2?n instanceof hn?new hn(n.l,n.a,n.b):n instanceof sn?fn(n.h,n.c,n.l):Sn((n=yn(n)).r,n.g,n.b):new hn(n,t,e)}function gn(n,t,e){var r=(n+16)/116,u=r+t/500,i=r-e/200;return u=vn(u)*Ka,r=vn(r)*Qa,i=vn(i)*no,new yn(mn(3.2404542*u-1.5371385*r-.4985314*i),mn(-.969266*u+1.8760108*r+.041556*i),mn(.0556434*u-.2040259*r+1.0572252*i))}function pn(n,t,e){return n>0?new sn(Math.atan2(e,t)*Ia,Math.sqrt(t*t+e*e),n):new sn(NaN,NaN,n)}function vn(n){return n>.206893034?n*n*n:(n-4/29)/7.787037}function dn(n){return n>.008856?Math.pow(n,1/3):7.787037*n+4/29}function mn(n){return Math.round(255*(.00304>=n?12.92*n:1.055*Math.pow(n,1/2.4)-.055))}function yn(n,t,e){return this instanceof yn?(this.r=~~n,this.g=~~t,void(this.b=~~e)):arguments.length<2?n instanceof yn?new yn(n.r,n.g,n.b):_n(""+n,yn,cn):new yn(n,t,e)}function Mn(n){return new yn(n>>16,n>>8&255,255&n)}function xn(n){return Mn(n)+""}function bn(n){return 16>n?"0"+Math.max(0,n).toString(16):Math.min(255,n).toString(16)}function _n(n,t,e){var r,u,i,a=0,o=0,l=0;if(r=/([a-z]+)\((.*)\)/.exec(n=n.toLowerCase()))switch(u=r[2].split(","),r[1]){case"hsl":return e(parseFloat(u[0]),parseFloat(u[1])/100,parseFloat(u[2])/100);case"rgb":return t(Nn(u[0]),Nn(u[1]),Nn(u[2]))}return(i=ro.get(n))?t(i.r,i.g,i.b):(null==n||"#"!==n.charAt(0)||isNaN(i=parseInt(n.slice(1),16))||(4===n.length?(a=(3840&i)>>4,a=a>>4|a,o=240&i,o=o>>4|o,l=15&i,l=l<<4|l):7===n.length&&(a=(16711680&i)>>16,o=(65280&i)>>8,l=255&i)),t(a,o,l))}function wn(n,t,e){var r,u,i=Math.min(n/=255,t/=255,e/=255),a=Math.max(n,t,e),o=a-i,l=(a+i)/2;return o?(u=.5>l?o/(a+i):o/(2-a-i),r=n==a?(t-e)/o+(e>t?6:0):t==a?(e-n)/o+2:(n-t)/o+4,r*=60):(r=NaN,u=l>0&&1>l?0:r),new ln(r,u,l)}function Sn(n,t,e){n=kn(n),t=kn(t),e=kn(e);var r=dn((.4124564*n+.3575761*t+.1804375*e)/Ka),u=dn((.2126729*n+.7151522*t+.072175*e)/Qa),i=dn((.0193339*n+.119192*t+.9503041*e)/no);return hn(116*u-16,500*(r-u),200*(u-i))}function kn(n){return(n/=255)<=.04045?n/12.92:Math.pow((n+.055)/1.055,2.4)}function Nn(n){var t=parseFloat(n);return"%"===n.charAt(n.length-1)?Math.round(2.55*t):t}function En(n){return"function"==typeof n?n:function(){return n}}function An(n){return function(t,e,r){return 2===arguments.length&&"function"==typeof e&&(r=e,e=null),Cn(t,e,n,r)}}function Cn(n,t,e,r){function u(){var n,t=l.status;if(!t&&Ln(l)||t>=200&&300>t||304===t){try{n=e.call(i,l)}catch(r){return void a.error.call(i,r)}a.load.call(i,n)}else a.error.call(i,l)}var i={},a=oa.dispatch("beforesend","progress","load","error"),o={},l=new XMLHttpRequest,c=null;return!this.XDomainRequest||"withCredentials"in l||!/^(http(s)?:)?\/\//.test(n)||(l=new XDomainRequest),"onload"in l?l.onload=l.onerror=u:l.onreadystatechange=function(){l.readyState>3&&u()},l.onprogress=function(n){var t=oa.event;oa.event=n;try{a.progress.call(i,l)}finally{oa.event=t}},i.header=function(n,t){return n=(n+"").toLowerCase(),arguments.length<2?o[n]:(null==t?delete o[n]:o[n]=t+"",i)},i.mimeType=function(n){return arguments.length?(t=null==n?null:n+"",i):t},i.responseType=function(n){return arguments.length?(c=n,i):c},i.response=function(n){return e=n,i},["get","post"].forEach(function(n){i[n]=function(){return i.send.apply(i,[n].concat(ca(arguments)))}}),i.send=function(e,r,u){if(2===arguments.length&&"function"==typeof r&&(u=r,r=null),l.open(e,n,!0),null==t||"accept"in o||(o.accept=t+",*/*"),l.setRequestHeader)for(var s in o)l.setRequestHeader(s,o[s]);return null!=t&&l.overrideMimeType&&l.overrideMimeType(t),null!=c&&(l.responseType=c),null!=u&&i.on("error",u).on("load",function(n){u(null,n)}),a.beforesend.call(i,l),l.send(null==r?null:r),i},i.abort=function(){return l.abort(),i},oa.rebind(i,a,"on"),null==r?i:i.get(zn(r))}function zn(n){return 1===n.length?function(t,e){n(null==t?e:null)}:n}function Ln(n){var t=n.responseType;return t&&"text"!==t?n.response:n.responseText}function qn(n,t,e){var r=arguments.length;2>r&&(t=0),3>r&&(e=Date.now());var u=e+t,i={c:n,t:u,n:null};return io?io.n=i:uo=i,io=i,ao||(oo=clearTimeout(oo),ao=1,lo(Tn)),i}function Tn(){var n=Rn(),t=Dn()-n;t>24?(isFinite(t)&&(clearTimeout(oo),oo=setTimeout(Tn,t)),ao=0):(ao=1,lo(Tn))}function Rn(){for(var n=Date.now(),t=uo;t;)n>=t.t&&t.c(n-t.t)&&(t.c=null),t=t.n;return n}function Dn(){for(var n,t=uo,e=1/0;t;)t.c?(t.t<e&&(e=t.t),t=(n=t).n):t=n?n.n=t.n:uo=t.n;return io=n,e}function Pn(n,t){return t-(n?Math.ceil(Math.log(n)/Math.LN10):1)}function jn(n,t){var e=Math.pow(10,3*Ma(8-t));return{scale:t>8?function(n){return n/e}:function(n){return n*e},symbol:n}}function Un(n){var t=n.decimal,e=n.thousands,r=n.grouping,u=n.currency,i=r&&e?function(n,t){for(var u=n.length,i=[],a=0,o=r[0],l=0;u>0&&o>0&&(l+o+1>t&&(o=Math.max(1,t-l)),i.push(n.substring(u-=o,u+o)),!((l+=o+1)>t));)o=r[a=(a+1)%r.length];return i.reverse().join(e)}:y;return function(n){var e=so.exec(n),r=e[1]||" ",a=e[2]||">",o=e[3]||"-",l=e[4]||"",c=e[5],s=+e[6],f=e[7],h=e[8],g=e[9],p=1,v="",d="",m=!1,y=!0;switch(h&&(h=+h.substring(1)),(c||"0"===r&&"="===a)&&(c=r="0",a="="),g){case"n":f=!0,g="g";break;case"%":p=100,d="%",g="f";break;case"p":p=100,d="%",g="r";break;case"b":case"o":case"x":case"X":"#"===l&&(v="0"+g.toLowerCase());case"c":y=!1;case"d":m=!0,h=0;break;case"s":p=-1,g="r"}"$"===l&&(v=u[0],d=u[1]),"r"!=g||h||(g="g"),null!=h&&("g"==g?h=Math.max(1,Math.min(21,h)):("e"==g||"f"==g)&&(h=Math.max(0,Math.min(20,h)))),g=fo.get(g)||Fn;var M=c&&f;return function(n){var e=d;if(m&&n%1)return"";var u=0>n||0===n&&0>1/n?(n=-n,"-"):"-"===o?"":o;if(0>p){var l=oa.formatPrefix(n,h);n=l.scale(n),e=l.symbol+d}else n*=p;n=g(n,h);var x,b,_=n.lastIndexOf(".");if(0>_){var w=y?n.lastIndexOf("e"):-1;0>w?(x=n,b=""):(x=n.substring(0,w),b=n.substring(w))}else x=n.substring(0,_),b=t+n.substring(_+1);!c&&f&&(x=i(x,1/0));var S=v.length+x.length+b.length+(M?0:u.length),k=s>S?new Array(S=s-S+1).join(r):"";return M&&(x=i(k+x,k.length?s-b.length:1/0)),u+=v,n=x+b,("<"===a?u+n+k:">"===a?k+u+n:"^"===a?k.substring(0,S>>=1)+u+n+k.substring(S):u+(M?n:k+n))+e}}}function Fn(n){return n+""}function Hn(){this._=new Date(arguments.length>1?Date.UTC.apply(this,arguments):arguments[0])}function On(n,t,e){function r(t){var e=n(t),r=i(e,1);return r-t>t-e?e:r}function u(e){return t(e=n(new go(e-1)),1),e}function i(n,e){return t(n=new go(+n),e),n}function a(n,r,i){var a=u(n),o=[];if(i>1)for(;r>a;)e(a)%i||o.push(new Date(+a)),t(a,1);else for(;r>a;)o.push(new Date(+a)),t(a,1);return o}function o(n,t,e){try{go=Hn;var r=new Hn;return r._=n,a(r,t,e)}finally{go=Date}}n.floor=n,n.round=r,n.ceil=u,n.offset=i,n.range=a;var l=n.utc=In(n);return l.floor=l,l.round=In(r),l.ceil=In(u),l.offset=In(i),l.range=o,n}function In(n){return function(t,e){try{go=Hn;var r=new Hn;return r._=t,n(r,e)._}finally{go=Date}}}function Yn(n){function t(n){function t(t){for(var e,u,i,a=[],o=-1,l=0;++o<r;)37===n.charCodeAt(o)&&(a.push(n.slice(l,o)),null!=(u=vo[e=n.charAt(++o)])&&(e=n.charAt(++o)),(i=A[e])&&(e=i(t,null==u?"e"===e?" ":"0":u)),a.push(e),l=o+1);return a.push(n.slice(l,o)),a.join("")}var r=n.length;return t.parse=function(t){var r={y:1900,m:0,d:1,H:0,M:0,S:0,L:0,Z:null},u=e(r,n,t,0);if(u!=t.length)return null;"p"in r&&(r.H=r.H%12+12*r.p);var i=null!=r.Z&&go!==Hn,a=new(i?Hn:go);return"j"in r?a.setFullYear(r.y,0,r.j):"W"in r||"U"in r?("w"in r||(r.w="W"in r?1:0),a.setFullYear(r.y,0,1),a.setFullYear(r.y,0,"W"in r?(r.w+6)%7+7*r.W-(a.getDay()+5)%7:r.w+7*r.U-(a.getDay()+6)%7)):a.setFullYear(r.y,r.m,r.d),a.setHours(r.H+(r.Z/100|0),r.M+r.Z%100,r.S,r.L),i?a._:a},t.toString=function(){return n},t}function e(n,t,e,r){for(var u,i,a,o=0,l=t.length,c=e.length;l>o;){if(r>=c)return-1;if(u=t.charCodeAt(o++),37===u){if(a=t.charAt(o++),i=C[a in vo?t.charAt(o++):a],!i||(r=i(n,e,r))<0)return-1}else if(u!=e.charCodeAt(r++))return-1}return r}function r(n,t,e){_.lastIndex=0;var r=_.exec(t.slice(e));return r?(n.w=w.get(r[0].toLowerCase()),e+r[0].length):-1}function u(n,t,e){x.lastIndex=0;var r=x.exec(t.slice(e));return r?(n.w=b.get(r[0].toLowerCase()),e+r[0].length):-1}function i(n,t,e){N.lastIndex=0;var r=N.exec(t.slice(e));return r?(n.m=E.get(r[0].toLowerCase()),e+r[0].length):-1}function a(n,t,e){S.lastIndex=0;var r=S.exec(t.slice(e));return r?(n.m=k.get(r[0].toLowerCase()),e+r[0].length):-1}function o(n,t,r){return e(n,A.c.toString(),t,r)}function l(n,t,r){return e(n,A.x.toString(),t,r)}function c(n,t,r){return e(n,A.X.toString(),t,r)}function s(n,t,e){var r=M.get(t.slice(e,e+=2).toLowerCase());return null==r?-1:(n.p=r,e)}var f=n.dateTime,h=n.date,g=n.time,p=n.periods,v=n.days,d=n.shortDays,m=n.months,y=n.shortMonths;t.utc=function(n){function e(n){try{go=Hn;var t=new go;return t._=n,r(t)}finally{go=Date}}var r=t(n);return e.parse=function(n){try{go=Hn;var t=r.parse(n);return t&&t._}finally{go=Date}},e.toString=r.toString,e},t.multi=t.utc.multi=ct;var M=oa.map(),x=Vn(v),b=Xn(v),_=Vn(d),w=Xn(d),S=Vn(m),k=Xn(m),N=Vn(y),E=Xn(y);p.forEach(function(n,t){M.set(n.toLowerCase(),t)});var A={a:function(n){return d[n.getDay()]},A:function(n){return v[n.getDay()]},b:function(n){return y[n.getMonth()]},B:function(n){return m[n.getMonth()]},c:t(f),d:function(n,t){return Zn(n.getDate(),t,2)},e:function(n,t){return Zn(n.getDate(),t,2)},H:function(n,t){return Zn(n.getHours(),t,2)},I:function(n,t){return Zn(n.getHours()%12||12,t,2)},j:function(n,t){return Zn(1+ho.dayOfYear(n),t,3)},L:function(n,t){return Zn(n.getMilliseconds(),t,3)},m:function(n,t){return Zn(n.getMonth()+1,t,2)},M:function(n,t){return Zn(n.getMinutes(),t,2)},p:function(n){return p[+(n.getHours()>=12)]},S:function(n,t){return Zn(n.getSeconds(),t,2)},U:function(n,t){return Zn(ho.sundayOfYear(n),t,2)},w:function(n){return n.getDay()},W:function(n,t){return Zn(ho.mondayOfYear(n),t,2)},x:t(h),X:t(g),y:function(n,t){return Zn(n.getFullYear()%100,t,2)},Y:function(n,t){return Zn(n.getFullYear()%1e4,t,4)},Z:ot,"%":function(){return"%"}},C={a:r,A:u,b:i,B:a,c:o,d:tt,e:tt,H:rt,I:rt,j:et,L:at,m:nt,M:ut,p:s,S:it,U:Bn,w:$n,W:Wn,x:l,X:c,y:Gn,Y:Jn,Z:Kn,"%":lt};return t}function Zn(n,t,e){var r=0>n?"-":"",u=(r?-n:n)+"",i=u.length;return r+(e>i?new Array(e-i+1).join(t)+u:u)}function Vn(n){return new RegExp("^(?:"+n.map(oa.requote).join("|")+")","i")}function Xn(n){for(var t=new c,e=-1,r=n.length;++e<r;)t.set(n[e].toLowerCase(),e);return t}function $n(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+1));return r?(n.w=+r[0],e+r[0].length):-1}function Bn(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e));return r?(n.U=+r[0],e+r[0].length):-1}function Wn(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e));return r?(n.W=+r[0],e+r[0].length):-1}function Jn(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+4));return r?(n.y=+r[0],e+r[0].length):-1}function Gn(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+2));return r?(n.y=Qn(+r[0]),e+r[0].length):-1}function Kn(n,t,e){return/^[+-]\d{4}$/.test(t=t.slice(e,e+5))?(n.Z=-t,e+5):-1}function Qn(n){return n+(n>68?1900:2e3)}function nt(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+2));return r?(n.m=r[0]-1,e+r[0].length):-1}function tt(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+2));return r?(n.d=+r[0],e+r[0].length):-1}function et(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+3));return r?(n.j=+r[0],e+r[0].length):-1}function rt(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+2));return r?(n.H=+r[0],e+r[0].length):-1}function ut(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+2));return r?(n.M=+r[0],e+r[0].length):-1}function it(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+2));return r?(n.S=+r[0],e+r[0].length):-1}function at(n,t,e){mo.lastIndex=0;var r=mo.exec(t.slice(e,e+3));return r?(n.L=+r[0],e+r[0].length):-1}function ot(n){var t=n.getTimezoneOffset(),e=t>0?"-":"+",r=Ma(t)/60|0,u=Ma(t)%60;return e+Zn(r,"0",2)+Zn(u,"0",2)}function lt(n,t,e){yo.lastIndex=0;var r=yo.exec(t.slice(e,e+1));return r?e+r[0].length:-1}function ct(n){for(var t=n.length,e=-1;++e<t;)n[e][0]=this(n[e][0]);return function(t){for(var e=0,r=n[e];!r[1](t);)r=n[++e];return r[0](t)}}function st(){}function ft(n,t,e){var r=e.s=n+t,u=r-n,i=r-u;e.t=n-i+(t-u)}function ht(n,t){n&&_o.hasOwnProperty(n.type)&&_o[n.type](n,t)}function gt(n,t,e){var r,u=-1,i=n.length-e;for(t.lineStart();++u<i;)r=n[u],t.point(r[0],r[1],r[2]);t.lineEnd()}function pt(n,t){var e=-1,r=n.length;for(t.polygonStart();++e<r;)gt(n[e],t,1);t.polygonEnd()}function vt(){function n(n,t){n*=Oa,t=t*Oa/2+ja/4;var e=n-r,a=e>=0?1:-1,o=a*e,l=Math.cos(t),c=Math.sin(t),s=i*c,f=u*l+s*Math.cos(o),h=s*a*Math.sin(o);So.add(Math.atan2(h,f)),r=n,u=l,i=c}var t,e,r,u,i;ko.point=function(a,o){ko.point=n,r=(t=a)*Oa,u=Math.cos(o=(e=o)*Oa/2+ja/4),i=Math.sin(o)},ko.lineEnd=function(){n(t,e)}}function dt(n){var t=n[0],e=n[1],r=Math.cos(e);return[r*Math.cos(t),r*Math.sin(t),Math.sin(e)]}function mt(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]}function yt(n,t){return[n[1]*t[2]-n[2]*t[1],n[2]*t[0]-n[0]*t[2],n[0]*t[1]-n[1]*t[0]]}function Mt(n,t){n[0]+=t[0],n[1]+=t[1],n[2]+=t[2]}function xt(n,t){return[n[0]*t,n[1]*t,n[2]*t]}function bt(n){var t=Math.sqrt(n[0]*n[0]+n[1]*n[1]+n[2]*n[2]);n[0]/=t,n[1]/=t,n[2]/=t}function _t(n){return[Math.atan2(n[1],n[0]),tn(n[2])]}function wt(n,t){return Ma(n[0]-t[0])<Da&&Ma(n[1]-t[1])<Da}function St(n,t){n*=Oa;var e=Math.cos(t*=Oa);kt(e*Math.cos(n),e*Math.sin(n),Math.sin(t))}function kt(n,t,e){++No,Ao+=(n-Ao)/No,Co+=(t-Co)/No,zo+=(e-zo)/No}function Nt(){function n(n,u){n*=Oa;var i=Math.cos(u*=Oa),a=i*Math.cos(n),o=i*Math.sin(n),l=Math.sin(u),c=Math.atan2(Math.sqrt((c=e*l-r*o)*c+(c=r*a-t*l)*c+(c=t*o-e*a)*c),t*a+e*o+r*l);Eo+=c,Lo+=c*(t+(t=a)),qo+=c*(e+(e=o)),To+=c*(r+(r=l)),kt(t,e,r)}var t,e,r;jo.point=function(u,i){u*=Oa;var a=Math.cos(i*=Oa);t=a*Math.cos(u),e=a*Math.sin(u),r=Math.sin(i),jo.point=n,kt(t,e,r)}}function Et(){jo.point=St}function At(){function n(n,t){n*=Oa;var e=Math.cos(t*=Oa),a=e*Math.cos(n),o=e*Math.sin(n),l=Math.sin(t),c=u*l-i*o,s=i*a-r*l,f=r*o-u*a,h=Math.sqrt(c*c+s*s+f*f),g=r*a+u*o+i*l,p=h&&-nn(g)/h,v=Math.atan2(h,g);Ro+=p*c,Do+=p*s,Po+=p*f,Eo+=v,Lo+=v*(r+(r=a)),qo+=v*(u+(u=o)),To+=v*(i+(i=l)),kt(r,u,i)}var t,e,r,u,i;jo.point=function(a,o){t=a,e=o,jo.point=n,a*=Oa;var l=Math.cos(o*=Oa);r=l*Math.cos(a),u=l*Math.sin(a),i=Math.sin(o),kt(r,u,i)},jo.lineEnd=function(){n(t,e),jo.lineEnd=Et,jo.point=St}}function Ct(n,t){function e(e,r){return e=n(e,r),t(e[0],e[1])}return n.invert&&t.invert&&(e.invert=function(e,r){return e=t.invert(e,r),e&&n.invert(e[0],e[1])}),e}function zt(){return!0}function Lt(n,t,e,r,u){var i=[],a=[];if(n.forEach(function(n){if(!((t=n.length-1)<=0)){var t,e=n[0],r=n[t];if(wt(e,r)){u.lineStart();for(var o=0;t>o;++o)u.point((e=n[o])[0],e[1]);return void u.lineEnd()}var l=new Tt(e,n,null,!0),c=new Tt(e,null,l,!1);l.o=c,i.push(l),a.push(c),l=new Tt(r,n,null,!1),c=new Tt(r,null,l,!0),l.o=c,i.push(l),a.push(c)}}),a.sort(t),qt(i),qt(a),i.length){for(var o=0,l=e,c=a.length;c>o;++o)a[o].e=l=!l;for(var s,f,h=i[0];;){for(var g=h,p=!0;g.v;)if((g=g.n)===h)return;s=g.z,u.lineStart();do{if(g.v=g.o.v=!0,g.e){if(p)for(var o=0,c=s.length;c>o;++o)u.point((f=s[o])[0],f[1]);else r(g.x,g.n.x,1,u);g=g.n}else{if(p){s=g.p.z;for(var o=s.length-1;o>=0;--o)u.point((f=s[o])[0],f[1])}else r(g.x,g.p.x,-1,u);g=g.p}g=g.o,s=g.z,p=!p}while(!g.v);u.lineEnd()}}}function qt(n){if(t=n.length){for(var t,e,r=0,u=n[0];++r<t;)u.n=e=n[r],e.p=u,u=e;u.n=e=n[0],e.p=u}}function Tt(n,t,e,r){this.x=n,this.z=t,this.o=e,this.e=r,this.v=!1,this.n=this.p=null}function Rt(n,t,e,r){return function(u,i){function a(t,e){var r=u(t,e);n(t=r[0],e=r[1])&&i.point(t,e)}function o(n,t){var e=u(n,t);d.point(e[0],e[1])}function l(){y.point=o,d.lineStart()}function c(){y.point=a,d.lineEnd()}function s(n,t){v.push([n,t]);var e=u(n,t);x.point(e[0],e[1])}function f(){x.lineStart(),v=[]}function h(){s(v[0][0],v[0][1]),x.lineEnd();var n,t=x.clean(),e=M.buffer(),r=e.length;if(v.pop(),p.push(v),v=null,r)if(1&t){n=e[0];var u,r=n.length-1,a=-1;if(r>0){for(b||(i.polygonStart(),b=!0),i.lineStart();++a<r;)i.point((u=n[a])[0],u[1]);i.lineEnd()}}else r>1&&2&t&&e.push(e.pop().concat(e.shift())),g.push(e.filter(Dt))}var g,p,v,d=t(i),m=u.invert(r[0],r[1]),y={point:a,lineStart:l,lineEnd:c,polygonStart:function(){y.point=s,y.lineStart=f,y.lineEnd=h,g=[],p=[]},polygonEnd:function(){y.point=a,y.lineStart=l,y.lineEnd=c,g=oa.merge(g);var n=Ot(m,p);g.length?(b||(i.polygonStart(),b=!0),Lt(g,jt,n,e,i)):n&&(b||(i.polygonStart(),b=!0),i.lineStart(),e(null,null,1,i),i.lineEnd()),b&&(i.polygonEnd(),b=!1),g=p=null},sphere:function(){i.polygonStart(),i.lineStart(),e(null,null,1,i),i.lineEnd(),i.polygonEnd()}},M=Pt(),x=t(M),b=!1;return y}}function Dt(n){return n.length>1}function Pt(){var n,t=[];return{lineStart:function(){t.push(n=[])},point:function(t,e){n.push([t,e])},lineEnd:b,buffer:function(){var e=t;return t=[],n=null,e},rejoin:function(){t.length>1&&t.push(t.pop().concat(t.shift()))}}}function jt(n,t){return((n=n.x)[0]<0?n[1]-Ha-Da:Ha-n[1])-((t=t.x)[0]<0?t[1]-Ha-Da:Ha-t[1])}function Ut(n){var t,e=NaN,r=NaN,u=NaN;return{lineStart:function(){n.lineStart(),t=1},point:function(i,a){var o=i>0?ja:-ja,l=Ma(i-e);Ma(l-ja)<Da?(n.point(e,r=(r+a)/2>0?Ha:-Ha),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(o,r),n.point(i,r),t=0):u!==o&&l>=ja&&(Ma(e-u)<Da&&(e-=u*Da),Ma(i-o)<Da&&(i-=o*Da),r=Ft(e,r,i,a),n.point(u,r),n.lineEnd(),n.lineStart(),n.point(o,r),t=0),n.point(e=i,r=a),u=o},lineEnd:function(){n.lineEnd(),e=r=NaN},clean:function(){return 2-t}}}function Ft(n,t,e,r){var u,i,a=Math.sin(n-e);return Ma(a)>Da?Math.atan((Math.sin(t)*(i=Math.cos(r))*Math.sin(e)-Math.sin(r)*(u=Math.cos(t))*Math.sin(n))/(u*i*a)):(t+r)/2}function Ht(n,t,e,r){var u;if(null==n)u=e*Ha,r.point(-ja,u),r.point(0,u),r.point(ja,u),r.point(ja,0),r.point(ja,-u),r.point(0,-u),r.point(-ja,-u),r.point(-ja,0),r.point(-ja,u);else if(Ma(n[0]-t[0])>Da){var i=n[0]<t[0]?ja:-ja;u=e*i/2,r.point(-i,u),r.point(0,u),r.point(i,u)}else r.point(t[0],t[1])}function Ot(n,t){var e=n[0],r=n[1],u=[Math.sin(e),-Math.cos(e),0],i=0,a=0;So.reset();for(var o=0,l=t.length;l>o;++o){var c=t[o],s=c.length;if(s)for(var f=c[0],h=f[0],g=f[1]/2+ja/4,p=Math.sin(g),v=Math.cos(g),d=1;;){d===s&&(d=0),n=c[d];var m=n[0],y=n[1]/2+ja/4,M=Math.sin(y),x=Math.cos(y),b=m-h,_=b>=0?1:-1,w=_*b,S=w>ja,k=p*M;if(So.add(Math.atan2(k*_*Math.sin(w),v*x+k*Math.cos(w))),i+=S?b+_*Ua:b,S^h>=e^m>=e){var N=yt(dt(f),dt(n));bt(N);var E=yt(u,N);bt(E);var A=(S^b>=0?-1:1)*tn(E[2]);(r>A||r===A&&(N[0]||N[1]))&&(a+=S^b>=0?1:-1)}if(!d++)break;h=m,p=M,v=x,f=n}}return(-Da>i||Da>i&&0>So)^1&a}function It(n){function t(n,t){return Math.cos(n)*Math.cos(t)>i}function e(n){var e,i,l,c,s;return{lineStart:function(){c=l=!1,s=1},point:function(f,h){var g,p=[f,h],v=t(f,h),d=a?v?0:u(f,h):v?u(f+(0>f?ja:-ja),h):0;if(!e&&(c=l=v)&&n.lineStart(),v!==l&&(g=r(e,p),(wt(e,g)||wt(p,g))&&(p[0]+=Da,p[1]+=Da,v=t(p[0],p[1]))),v!==l)s=0,v?(n.lineStart(),g=r(p,e),n.point(g[0],g[1])):(g=r(e,p),n.point(g[0],g[1]),n.lineEnd()),e=g;else if(o&&e&&a^v){var m;d&i||!(m=r(p,e,!0))||(s=0,a?(n.lineStart(),n.point(m[0][0],m[0][1]),n.point(m[1][0],m[1][1]),n.lineEnd()):(n.point(m[1][0],m[1][1]),n.lineEnd(),n.lineStart(),n.point(m[0][0],m[0][1])))}!v||e&&wt(e,p)||n.point(p[0],p[1]),e=p,l=v,i=d},lineEnd:function(){l&&n.lineEnd(),e=null},clean:function(){return s|(c&&l)<<1}}}function r(n,t,e){var r=dt(n),u=dt(t),a=[1,0,0],o=yt(r,u),l=mt(o,o),c=o[0],s=l-c*c;if(!s)return!e&&n;var f=i*l/s,h=-i*c/s,g=yt(a,o),p=xt(a,f),v=xt(o,h);Mt(p,v);var d=g,m=mt(p,d),y=mt(d,d),M=m*m-y*(mt(p,p)-1);if(!(0>M)){var x=Math.sqrt(M),b=xt(d,(-m-x)/y);if(Mt(b,p),b=_t(b),!e)return b;var _,w=n[0],S=t[0],k=n[1],N=t[1];w>S&&(_=w,w=S,S=_);var E=S-w,A=Ma(E-ja)<Da,C=A||Da>E;if(!A&&k>N&&(_=k,k=N,N=_),C?A?k+N>0^b[1]<(Ma(b[0]-w)<Da?k:N):k<=b[1]&&b[1]<=N:E>ja^(w<=b[0]&&b[0]<=S)){var z=xt(d,(-m+x)/y);return Mt(z,p),[b,_t(z)]}}}function u(t,e){var r=a?n:ja-n,u=0;return-r>t?u|=1:t>r&&(u|=2),-r>e?u|=4:e>r&&(u|=8),u}var i=Math.cos(n),a=i>0,o=Ma(i)>Da,l=ve(n,6*Oa);return Rt(t,e,l,a?[0,-n]:[-ja,n-ja])}function Yt(n,t,e,r){return function(u){var i,a=u.a,o=u.b,l=a.x,c=a.y,s=o.x,f=o.y,h=0,g=1,p=s-l,v=f-c;if(i=n-l,p||!(i>0)){if(i/=p,0>p){if(h>i)return;g>i&&(g=i)}else if(p>0){if(i>g)return;i>h&&(h=i)}if(i=e-l,p||!(0>i)){if(i/=p,0>p){if(i>g)return;i>h&&(h=i)}else if(p>0){if(h>i)return;g>i&&(g=i)}if(i=t-c,v||!(i>0)){if(i/=v,0>v){if(h>i)return;g>i&&(g=i)}else if(v>0){if(i>g)return;i>h&&(h=i)}if(i=r-c,v||!(0>i)){if(i/=v,0>v){if(i>g)return;i>h&&(h=i)}else if(v>0){if(h>i)return;g>i&&(g=i)}return h>0&&(u.a={x:l+h*p,y:c+h*v}),1>g&&(u.b={x:l+g*p,y:c+g*v}),u}}}}}}function Zt(n,t,e,r){function u(r,u){return Ma(r[0]-n)<Da?u>0?0:3:Ma(r[0]-e)<Da?u>0?2:1:Ma(r[1]-t)<Da?u>0?1:0:u>0?3:2}function i(n,t){return a(n.x,t.x)}function a(n,t){var e=u(n,1),r=u(t,1);return e!==r?e-r:0===e?t[1]-n[1]:1===e?n[0]-t[0]:2===e?n[1]-t[1]:t[0]-n[0]}return function(o){function l(n){for(var t=0,e=d.length,r=n[1],u=0;e>u;++u)for(var i,a=1,o=d[u],l=o.length,c=o[0];l>a;++a)i=o[a],c[1]<=r?i[1]>r&&Q(c,i,n)>0&&++t:i[1]<=r&&Q(c,i,n)<0&&--t,c=i;return 0!==t}function c(i,o,l,c){var s=0,f=0;if(null==i||(s=u(i,l))!==(f=u(o,l))||a(i,o)<0^l>0){do c.point(0===s||3===s?n:e,s>1?r:t);while((s=(s+l+4)%4)!==f)}else c.point(o[0],o[1])}function s(u,i){return u>=n&&e>=u&&i>=t&&r>=i}function f(n,t){s(n,t)&&o.point(n,t)}function h(){C.point=p,d&&d.push(m=[]),S=!0,w=!1,b=_=NaN}function g(){v&&(p(y,M),x&&w&&E.rejoin(),v.push(E.buffer())),C.point=f,w&&o.lineEnd()}function p(n,t){n=Math.max(-Fo,Math.min(Fo,n)),t=Math.max(-Fo,Math.min(Fo,t));var e=s(n,t);if(d&&m.push([n,t]),S)y=n,M=t,x=e,S=!1,e&&(o.lineStart(),o.point(n,t));else if(e&&w)o.point(n,t);else{var r={a:{x:b,y:_},b:{x:n,y:t}};A(r)?(w||(o.lineStart(),o.point(r.a.x,r.a.y)),o.point(r.b.x,r.b.y),e||o.lineEnd(),k=!1):e&&(o.lineStart(),o.point(n,t),k=!1)}b=n,_=t,w=e}var v,d,m,y,M,x,b,_,w,S,k,N=o,E=Pt(),A=Yt(n,t,e,r),C={point:f,lineStart:h,lineEnd:g,polygonStart:function(){o=E,v=[],d=[],k=!0},polygonEnd:function(){o=N,v=oa.merge(v);var t=l([n,r]),e=k&&t,u=v.length;(e||u)&&(o.polygonStart(),e&&(o.lineStart(),c(null,null,1,o),o.lineEnd()),u&&Lt(v,i,t,c,o),o.polygonEnd()),v=d=m=null}};return C}}function Vt(n){var t=0,e=ja/3,r=oe(n),u=r(t,e);return u.parallels=function(n){return arguments.length?r(t=n[0]*ja/180,e=n[1]*ja/180):[t/ja*180,e/ja*180]},u}function Xt(n,t){function e(n,t){var e=Math.sqrt(i-2*u*Math.sin(t))/u;return[e*Math.sin(n*=u),a-e*Math.cos(n)]}var r=Math.sin(n),u=(r+Math.sin(t))/2,i=1+r*(2*u-r),a=Math.sqrt(i)/u;return e.invert=function(n,t){var e=a-t;return[Math.atan2(n,e)/u,tn((i-(n*n+e*e)*u*u)/(2*u))]},e}function $t(){function n(n,t){Oo+=u*n-r*t,r=n,u=t}var t,e,r,u;Xo.point=function(i,a){Xo.point=n,t=r=i,e=u=a},Xo.lineEnd=function(){n(t,e)}}function Bt(n,t){Io>n&&(Io=n),n>Zo&&(Zo=n),Yo>t&&(Yo=t),t>Vo&&(Vo=t)}function Wt(){function n(n,t){a.push("M",n,",",t,i)}function t(n,t){a.push("M",n,",",t),o.point=e}function e(n,t){a.push("L",n,",",t)}function r(){o.point=n}function u(){a.push("Z")}var i=Jt(4.5),a=[],o={point:n,lineStart:function(){o.point=t},lineEnd:r,polygonStart:function(){o.lineEnd=u},polygonEnd:function(){o.lineEnd=r,o.point=n},pointRadius:function(n){return i=Jt(n),o},result:function(){if(a.length){var n=a.join("");return a=[],n}}};return o}function Jt(n){return"m0,"+n+"a"+n+","+n+" 0 1,1 0,"+-2*n+"a"+n+","+n+" 0 1,1 0,"+2*n+"z"}function Gt(n,t){Ao+=n,Co+=t,++zo}function Kt(){function n(n,r){var u=n-t,i=r-e,a=Math.sqrt(u*u+i*i);Lo+=a*(t+n)/2,qo+=a*(e+r)/2,To+=a,Gt(t=n,e=r)}var t,e;Bo.point=function(r,u){Bo.point=n,Gt(t=r,e=u)}}function Qt(){Bo.point=Gt}function ne(){function n(n,t){var e=n-r,i=t-u,a=Math.sqrt(e*e+i*i);Lo+=a*(r+n)/2,qo+=a*(u+t)/2,To+=a,a=u*n-r*t,Ro+=a*(r+n),Do+=a*(u+t),Po+=3*a,Gt(r=n,u=t)}var t,e,r,u;Bo.point=function(i,a){Bo.point=n,Gt(t=r=i,e=u=a)},Bo.lineEnd=function(){n(t,e)}}function te(n){function t(t,e){n.moveTo(t+a,e),n.arc(t,e,a,0,Ua)}function e(t,e){n.moveTo(t,e),o.point=r}function r(t,e){n.lineTo(t,e)}function u(){o.point=t}function i(){n.closePath()}var a=4.5,o={point:t,lineStart:function(){o.point=e},lineEnd:u,polygonStart:function(){o.lineEnd=i},polygonEnd:function(){o.lineEnd=u,o.point=t},pointRadius:function(n){return a=n,o},result:b};return o}function ee(n){function t(n){return(o?r:e)(n)}function e(t){return ie(t,function(e,r){e=n(e,r),t.point(e[0],e[1])})}function r(t){function e(e,r){e=n(e,r),t.point(e[0],e[1])}function r(){M=NaN,S.point=i,t.lineStart()}function i(e,r){var i=dt([e,r]),a=n(e,r);u(M,x,y,b,_,w,M=a[0],x=a[1],y=e,b=i[0],_=i[1],w=i[2],o,t),t.point(M,x)}function a(){S.point=e,t.lineEnd()}function l(){r(),S.point=c,S.lineEnd=s}function c(n,t){
2
+i(f=n,h=t),g=M,p=x,v=b,d=_,m=w,S.point=i}function s(){u(M,x,y,b,_,w,g,p,f,v,d,m,o,t),S.lineEnd=a,a()}var f,h,g,p,v,d,m,y,M,x,b,_,w,S={point:e,lineStart:r,lineEnd:a,polygonStart:function(){t.polygonStart(),S.lineStart=l},polygonEnd:function(){t.polygonEnd(),S.lineStart=r}};return S}function u(t,e,r,o,l,c,s,f,h,g,p,v,d,m){var y=s-t,M=f-e,x=y*y+M*M;if(x>4*i&&d--){var b=o+g,_=l+p,w=c+v,S=Math.sqrt(b*b+_*_+w*w),k=Math.asin(w/=S),N=Ma(Ma(w)-1)<Da||Ma(r-h)<Da?(r+h)/2:Math.atan2(_,b),E=n(N,k),A=E[0],C=E[1],z=A-t,L=C-e,q=M*z-y*L;(q*q/x>i||Ma((y*z+M*L)/x-.5)>.3||a>o*g+l*p+c*v)&&(u(t,e,r,o,l,c,A,C,N,b/=S,_/=S,w,d,m),m.point(A,C),u(A,C,N,b,_,w,s,f,h,g,p,v,d,m))}}var i=.5,a=Math.cos(30*Oa),o=16;return t.precision=function(n){return arguments.length?(o=(i=n*n)>0&&16,t):Math.sqrt(i)},t}function re(n){var t=ee(function(t,e){return n([t*Ia,e*Ia])});return function(n){return le(t(n))}}function ue(n){this.stream=n}function ie(n,t){return{point:t,sphere:function(){n.sphere()},lineStart:function(){n.lineStart()},lineEnd:function(){n.lineEnd()},polygonStart:function(){n.polygonStart()},polygonEnd:function(){n.polygonEnd()}}}function ae(n){return oe(function(){return n})()}function oe(n){function t(n){return n=o(n[0]*Oa,n[1]*Oa),[n[0]*h+l,c-n[1]*h]}function e(n){return n=o.invert((n[0]-l)/h,(c-n[1])/h),n&&[n[0]*Ia,n[1]*Ia]}function r(){o=Ct(a=fe(m,M,x),i);var n=i(v,d);return l=g-n[0]*h,c=p+n[1]*h,u()}function u(){return s&&(s.valid=!1,s=null),t}var i,a,o,l,c,s,f=ee(function(n,t){return n=i(n,t),[n[0]*h+l,c-n[1]*h]}),h=150,g=480,p=250,v=0,d=0,m=0,M=0,x=0,b=Uo,_=y,w=null,S=null;return t.stream=function(n){return s&&(s.valid=!1),s=le(b(a,f(_(n)))),s.valid=!0,s},t.clipAngle=function(n){return arguments.length?(b=null==n?(w=n,Uo):It((w=+n)*Oa),u()):w},t.clipExtent=function(n){return arguments.length?(S=n,_=n?Zt(n[0][0],n[0][1],n[1][0],n[1][1]):y,u()):S},t.scale=function(n){return arguments.length?(h=+n,r()):h},t.translate=function(n){return arguments.length?(g=+n[0],p=+n[1],r()):[g,p]},t.center=function(n){return arguments.length?(v=n[0]%360*Oa,d=n[1]%360*Oa,r()):[v*Ia,d*Ia]},t.rotate=function(n){return arguments.length?(m=n[0]%360*Oa,M=n[1]%360*Oa,x=n.length>2?n[2]%360*Oa:0,r()):[m*Ia,M*Ia,x*Ia]},oa.rebind(t,f,"precision"),function(){return i=n.apply(this,arguments),t.invert=i.invert&&e,r()}}function le(n){return ie(n,function(t,e){n.point(t*Oa,e*Oa)})}function ce(n,t){return[n,t]}function se(n,t){return[n>ja?n-Ua:-ja>n?n+Ua:n,t]}function fe(n,t,e){return n?t||e?Ct(ge(n),pe(t,e)):ge(n):t||e?pe(t,e):se}function he(n){return function(t,e){return t+=n,[t>ja?t-Ua:-ja>t?t+Ua:t,e]}}function ge(n){var t=he(n);return t.invert=he(-n),t}function pe(n,t){function e(n,t){var e=Math.cos(t),o=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),s=c*r+o*u;return[Math.atan2(l*i-s*a,o*r-c*u),tn(s*i+l*a)]}var r=Math.cos(n),u=Math.sin(n),i=Math.cos(t),a=Math.sin(t);return e.invert=function(n,t){var e=Math.cos(t),o=Math.cos(n)*e,l=Math.sin(n)*e,c=Math.sin(t),s=c*i-l*a;return[Math.atan2(l*i+c*a,o*r+s*u),tn(s*r-o*u)]},e}function ve(n,t){var e=Math.cos(n),r=Math.sin(n);return function(u,i,a,o){var l=a*t;null!=u?(u=de(e,u),i=de(e,i),(a>0?i>u:u>i)&&(u+=a*Ua)):(u=n+a*Ua,i=n-.5*l);for(var c,s=u;a>0?s>i:i>s;s-=l)o.point((c=_t([e,-r*Math.cos(s),-r*Math.sin(s)]))[0],c[1])}}function de(n,t){var e=dt(t);e[0]-=n,bt(e);var r=nn(-e[1]);return((-e[2]<0?-r:r)+2*Math.PI-Da)%(2*Math.PI)}function me(n,t,e){var r=oa.range(n,t-Da,e).concat(t);return function(n){return r.map(function(t){return[n,t]})}}function ye(n,t,e){var r=oa.range(n,t-Da,e).concat(t);return function(n){return r.map(function(t){return[t,n]})}}function Me(n){return n.source}function xe(n){return n.target}function be(n,t,e,r){var u=Math.cos(t),i=Math.sin(t),a=Math.cos(r),o=Math.sin(r),l=u*Math.cos(n),c=u*Math.sin(n),s=a*Math.cos(e),f=a*Math.sin(e),h=2*Math.asin(Math.sqrt(an(r-t)+u*a*an(e-n))),g=1/Math.sin(h),p=h?function(n){var t=Math.sin(n*=h)*g,e=Math.sin(h-n)*g,r=e*l+t*s,u=e*c+t*f,a=e*i+t*o;return[Math.atan2(u,r)*Ia,Math.atan2(a,Math.sqrt(r*r+u*u))*Ia]}:function(){return[n*Ia,t*Ia]};return p.distance=h,p}function _e(){function n(n,u){var i=Math.sin(u*=Oa),a=Math.cos(u),o=Ma((n*=Oa)-t),l=Math.cos(o);Wo+=Math.atan2(Math.sqrt((o=a*Math.sin(o))*o+(o=r*i-e*a*l)*o),e*i+r*a*l),t=n,e=i,r=a}var t,e,r;Jo.point=function(u,i){t=u*Oa,e=Math.sin(i*=Oa),r=Math.cos(i),Jo.point=n},Jo.lineEnd=function(){Jo.point=Jo.lineEnd=b}}function we(n,t){function e(t,e){var r=Math.cos(t),u=Math.cos(e),i=n(r*u);return[i*u*Math.sin(t),i*Math.sin(e)]}return e.invert=function(n,e){var r=Math.sqrt(n*n+e*e),u=t(r),i=Math.sin(u),a=Math.cos(u);return[Math.atan2(n*i,r*a),Math.asin(r&&e*i/r)]},e}function Se(n,t){function e(n,t){a>0?-Ha+Da>t&&(t=-Ha+Da):t>Ha-Da&&(t=Ha-Da);var e=a/Math.pow(u(t),i);return[e*Math.sin(i*n),a-e*Math.cos(i*n)]}var r=Math.cos(n),u=function(n){return Math.tan(ja/4+n/2)},i=n===t?Math.sin(n):Math.log(r/Math.cos(t))/Math.log(u(t)/u(n)),a=r*Math.pow(u(n),i)/i;return i?(e.invert=function(n,t){var e=a-t,r=K(i)*Math.sqrt(n*n+e*e);return[Math.atan2(n,e)/i,2*Math.atan(Math.pow(a/r,1/i))-Ha]},e):Ne}function ke(n,t){function e(n,t){var e=i-t;return[e*Math.sin(u*n),i-e*Math.cos(u*n)]}var r=Math.cos(n),u=n===t?Math.sin(n):(r-Math.cos(t))/(t-n),i=r/u+n;return Ma(u)<Da?ce:(e.invert=function(n,t){var e=i-t;return[Math.atan2(n,e)/u,i-K(u)*Math.sqrt(n*n+e*e)]},e)}function Ne(n,t){return[n,Math.log(Math.tan(ja/4+t/2))]}function Ee(n){var t,e=ae(n),r=e.scale,u=e.translate,i=e.clipExtent;return e.scale=function(){var n=r.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.translate=function(){var n=u.apply(e,arguments);return n===e?t?e.clipExtent(null):e:n},e.clipExtent=function(n){var a=i.apply(e,arguments);if(a===e){if(t=null==n){var o=ja*r(),l=u();i([[l[0]-o,l[1]-o],[l[0]+o,l[1]+o]])}}else t&&(a=null);return a},e.clipExtent(null)}function Ae(n,t){return[Math.log(Math.tan(ja/4+t/2)),-n]}function Ce(n){return n[0]}function ze(n){return n[1]}function Le(n){for(var t=n.length,e=[0,1],r=2,u=2;t>u;u++){for(;r>1&&Q(n[e[r-2]],n[e[r-1]],n[u])<=0;)--r;e[r++]=u}return e.slice(0,r)}function qe(n,t){return n[0]-t[0]||n[1]-t[1]}function Te(n,t,e){return(e[0]-t[0])*(n[1]-t[1])<(e[1]-t[1])*(n[0]-t[0])}function Re(n,t,e,r){var u=n[0],i=e[0],a=t[0]-u,o=r[0]-i,l=n[1],c=e[1],s=t[1]-l,f=r[1]-c,h=(o*(l-c)-f*(u-i))/(f*a-o*s);return[u+h*a,l+h*s]}function De(n){var t=n[0],e=n[n.length-1];return!(t[0]-e[0]||t[1]-e[1])}function Pe(){rr(this),this.edge=this.site=this.circle=null}function je(n){var t=ll.pop()||new Pe;return t.site=n,t}function Ue(n){Be(n),il.remove(n),ll.push(n),rr(n)}function Fe(n){var t=n.circle,e=t.x,r=t.cy,u={x:e,y:r},i=n.P,a=n.N,o=[n];Ue(n);for(var l=i;l.circle&&Ma(e-l.circle.x)<Da&&Ma(r-l.circle.cy)<Da;)i=l.P,o.unshift(l),Ue(l),l=i;o.unshift(l),Be(l);for(var c=a;c.circle&&Ma(e-c.circle.x)<Da&&Ma(r-c.circle.cy)<Da;)a=c.N,o.push(c),Ue(c),c=a;o.push(c),Be(c);var s,f=o.length;for(s=1;f>s;++s)c=o[s],l=o[s-1],nr(c.edge,l.site,c.site,u);l=o[0],c=o[f-1],c.edge=Ke(l.site,c.site,null,u),$e(l),$e(c)}function He(n){for(var t,e,r,u,i=n.x,a=n.y,o=il._;o;)if(r=Oe(o,a)-i,r>Da)o=o.L;else{if(u=i-Ie(o,a),!(u>Da)){r>-Da?(t=o.P,e=o):u>-Da?(t=o,e=o.N):t=e=o;break}if(!o.R){t=o;break}o=o.R}var l=je(n);if(il.insert(t,l),t||e){if(t===e)return Be(t),e=je(t.site),il.insert(l,e),l.edge=e.edge=Ke(t.site,l.site),$e(t),void $e(e);if(!e)return void(l.edge=Ke(t.site,l.site));Be(t),Be(e);var c=t.site,s=c.x,f=c.y,h=n.x-s,g=n.y-f,p=e.site,v=p.x-s,d=p.y-f,m=2*(h*d-g*v),y=h*h+g*g,M=v*v+d*d,x={x:(d*y-g*M)/m+s,y:(h*M-v*y)/m+f};nr(e.edge,c,p,x),l.edge=Ke(c,n,null,x),e.edge=Ke(n,p,null,x),$e(t),$e(e)}}function Oe(n,t){var e=n.site,r=e.x,u=e.y,i=u-t;if(!i)return r;var a=n.P;if(!a)return-(1/0);e=a.site;var o=e.x,l=e.y,c=l-t;if(!c)return o;var s=o-r,f=1/i-1/c,h=s/c;return f?(-h+Math.sqrt(h*h-2*f*(s*s/(-2*c)-l+c/2+u-i/2)))/f+r:(r+o)/2}function Ie(n,t){var e=n.N;if(e)return Oe(e,t);var r=n.site;return r.y===t?r.x:1/0}function Ye(n){this.site=n,this.edges=[]}function Ze(n){for(var t,e,r,u,i,a,o,l,c,s,f=n[0][0],h=n[1][0],g=n[0][1],p=n[1][1],v=ul,d=v.length;d--;)if(i=v[d],i&&i.prepare())for(o=i.edges,l=o.length,a=0;l>a;)s=o[a].end(),r=s.x,u=s.y,c=o[++a%l].start(),t=c.x,e=c.y,(Ma(r-t)>Da||Ma(u-e)>Da)&&(o.splice(a,0,new tr(Qe(i.site,s,Ma(r-f)<Da&&p-u>Da?{x:f,y:Ma(t-f)<Da?e:p}:Ma(u-p)<Da&&h-r>Da?{x:Ma(e-p)<Da?t:h,y:p}:Ma(r-h)<Da&&u-g>Da?{x:h,y:Ma(t-h)<Da?e:g}:Ma(u-g)<Da&&r-f>Da?{x:Ma(e-g)<Da?t:f,y:g}:null),i.site,null)),++l)}function Ve(n,t){return t.angle-n.angle}function Xe(){rr(this),this.x=this.y=this.arc=this.site=this.cy=null}function $e(n){var t=n.P,e=n.N;if(t&&e){var r=t.site,u=n.site,i=e.site;if(r!==i){var a=u.x,o=u.y,l=r.x-a,c=r.y-o,s=i.x-a,f=i.y-o,h=2*(l*f-c*s);if(!(h>=-Pa)){var g=l*l+c*c,p=s*s+f*f,v=(f*g-c*p)/h,d=(l*p-s*g)/h,f=d+o,m=cl.pop()||new Xe;m.arc=n,m.site=u,m.x=v+a,m.y=f+Math.sqrt(v*v+d*d),m.cy=f,n.circle=m;for(var y=null,M=ol._;M;)if(m.y<M.y||m.y===M.y&&m.x<=M.x){if(!M.L){y=M.P;break}M=M.L}else{if(!M.R){y=M;break}M=M.R}ol.insert(y,m),y||(al=m)}}}}function Be(n){var t=n.circle;t&&(t.P||(al=t.N),ol.remove(t),cl.push(t),rr(t),n.circle=null)}function We(n){for(var t,e=rl,r=Yt(n[0][0],n[0][1],n[1][0],n[1][1]),u=e.length;u--;)t=e[u],(!Je(t,n)||!r(t)||Ma(t.a.x-t.b.x)<Da&&Ma(t.a.y-t.b.y)<Da)&&(t.a=t.b=null,e.splice(u,1))}function Je(n,t){var e=n.b;if(e)return!0;var r,u,i=n.a,a=t[0][0],o=t[1][0],l=t[0][1],c=t[1][1],s=n.l,f=n.r,h=s.x,g=s.y,p=f.x,v=f.y,d=(h+p)/2,m=(g+v)/2;if(v===g){if(a>d||d>=o)return;if(h>p){if(i){if(i.y>=c)return}else i={x:d,y:l};e={x:d,y:c}}else{if(i){if(i.y<l)return}else i={x:d,y:c};e={x:d,y:l}}}else if(r=(h-p)/(v-g),u=m-r*d,-1>r||r>1)if(h>p){if(i){if(i.y>=c)return}else i={x:(l-u)/r,y:l};e={x:(c-u)/r,y:c}}else{if(i){if(i.y<l)return}else i={x:(c-u)/r,y:c};e={x:(l-u)/r,y:l}}else if(v>g){if(i){if(i.x>=o)return}else i={x:a,y:r*a+u};e={x:o,y:r*o+u}}else{if(i){if(i.x<a)return}else i={x:o,y:r*o+u};e={x:a,y:r*a+u}}return n.a=i,n.b=e,!0}function Ge(n,t){this.l=n,this.r=t,this.a=this.b=null}function Ke(n,t,e,r){var u=new Ge(n,t);return rl.push(u),e&&nr(u,n,t,e),r&&nr(u,t,n,r),ul[n.i].edges.push(new tr(u,n,t)),ul[t.i].edges.push(new tr(u,t,n)),u}function Qe(n,t,e){var r=new Ge(n,null);return r.a=t,r.b=e,rl.push(r),r}function nr(n,t,e,r){n.a||n.b?n.l===e?n.b=r:n.a=r:(n.a=r,n.l=t,n.r=e)}function tr(n,t,e){var r=n.a,u=n.b;this.edge=n,this.site=t,this.angle=e?Math.atan2(e.y-t.y,e.x-t.x):n.l===t?Math.atan2(u.x-r.x,r.y-u.y):Math.atan2(r.x-u.x,u.y-r.y)}function er(){this._=null}function rr(n){n.U=n.C=n.L=n.R=n.P=n.N=null}function ur(n,t){var e=t,r=t.R,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.R=r.L,e.R&&(e.R.U=e),r.L=e}function ir(n,t){var e=t,r=t.L,u=e.U;u?u.L===e?u.L=r:u.R=r:n._=r,r.U=u,e.U=r,e.L=r.R,e.L&&(e.L.U=e),r.R=e}function ar(n){for(;n.L;)n=n.L;return n}function or(n,t){var e,r,u,i=n.sort(lr).pop();for(rl=[],ul=new Array(n.length),il=new er,ol=new er;;)if(u=al,i&&(!u||i.y<u.y||i.y===u.y&&i.x<u.x))(i.x!==e||i.y!==r)&&(ul[i.i]=new Ye(i),He(i),e=i.x,r=i.y),i=n.pop();else{if(!u)break;Fe(u.arc)}t&&(We(t),Ze(t));var a={cells:ul,edges:rl};return il=ol=rl=ul=null,a}function lr(n,t){return t.y-n.y||t.x-n.x}function cr(n,t,e){return(n.x-e.x)*(t.y-n.y)-(n.x-t.x)*(e.y-n.y)}function sr(n){return n.x}function fr(n){return n.y}function hr(){return{leaf:!0,nodes:[],point:null,x:null,y:null}}function gr(n,t,e,r,u,i){if(!n(t,e,r,u,i)){var a=.5*(e+u),o=.5*(r+i),l=t.nodes;l[0]&&gr(n,l[0],e,r,a,o),l[1]&&gr(n,l[1],a,r,u,o),l[2]&&gr(n,l[2],e,o,a,i),l[3]&&gr(n,l[3],a,o,u,i)}}function pr(n,t,e,r,u,i,a){var o,l=1/0;return function c(n,s,f,h,g){if(!(s>i||f>a||r>h||u>g)){if(p=n.point){var p,v=t-n.x,d=e-n.y,m=v*v+d*d;if(l>m){var y=Math.sqrt(l=m);r=t-y,u=e-y,i=t+y,a=e+y,o=p}}for(var M=n.nodes,x=.5*(s+h),b=.5*(f+g),_=t>=x,w=e>=b,S=w<<1|_,k=S+4;k>S;++S)if(n=M[3&S])switch(3&S){case 0:c(n,s,f,x,b);break;case 1:c(n,x,f,h,b);break;case 2:c(n,s,b,x,g);break;case 3:c(n,x,b,h,g)}}}(n,r,u,i,a),o}function vr(n,t){n=oa.rgb(n),t=oa.rgb(t);var e=n.r,r=n.g,u=n.b,i=t.r-e,a=t.g-r,o=t.b-u;return function(n){return"#"+bn(Math.round(e+i*n))+bn(Math.round(r+a*n))+bn(Math.round(u+o*n))}}function dr(n,t){var e,r={},u={};for(e in n)e in t?r[e]=Mr(n[e],t[e]):u[e]=n[e];for(e in t)e in n||(u[e]=t[e]);return function(n){for(e in r)u[e]=r[e](n);return u}}function mr(n,t){return n=+n,t=+t,function(e){return n*(1-e)+t*e}}function yr(n,t){var e,r,u,i=fl.lastIndex=hl.lastIndex=0,a=-1,o=[],l=[];for(n+="",t+="";(e=fl.exec(n))&&(r=hl.exec(t));)(u=r.index)>i&&(u=t.slice(i,u),o[a]?o[a]+=u:o[++a]=u),(e=e[0])===(r=r[0])?o[a]?o[a]+=r:o[++a]=r:(o[++a]=null,l.push({i:a,x:mr(e,r)})),i=hl.lastIndex;return i<t.length&&(u=t.slice(i),o[a]?o[a]+=u:o[++a]=u),o.length<2?l[0]?(t=l[0].x,function(n){return t(n)+""}):function(){return t}:(t=l.length,function(n){for(var e,r=0;t>r;++r)o[(e=l[r]).i]=e.x(n);return o.join("")})}function Mr(n,t){for(var e,r=oa.interpolators.length;--r>=0&&!(e=oa.interpolators[r](n,t)););return e}function xr(n,t){var e,r=[],u=[],i=n.length,a=t.length,o=Math.min(n.length,t.length);for(e=0;o>e;++e)r.push(Mr(n[e],t[e]));for(;i>e;++e)u[e]=n[e];for(;a>e;++e)u[e]=t[e];return function(n){for(e=0;o>e;++e)u[e]=r[e](n);return u}}function br(n){return function(t){return 0>=t?0:t>=1?1:n(t)}}function _r(n){return function(t){return 1-n(1-t)}}function wr(n){return function(t){return.5*(.5>t?n(2*t):2-n(2-2*t))}}function Sr(n){return n*n}function kr(n){return n*n*n}function Nr(n){if(0>=n)return 0;if(n>=1)return 1;var t=n*n,e=t*n;return 4*(.5>n?e:3*(n-t)+e-.75)}function Er(n){return function(t){return Math.pow(t,n)}}function Ar(n){return 1-Math.cos(n*Ha)}function Cr(n){return Math.pow(2,10*(n-1))}function zr(n){return 1-Math.sqrt(1-n*n)}function Lr(n,t){var e;return arguments.length<2&&(t=.45),arguments.length?e=t/Ua*Math.asin(1/n):(n=1,e=t/4),function(r){return 1+n*Math.pow(2,-10*r)*Math.sin((r-e)*Ua/t)}}function qr(n){return n||(n=1.70158),function(t){return t*t*((n+1)*t-n)}}function Tr(n){return 1/2.75>n?7.5625*n*n:2/2.75>n?7.5625*(n-=1.5/2.75)*n+.75:2.5/2.75>n?7.5625*(n-=2.25/2.75)*n+.9375:7.5625*(n-=2.625/2.75)*n+.984375}function Rr(n,t){n=oa.hcl(n),t=oa.hcl(t);var e=n.h,r=n.c,u=n.l,i=t.h-e,a=t.c-r,o=t.l-u;return isNaN(a)&&(a=0,r=isNaN(r)?t.c:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return fn(e+i*n,r+a*n,u+o*n)+""}}function Dr(n,t){n=oa.hsl(n),t=oa.hsl(t);var e=n.h,r=n.s,u=n.l,i=t.h-e,a=t.s-r,o=t.l-u;return isNaN(a)&&(a=0,r=isNaN(r)?t.s:r),isNaN(i)?(i=0,e=isNaN(e)?t.h:e):i>180?i-=360:-180>i&&(i+=360),function(n){return cn(e+i*n,r+a*n,u+o*n)+""}}function Pr(n,t){n=oa.lab(n),t=oa.lab(t);var e=n.l,r=n.a,u=n.b,i=t.l-e,a=t.a-r,o=t.b-u;return function(n){return gn(e+i*n,r+a*n,u+o*n)+""}}function jr(n,t){return t-=n,function(e){return Math.round(n+t*e)}}function Ur(n){var t=[n.a,n.b],e=[n.c,n.d],r=Hr(t),u=Fr(t,e),i=Hr(Or(e,t,-u))||0;t[0]*e[1]<e[0]*t[1]&&(t[0]*=-1,t[1]*=-1,r*=-1,u*=-1),this.rotate=(r?Math.atan2(t[1],t[0]):Math.atan2(-e[0],e[1]))*Ia,this.translate=[n.e,n.f],this.scale=[r,i],this.skew=i?Math.atan2(u,i)*Ia:0}function Fr(n,t){return n[0]*t[0]+n[1]*t[1]}function Hr(n){var t=Math.sqrt(Fr(n,n));return t&&(n[0]/=t,n[1]/=t),t}function Or(n,t,e){return n[0]+=e*t[0],n[1]+=e*t[1],n}function Ir(n){return n.length?n.pop()+",":""}function Yr(n,t,e,r){if(n[0]!==t[0]||n[1]!==t[1]){var u=e.push("translate(",null,",",null,")");r.push({i:u-4,x:mr(n[0],t[0])},{i:u-2,x:mr(n[1],t[1])})}else(t[0]||t[1])&&e.push("translate("+t+")")}function Zr(n,t,e,r){n!==t?(n-t>180?t+=360:t-n>180&&(n+=360),r.push({i:e.push(Ir(e)+"rotate(",null,")")-2,x:mr(n,t)})):t&&e.push(Ir(e)+"rotate("+t+")")}function Vr(n,t,e,r){n!==t?r.push({i:e.push(Ir(e)+"skewX(",null,")")-2,x:mr(n,t)}):t&&e.push(Ir(e)+"skewX("+t+")")}function Xr(n,t,e,r){if(n[0]!==t[0]||n[1]!==t[1]){var u=e.push(Ir(e)+"scale(",null,",",null,")");r.push({i:u-4,x:mr(n[0],t[0])},{i:u-2,x:mr(n[1],t[1])})}else(1!==t[0]||1!==t[1])&&e.push(Ir(e)+"scale("+t+")")}function $r(n,t){var e=[],r=[];return n=oa.transform(n),t=oa.transform(t),Yr(n.translate,t.translate,e,r),Zr(n.rotate,t.rotate,e,r),Vr(n.skew,t.skew,e,r),Xr(n.scale,t.scale,e,r),n=t=null,function(n){for(var t,u=-1,i=r.length;++u<i;)e[(t=r[u]).i]=t.x(n);return e.join("")}}function Br(n,t){return t=(t-=n=+n)||1/t,function(e){return(e-n)/t}}function Wr(n,t){return t=(t-=n=+n)||1/t,function(e){return Math.max(0,Math.min(1,(e-n)/t))}}function Jr(n){for(var t=n.source,e=n.target,r=Kr(t,e),u=[t];t!==r;)t=t.parent,u.push(t);for(var i=u.length;e!==r;)u.splice(i,0,e),e=e.parent;return u}function Gr(n){for(var t=[],e=n.parent;null!=e;)t.push(n),n=e,e=e.parent;return t.push(n),t}function Kr(n,t){if(n===t)return n;for(var e=Gr(n),r=Gr(t),u=e.pop(),i=r.pop(),a=null;u===i;)a=u,u=e.pop(),i=r.pop();return a}function Qr(n){n.fixed|=2}function nu(n){n.fixed&=-7}function tu(n){n.fixed|=4,n.px=n.x,n.py=n.y}function eu(n){n.fixed&=-5}function ru(n,t,e){var r=0,u=0;if(n.charge=0,!n.leaf)for(var i,a=n.nodes,o=a.length,l=-1;++l<o;)i=a[l],null!=i&&(ru(i,t,e),n.charge+=i.charge,r+=i.charge*i.cx,u+=i.charge*i.cy);if(n.point){n.leaf||(n.point.x+=Math.random()-.5,n.point.y+=Math.random()-.5);var c=t*e[n.point.index];n.charge+=n.pointCharge=c,r+=c*n.point.x,u+=c*n.point.y}n.cx=r/n.charge,n.cy=u/n.charge}function uu(n,t){return oa.rebind(n,t,"sort","children","value"),n.nodes=n,n.links=su,n}function iu(n,t){for(var e=[n];null!=(n=e.pop());)if(t(n),(u=n.children)&&(r=u.length))for(var r,u;--r>=0;)e.push(u[r])}function au(n,t){for(var e=[n],r=[];null!=(n=e.pop());)if(r.push(n),(i=n.children)&&(u=i.length))for(var u,i,a=-1;++a<u;)e.push(i[a]);for(;null!=(n=r.pop());)t(n)}function ou(n){return n.children}function lu(n){return n.value}function cu(n,t){return t.value-n.value}function su(n){return oa.merge(n.map(function(n){return(n.children||[]).map(function(t){return{source:n,target:t}})}))}function fu(n){return n.x}function hu(n){return n.y}function gu(n,t,e){n.y0=t,n.y=e}function pu(n){return oa.range(n.length)}function vu(n){for(var t=-1,e=n[0].length,r=[];++t<e;)r[t]=0;return r}function du(n){for(var t,e=1,r=0,u=n[0][1],i=n.length;i>e;++e)(t=n[e][1])>u&&(r=e,u=t);return r}function mu(n){return n.reduce(yu,0)}function yu(n,t){return n+t[1]}function Mu(n,t){return xu(n,Math.ceil(Math.log(t.length)/Math.LN2+1))}function xu(n,t){for(var e=-1,r=+n[0],u=(n[1]-r)/t,i=[];++e<=t;)i[e]=u*e+r;return i}function bu(n){return[oa.min(n),oa.max(n)]}function _u(n,t){return n.value-t.value}function wu(n,t){var e=n._pack_next;n._pack_next=t,t._pack_prev=n,t._pack_next=e,e._pack_prev=t}function Su(n,t){n._pack_next=t,t._pack_prev=n}function ku(n,t){var e=t.x-n.x,r=t.y-n.y,u=n.r+t.r;return.999*u*u>e*e+r*r}function Nu(n){function t(n){s=Math.min(n.x-n.r,s),f=Math.max(n.x+n.r,f),h=Math.min(n.y-n.r,h),g=Math.max(n.y+n.r,g)}if((e=n.children)&&(c=e.length)){var e,r,u,i,a,o,l,c,s=1/0,f=-(1/0),h=1/0,g=-(1/0);if(e.forEach(Eu),r=e[0],r.x=-r.r,r.y=0,t(r),c>1&&(u=e[1],u.x=u.r,u.y=0,t(u),c>2))for(i=e[2],zu(r,u,i),t(i),wu(r,i),r._pack_prev=i,wu(i,u),u=r._pack_next,a=3;c>a;a++){zu(r,u,i=e[a]);var p=0,v=1,d=1;for(o=u._pack_next;o!==u;o=o._pack_next,v++)if(ku(o,i)){p=1;break}if(1==p)for(l=r._pack_prev;l!==o._pack_prev&&!ku(l,i);l=l._pack_prev,d++);p?(d>v||v==d&&u.r<r.r?Su(r,u=o):Su(r=l,u),a--):(wu(r,i),u=i,t(i))}var m=(s+f)/2,y=(h+g)/2,M=0;for(a=0;c>a;a++)i=e[a],i.x-=m,i.y-=y,M=Math.max(M,i.r+Math.sqrt(i.x*i.x+i.y*i.y));n.r=M,e.forEach(Au)}}function Eu(n){n._pack_next=n._pack_prev=n}function Au(n){delete n._pack_next,delete n._pack_prev}function Cu(n,t,e,r){var u=n.children;if(n.x=t+=r*n.x,n.y=e+=r*n.y,n.r*=r,u)for(var i=-1,a=u.length;++i<a;)Cu(u[i],t,e,r)}function zu(n,t,e){var r=n.r+e.r,u=t.x-n.x,i=t.y-n.y;if(r&&(u||i)){var a=t.r+e.r,o=u*u+i*i;a*=a,r*=r;var l=.5+(r-a)/(2*o),c=Math.sqrt(Math.max(0,2*a*(r+o)-(r-=o)*r-a*a))/(2*o);e.x=n.x+l*u+c*i,e.y=n.y+l*i-c*u}else e.x=n.x+r,e.y=n.y}function Lu(n,t){return n.parent==t.parent?1:2}function qu(n){var t=n.children;return t.length?t[0]:n.t}function Tu(n){var t,e=n.children;return(t=e.length)?e[t-1]:n.t}function Ru(n,t,e){var r=e/(t.i-n.i);t.c-=r,t.s+=e,n.c+=r,t.z+=e,t.m+=e}function Du(n){for(var t,e=0,r=0,u=n.children,i=u.length;--i>=0;)t=u[i],t.z+=e,t.m+=e,e+=t.s+(r+=t.c)}function Pu(n,t,e){return n.a.parent===t.parent?n.a:e}function ju(n){return 1+oa.max(n,function(n){return n.y})}function Uu(n){return n.reduce(function(n,t){return n+t.x},0)/n.length}function Fu(n){var t=n.children;return t&&t.length?Fu(t[0]):n}function Hu(n){var t,e=n.children;return e&&(t=e.length)?Hu(e[t-1]):n}function Ou(n){return{x:n.x,y:n.y,dx:n.dx,dy:n.dy}}function Iu(n,t){var e=n.x+t[3],r=n.y+t[0],u=n.dx-t[1]-t[3],i=n.dy-t[0]-t[2];return 0>u&&(e+=u/2,u=0),0>i&&(r+=i/2,i=0),{x:e,y:r,dx:u,dy:i}}function Yu(n){var t=n[0],e=n[n.length-1];return e>t?[t,e]:[e,t]}function Zu(n){return n.rangeExtent?n.rangeExtent():Yu(n.range())}function Vu(n,t,e,r){var u=e(n[0],n[1]),i=r(t[0],t[1]);return function(n){return i(u(n))}}function Xu(n,t){var e,r=0,u=n.length-1,i=n[r],a=n[u];return i>a&&(e=r,r=u,u=e,e=i,i=a,a=e),n[r]=t.floor(i),n[u]=t.ceil(a),n}function $u(n){return n?{floor:function(t){return Math.floor(t/n)*n},ceil:function(t){return Math.ceil(t/n)*n}}:wl}function Bu(n,t,e,r){var u=[],i=[],a=0,o=Math.min(n.length,t.length)-1;for(n[o]<n[0]&&(n=n.slice().reverse(),t=t.slice().reverse());++a<=o;)u.push(e(n[a-1],n[a])),i.push(r(t[a-1],t[a]));return function(t){var e=oa.bisect(n,t,1,o)-1;return i[e](u[e](t))}}function Wu(n,t,e,r){function u(){var u=Math.min(n.length,t.length)>2?Bu:Vu,l=r?Wr:Br;return a=u(n,t,l,e),o=u(t,n,l,Mr),i}function i(n){return a(n)}var a,o;return i.invert=function(n){return o(n)},i.domain=function(t){return arguments.length?(n=t.map(Number),u()):n},i.range=function(n){return arguments.length?(t=n,u()):t},i.rangeRound=function(n){return i.range(n).interpolate(jr)},i.clamp=function(n){return arguments.length?(r=n,u()):r},i.interpolate=function(n){return arguments.length?(e=n,u()):e},i.ticks=function(t){return Qu(n,t)},i.tickFormat=function(t,e){return ni(n,t,e)},i.nice=function(t){return Gu(n,t),u()},i.copy=function(){return Wu(n,t,e,r)},u()}function Ju(n,t){return oa.rebind(n,t,"range","rangeRound","interpolate","clamp")}function Gu(n,t){return Xu(n,$u(Ku(n,t)[2])),Xu(n,$u(Ku(n,t)[2])),n}function Ku(n,t){null==t&&(t=10);var e=Yu(n),r=e[1]-e[0],u=Math.pow(10,Math.floor(Math.log(r/t)/Math.LN10)),i=t/r*u;return.15>=i?u*=10:.35>=i?u*=5:.75>=i&&(u*=2),e[0]=Math.ceil(e[0]/u)*u,e[1]=Math.floor(e[1]/u)*u+.5*u,e[2]=u,e}function Qu(n,t){return oa.range.apply(oa,Ku(n,t))}function ni(n,t,e){var r=Ku(n,t);if(e){var u=so.exec(e);if(u.shift(),"s"===u[8]){var i=oa.formatPrefix(Math.max(Ma(r[0]),Ma(r[1])));return u[7]||(u[7]="."+ti(i.scale(r[2]))),u[8]="f",e=oa.format(u.join("")),function(n){return e(i.scale(n))+i.symbol}}u[7]||(u[7]="."+ei(u[8],r)),e=u.join("")}else e=",."+ti(r[2])+"f";return oa.format(e)}function ti(n){return-Math.floor(Math.log(n)/Math.LN10+.01)}function ei(n,t){var e=ti(t[2]);return n in Sl?Math.abs(e-ti(Math.max(Ma(t[0]),Ma(t[1]))))+ +("e"!==n):e-2*("%"===n)}function ri(n,t,e,r){function u(n){return(e?Math.log(0>n?0:n):-Math.log(n>0?0:-n))/Math.log(t)}function i(n){return e?Math.pow(t,n):-Math.pow(t,-n)}function a(t){return n(u(t))}return a.invert=function(t){return i(n.invert(t))},a.domain=function(t){return arguments.length?(e=t[0]>=0,n.domain((r=t.map(Number)).map(u)),a):r},a.base=function(e){return arguments.length?(t=+e,n.domain(r.map(u)),a):t},a.nice=function(){var t=Xu(r.map(u),e?Math:Nl);return n.domain(t),r=t.map(i),a},a.ticks=function(){var n=Yu(r),a=[],o=n[0],l=n[1],c=Math.floor(u(o)),s=Math.ceil(u(l)),f=t%1?2:t;if(isFinite(s-c)){if(e){for(;s>c;c++)for(var h=1;f>h;h++)a.push(i(c)*h);a.push(i(c))}else for(a.push(i(c));c++<s;)for(var h=f-1;h>0;h--)a.push(i(c)*h);for(c=0;a[c]<o;c++);for(s=a.length;a[s-1]>l;s--);a=a.slice(c,s)}return a},a.tickFormat=function(n,e){if(!arguments.length)return kl;arguments.length<2?e=kl:"function"!=typeof e&&(e=oa.format(e));var r=Math.max(1,t*n/a.ticks().length);return function(n){var a=n/i(Math.round(u(n)));return t-.5>a*t&&(a*=t),r>=a?e(n):""}},a.copy=function(){return ri(n.copy(),t,e,r)},Ju(a,n)}function ui(n,t,e){function r(t){return n(u(t))}var u=ii(t),i=ii(1/t);return r.invert=function(t){return i(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain((e=t.map(Number)).map(u)),r):e},r.ticks=function(n){return Qu(e,n)},r.tickFormat=function(n,t){return ni(e,n,t)},r.nice=function(n){return r.domain(Gu(e,n))},r.exponent=function(a){return arguments.length?(u=ii(t=a),i=ii(1/t),n.domain(e.map(u)),r):t},r.copy=function(){return ui(n.copy(),t,e)},Ju(r,n)}function ii(n){return function(t){return 0>t?-Math.pow(-t,n):Math.pow(t,n)}}function ai(n,t){function e(e){return i[((u.get(e)||("range"===t.t?u.set(e,n.push(e)):NaN))-1)%i.length]}function r(t,e){return oa.range(n.length).map(function(n){return t+e*n})}var u,i,a;return e.domain=function(r){if(!arguments.length)return n;n=[],u=new c;for(var i,a=-1,o=r.length;++a<o;)u.has(i=r[a])||u.set(i,n.push(i));return e[t.t].apply(e,t.a)},e.range=function(n){return arguments.length?(i=n,a=0,t={t:"range",a:arguments},e):i},e.rangePoints=function(u,o){arguments.length<2&&(o=0);var l=u[0],c=u[1],s=n.length<2?(l=(l+c)/2,0):(c-l)/(n.length-1+o);return i=r(l+s*o/2,s),a=0,t={t:"rangePoints",a:arguments},e},e.rangeRoundPoints=function(u,o){arguments.length<2&&(o=0);var l=u[0],c=u[1],s=n.length<2?(l=c=Math.round((l+c)/2),0):(c-l)/(n.length-1+o)|0;return i=r(l+Math.round(s*o/2+(c-l-(n.length-1+o)*s)/2),s),a=0,t={t:"rangeRoundPoints",a:arguments},e},e.rangeBands=function(u,o,l){arguments.length<2&&(o=0),arguments.length<3&&(l=o);var c=u[1]<u[0],s=u[c-0],f=u[1-c],h=(f-s)/(n.length-o+2*l);return i=r(s+h*l,h),c&&i.reverse(),a=h*(1-o),t={t:"rangeBands",a:arguments},e},e.rangeRoundBands=function(u,o,l){arguments.length<2&&(o=0),arguments.length<3&&(l=o);var c=u[1]<u[0],s=u[c-0],f=u[1-c],h=Math.floor((f-s)/(n.length-o+2*l));return i=r(s+Math.round((f-s-(n.length-o)*h)/2),h),c&&i.reverse(),a=Math.round(h*(1-o)),t={t:"rangeRoundBands",a:arguments},e},e.rangeBand=function(){return a},e.rangeExtent=function(){return Yu(t.a[0])},e.copy=function(){return ai(n,t)},e.domain(n)}function oi(n,t){function i(){var e=0,r=t.length;for(o=[];++e<r;)o[e-1]=oa.quantile(n,e/r);return a}function a(n){return isNaN(n=+n)?void 0:t[oa.bisect(o,n)]}var o;return a.domain=function(t){return arguments.length?(n=t.map(r).filter(u).sort(e),i()):n},a.range=function(n){return arguments.length?(t=n,i()):t},a.quantiles=function(){return o},a.invertExtent=function(e){return e=t.indexOf(e),0>e?[NaN,NaN]:[e>0?o[e-1]:n[0],e<o.length?o[e]:n[n.length-1]]},a.copy=function(){return oi(n,t)},i()}function li(n,t,e){function r(t){return e[Math.max(0,Math.min(a,Math.floor(i*(t-n))))]}function u(){return i=e.length/(t-n),a=e.length-1,r}var i,a;return r.domain=function(e){return arguments.length?(n=+e[0],t=+e[e.length-1],u()):[n,t]},r.range=function(n){return arguments.length?(e=n,u()):e},r.invertExtent=function(t){return t=e.indexOf(t),t=0>t?NaN:t/i+n,[t,t+1/i]},r.copy=function(){return li(n,t,e)},u()}function ci(n,t){function e(e){return e>=e?t[oa.bisect(n,e)]:void 0}return e.domain=function(t){return arguments.length?(n=t,e):n},e.range=function(n){return arguments.length?(t=n,e):t},e.invertExtent=function(e){return e=t.indexOf(e),[n[e-1],n[e]]},e.copy=function(){return ci(n,t)},e}function si(n){function t(n){return+n}return t.invert=t,t.domain=t.range=function(e){return arguments.length?(n=e.map(t),t):n},t.ticks=function(t){return Qu(n,t)},t.tickFormat=function(t,e){return ni(n,t,e)},t.copy=function(){return si(n)},t}function fi(){return 0}function hi(n){return n.innerRadius}function gi(n){return n.outerRadius}function pi(n){return n.startAngle}function vi(n){return n.endAngle}function di(n){return n&&n.padAngle}function mi(n,t,e,r){return(n-e)*t-(t-r)*n>0?0:1}function yi(n,t,e,r,u){var i=n[0]-t[0],a=n[1]-t[1],o=(u?r:-r)/Math.sqrt(i*i+a*a),l=o*a,c=-o*i,s=n[0]+l,f=n[1]+c,h=t[0]+l,g=t[1]+c,p=(s+h)/2,v=(f+g)/2,d=h-s,m=g-f,y=d*d+m*m,M=e-r,x=s*g-h*f,b=(0>m?-1:1)*Math.sqrt(Math.max(0,M*M*y-x*x)),_=(x*m-d*b)/y,w=(-x*d-m*b)/y,S=(x*m+d*b)/y,k=(-x*d+m*b)/y,N=_-p,E=w-v,A=S-p,C=k-v;return N*N+E*E>A*A+C*C&&(_=S,w=k),[[_-l,w-c],[_*e/M,w*e/M]]}function Mi(n){function t(t){function a(){c.push("M",i(n(s),o))}for(var l,c=[],s=[],f=-1,h=t.length,g=En(e),p=En(r);++f<h;)u.call(this,l=t[f],f)?s.push([+g.call(this,l,f),+p.call(this,l,f)]):s.length&&(a(),s=[]);return s.length&&a(),c.length?c.join(""):null}var e=Ce,r=ze,u=zt,i=xi,a=i.key,o=.7;return t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t.defined=function(n){return arguments.length?(u=n,t):u},t.interpolate=function(n){return arguments.length?(a="function"==typeof n?i=n:(i=ql.get(n)||xi).key,t):a},t.tension=function(n){return arguments.length?(o=n,t):o},t}function xi(n){return n.length>1?n.join("L"):n+"Z"}function bi(n){return n.join("L")+"Z"}function _i(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r[0]+(r=n[t])[0])/2,"V",r[1]);return e>1&&u.push("H",r[0]),u.join("")}function wi(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("V",(r=n[t])[1],"H",r[0]);return u.join("")}function Si(n){for(var t=0,e=n.length,r=n[0],u=[r[0],",",r[1]];++t<e;)u.push("H",(r=n[t])[0],"V",r[1]);return u.join("")}function ki(n,t){return n.length<4?xi(n):n[1]+Ai(n.slice(1,-1),Ci(n,t))}function Ni(n,t){return n.length<3?bi(n):n[0]+Ai((n.push(n[0]),n),Ci([n[n.length-2]].concat(n,[n[1]]),t))}function Ei(n,t){return n.length<3?xi(n):n[0]+Ai(n,Ci(n,t))}function Ai(n,t){if(t.length<1||n.length!=t.length&&n.length!=t.length+2)return xi(n);var e=n.length!=t.length,r="",u=n[0],i=n[1],a=t[0],o=a,l=1;if(e&&(r+="Q"+(i[0]-2*a[0]/3)+","+(i[1]-2*a[1]/3)+","+i[0]+","+i[1],u=n[1],l=2),t.length>1){o=t[1],i=n[l],l++,r+="C"+(u[0]+a[0])+","+(u[1]+a[1])+","+(i[0]-o[0])+","+(i[1]-o[1])+","+i[0]+","+i[1];for(var c=2;c<t.length;c++,l++)i=n[l],o=t[c],r+="S"+(i[0]-o[0])+","+(i[1]-o[1])+","+i[0]+","+i[1]}if(e){var s=n[l];r+="Q"+(i[0]+2*o[0]/3)+","+(i[1]+2*o[1]/3)+","+s[0]+","+s[1]}return r}function Ci(n,t){for(var e,r=[],u=(1-t)/2,i=n[0],a=n[1],o=1,l=n.length;++o<l;)e=i,i=a,a=n[o],r.push([u*(a[0]-e[0]),u*(a[1]-e[1])]);return r}function zi(n){if(n.length<3)return xi(n);var t=1,e=n.length,r=n[0],u=r[0],i=r[1],a=[u,u,u,(r=n[1])[0]],o=[i,i,i,r[1]],l=[u,",",i,"L",Ri(Dl,a),",",Ri(Dl,o)];for(n.push(n[e-1]);++t<=e;)r=n[t],a.shift(),a.push(r[0]),o.shift(),o.push(r[1]),Di(l,a,o);return n.pop(),l.push("L",r),l.join("")}function Li(n){if(n.length<4)return xi(n);for(var t,e=[],r=-1,u=n.length,i=[0],a=[0];++r<3;)t=n[r],i.push(t[0]),a.push(t[1]);for(e.push(Ri(Dl,i)+","+Ri(Dl,a)),--r;++r<u;)t=n[r],i.shift(),i.push(t[0]),a.shift(),a.push(t[1]),Di(e,i,a);return e.join("")}function qi(n){for(var t,e,r=-1,u=n.length,i=u+4,a=[],o=[];++r<4;)e=n[r%u],a.push(e[0]),o.push(e[1]);for(t=[Ri(Dl,a),",",Ri(Dl,o)],--r;++r<i;)e=n[r%u],a.shift(),a.push(e[0]),o.shift(),o.push(e[1]),Di(t,a,o);return t.join("")}function Ti(n,t){var e=n.length-1;if(e)for(var r,u,i=n[0][0],a=n[0][1],o=n[e][0]-i,l=n[e][1]-a,c=-1;++c<=e;)r=n[c],u=c/e,r[0]=t*r[0]+(1-t)*(i+u*o),r[1]=t*r[1]+(1-t)*(a+u*l);return zi(n)}function Ri(n,t){return n[0]*t[0]+n[1]*t[1]+n[2]*t[2]+n[3]*t[3]}function Di(n,t,e){n.push("C",Ri(Tl,t),",",Ri(Tl,e),",",Ri(Rl,t),",",Ri(Rl,e),",",Ri(Dl,t),",",Ri(Dl,e))}function Pi(n,t){return(t[1]-n[1])/(t[0]-n[0])}function ji(n){for(var t=0,e=n.length-1,r=[],u=n[0],i=n[1],a=r[0]=Pi(u,i);++t<e;)r[t]=(a+(a=Pi(u=i,i=n[t+1])))/2;return r[t]=a,r}function Ui(n){for(var t,e,r,u,i=[],a=ji(n),o=-1,l=n.length-1;++o<l;)t=Pi(n[o],n[o+1]),Ma(t)<Da?a[o]=a[o+1]=0:(e=a[o]/t,r=a[o+1]/t,u=e*e+r*r,u>9&&(u=3*t/Math.sqrt(u),a[o]=u*e,a[o+1]=u*r));for(o=-1;++o<=l;)u=(n[Math.min(l,o+1)][0]-n[Math.max(0,o-1)][0])/(6*(1+a[o]*a[o])),i.push([u||0,a[o]*u||0]);return i}function Fi(n){return n.length<3?xi(n):n[0]+Ai(n,Ui(n))}function Hi(n){for(var t,e,r,u=-1,i=n.length;++u<i;)t=n[u],e=t[0],r=t[1]-Ha,t[0]=e*Math.cos(r),t[1]=e*Math.sin(r);return n}function Oi(n){function t(t){function l(){v.push("M",o(n(m),f),s,c(n(d.reverse()),f),"Z")}for(var h,g,p,v=[],d=[],m=[],y=-1,M=t.length,x=En(e),b=En(u),_=e===r?function(){
3
+return g}:En(r),w=u===i?function(){return p}:En(i);++y<M;)a.call(this,h=t[y],y)?(d.push([g=+x.call(this,h,y),p=+b.call(this,h,y)]),m.push([+_.call(this,h,y),+w.call(this,h,y)])):d.length&&(l(),d=[],m=[]);return d.length&&l(),v.length?v.join(""):null}var e=Ce,r=Ce,u=0,i=ze,a=zt,o=xi,l=o.key,c=o,s="L",f=.7;return t.x=function(n){return arguments.length?(e=r=n,t):r},t.x0=function(n){return arguments.length?(e=n,t):e},t.x1=function(n){return arguments.length?(r=n,t):r},t.y=function(n){return arguments.length?(u=i=n,t):i},t.y0=function(n){return arguments.length?(u=n,t):u},t.y1=function(n){return arguments.length?(i=n,t):i},t.defined=function(n){return arguments.length?(a=n,t):a},t.interpolate=function(n){return arguments.length?(l="function"==typeof n?o=n:(o=ql.get(n)||xi).key,c=o.reverse||o,s=o.closed?"M":"L",t):l},t.tension=function(n){return arguments.length?(f=n,t):f},t}function Ii(n){return n.radius}function Yi(n){return[n.x,n.y]}function Zi(n){return function(){var t=n.apply(this,arguments),e=t[0],r=t[1]-Ha;return[e*Math.cos(r),e*Math.sin(r)]}}function Vi(){return 64}function Xi(){return"circle"}function $i(n){var t=Math.sqrt(n/ja);return"M0,"+t+"A"+t+","+t+" 0 1,1 0,"+-t+"A"+t+","+t+" 0 1,1 0,"+t+"Z"}function Bi(n){return function(){var t,e,r;(t=this[n])&&(r=t[e=t.active])&&(r.timer.c=null,r.timer.t=NaN,--t.count?delete t[e]:delete this[n],t.active+=.5,r.event&&r.event.interrupt.call(this,this.__data__,r.index))}}function Wi(n,t,e){return Sa(n,Il),n.namespace=t,n.id=e,n}function Ji(n,t,e,r){var u=n.id,i=n.namespace;return Y(n,"function"==typeof e?function(n,a,o){n[i][u].tween.set(t,r(e.call(n,n.__data__,a,o)))}:(e=r(e),function(n){n[i][u].tween.set(t,e)}))}function Gi(n){return null==n&&(n=""),function(){this.textContent=n}}function Ki(n){return null==n?"__transition__":"__transition_"+n+"__"}function Qi(n,t,e,r,u){function i(n){var t=v.delay;return s.t=t+l,n>=t?a(n-t):void(s.c=a)}function a(e){var u=p.active,i=p[u];i&&(i.timer.c=null,i.timer.t=NaN,--p.count,delete p[u],i.event&&i.event.interrupt.call(n,n.__data__,i.index));for(var a in p)if(r>+a){var c=p[a];c.timer.c=null,c.timer.t=NaN,--p.count,delete p[a]}s.c=o,qn(function(){return s.c&&o(e||1)&&(s.c=null,s.t=NaN),1},0,l),p.active=r,v.event&&v.event.start.call(n,n.__data__,t),g=[],v.tween.forEach(function(e,r){(r=r.call(n,n.__data__,t))&&g.push(r)}),h=v.ease,f=v.duration}function o(u){for(var i=u/f,a=h(i),o=g.length;o>0;)g[--o].call(n,a);return i>=1?(v.event&&v.event.end.call(n,n.__data__,t),--p.count?delete p[r]:delete n[e],1):void 0}var l,s,f,h,g,p=n[e]||(n[e]={active:0,count:0}),v=p[r];v||(l=u.time,s=qn(i,0,l),v=p[r]={tween:new c,time:l,timer:s,delay:u.delay,duration:u.duration,ease:u.ease,index:t},u=null,++p.count)}function na(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate("+(isFinite(r)?r:e(n))+",0)"})}function ta(n,t,e){n.attr("transform",function(n){var r=t(n);return"translate(0,"+(isFinite(r)?r:e(n))+")"})}function ea(n){return n.toISOString()}function ra(n,t,e){function r(t){return n(t)}function u(n,e){var r=n[1]-n[0],u=r/e,i=oa.bisect(Gl,u);return i==Gl.length?[t.year,Ku(n.map(function(n){return n/31536e6}),e)[2]]:i?t[u/Gl[i-1]<Gl[i]/u?i-1:i]:[nc,Ku(n,e)[2]]}return r.invert=function(t){return ua(n.invert(t))},r.domain=function(t){return arguments.length?(n.domain(t),r):n.domain().map(ua)},r.nice=function(n,t){function e(e){return!isNaN(e)&&!n.range(e,ua(+e+1),t).length}var i=r.domain(),a=Yu(i),o=null==n?u(a,10):"number"==typeof n&&u(a,n);return o&&(n=o[0],t=o[1]),r.domain(Xu(i,t>1?{floor:function(t){for(;e(t=n.floor(t));)t=ua(t-1);return t},ceil:function(t){for(;e(t=n.ceil(t));)t=ua(+t+1);return t}}:n))},r.ticks=function(n,t){var e=Yu(r.domain()),i=null==n?u(e,10):"number"==typeof n?u(e,n):!n.range&&[{range:n},t];return i&&(n=i[0],t=i[1]),n.range(e[0],ua(+e[1]+1),1>t?1:t)},r.tickFormat=function(){return e},r.copy=function(){return ra(n.copy(),t,e)},Ju(r,n)}function ua(n){return new Date(n)}function ia(n){return JSON.parse(n.responseText)}function aa(n){var t=sa.createRange();return t.selectNode(sa.body),t.createContextualFragment(n.responseText)}var oa={version:"3.5.12"},la=[].slice,ca=function(n){return la.call(n)},sa=this.document;if(sa)try{ca(sa.documentElement.childNodes)[0].nodeType}catch(fa){ca=function(n){for(var t=n.length,e=new Array(t);t--;)e[t]=n[t];return e}}if(Date.now||(Date.now=function(){return+new Date}),sa)try{sa.createElement("DIV").style.setProperty("opacity",0,"")}catch(ha){var ga=this.Element.prototype,pa=ga.setAttribute,va=ga.setAttributeNS,da=this.CSSStyleDeclaration.prototype,ma=da.setProperty;ga.setAttribute=function(n,t){pa.call(this,n,t+"")},ga.setAttributeNS=function(n,t,e){va.call(this,n,t,e+"")},da.setProperty=function(n,t,e){ma.call(this,n,t+"",e)}}oa.ascending=e,oa.descending=function(n,t){return n>t?-1:t>n?1:t>=n?0:NaN},oa.min=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i;)if(null!=(r=n[u])&&r>=r){e=r;break}for(;++u<i;)null!=(r=n[u])&&e>r&&(e=r)}else{for(;++u<i;)if(null!=(r=t.call(n,n[u],u))&&r>=r){e=r;break}for(;++u<i;)null!=(r=t.call(n,n[u],u))&&e>r&&(e=r)}return e},oa.max=function(n,t){var e,r,u=-1,i=n.length;if(1===arguments.length){for(;++u<i;)if(null!=(r=n[u])&&r>=r){e=r;break}for(;++u<i;)null!=(r=n[u])&&r>e&&(e=r)}else{for(;++u<i;)if(null!=(r=t.call(n,n[u],u))&&r>=r){e=r;break}for(;++u<i;)null!=(r=t.call(n,n[u],u))&&r>e&&(e=r)}return e},oa.extent=function(n,t){var e,r,u,i=-1,a=n.length;if(1===arguments.length){for(;++i<a;)if(null!=(r=n[i])&&r>=r){e=u=r;break}for(;++i<a;)null!=(r=n[i])&&(e>r&&(e=r),r>u&&(u=r))}else{for(;++i<a;)if(null!=(r=t.call(n,n[i],i))&&r>=r){e=u=r;break}for(;++i<a;)null!=(r=t.call(n,n[i],i))&&(e>r&&(e=r),r>u&&(u=r))}return[e,u]},oa.sum=function(n,t){var e,r=0,i=n.length,a=-1;if(1===arguments.length)for(;++a<i;)u(e=+n[a])&&(r+=e);else for(;++a<i;)u(e=+t.call(n,n[a],a))&&(r+=e);return r},oa.mean=function(n,t){var e,i=0,a=n.length,o=-1,l=a;if(1===arguments.length)for(;++o<a;)u(e=r(n[o]))?i+=e:--l;else for(;++o<a;)u(e=r(t.call(n,n[o],o)))?i+=e:--l;return l?i/l:void 0},oa.quantile=function(n,t){var e=(n.length-1)*t+1,r=Math.floor(e),u=+n[r-1],i=e-r;return i?u+i*(n[r]-u):u},oa.median=function(n,t){var i,a=[],o=n.length,l=-1;if(1===arguments.length)for(;++l<o;)u(i=r(n[l]))&&a.push(i);else for(;++l<o;)u(i=r(t.call(n,n[l],l)))&&a.push(i);return a.length?oa.quantile(a.sort(e),.5):void 0},oa.variance=function(n,t){var e,i,a=n.length,o=0,l=0,c=-1,s=0;if(1===arguments.length)for(;++c<a;)u(e=r(n[c]))&&(i=e-o,o+=i/++s,l+=i*(e-o));else for(;++c<a;)u(e=r(t.call(n,n[c],c)))&&(i=e-o,o+=i/++s,l+=i*(e-o));return s>1?l/(s-1):void 0},oa.deviation=function(){var n=oa.variance.apply(this,arguments);return n?Math.sqrt(n):n};var ya=i(e);oa.bisectLeft=ya.left,oa.bisect=oa.bisectRight=ya.right,oa.bisector=function(n){return i(1===n.length?function(t,r){return e(n(t),r)}:n)},oa.shuffle=function(n,t,e){(i=arguments.length)<3&&(e=n.length,2>i&&(t=0));for(var r,u,i=e-t;i;)u=Math.random()*i--|0,r=n[i+t],n[i+t]=n[u+t],n[u+t]=r;return n},oa.permute=function(n,t){for(var e=t.length,r=new Array(e);e--;)r[e]=n[t[e]];return r},oa.pairs=function(n){for(var t,e=0,r=n.length-1,u=n[0],i=new Array(0>r?0:r);r>e;)i[e]=[t=u,u=n[++e]];return i},oa.zip=function(){if(!(r=arguments.length))return[];for(var n=-1,t=oa.min(arguments,a),e=new Array(t);++n<t;)for(var r,u=-1,i=e[n]=new Array(r);++u<r;)i[u]=arguments[u][n];return e},oa.transpose=function(n){return oa.zip.apply(oa,n)},oa.keys=function(n){var t=[];for(var e in n)t.push(e);return t},oa.values=function(n){var t=[];for(var e in n)t.push(n[e]);return t},oa.entries=function(n){var t=[];for(var e in n)t.push({key:e,value:n[e]});return t},oa.merge=function(n){for(var t,e,r,u=n.length,i=-1,a=0;++i<u;)a+=n[i].length;for(e=new Array(a);--u>=0;)for(r=n[u],t=r.length;--t>=0;)e[--a]=r[t];return e};var Ma=Math.abs;oa.range=function(n,t,e){if(arguments.length<3&&(e=1,arguments.length<2&&(t=n,n=0)),(t-n)/e===1/0)throw new Error("infinite range");var r,u=[],i=o(Ma(e)),a=-1;if(n*=i,t*=i,e*=i,0>e)for(;(r=n+e*++a)>t;)u.push(r/i);else for(;(r=n+e*++a)<t;)u.push(r/i);return u},oa.map=function(n,t){var e=new c;if(n instanceof c)n.forEach(function(n,t){e.set(n,t)});else if(Array.isArray(n)){var r,u=-1,i=n.length;if(1===arguments.length)for(;++u<i;)e.set(u,n[u]);else for(;++u<i;)e.set(t.call(n,r=n[u],u),r)}else for(var a in n)e.set(a,n[a]);return e};var xa="__proto__",ba="\x00";l(c,{has:h,get:function(n){return this._[s(n)]},set:function(n,t){return this._[s(n)]=t},remove:g,keys:p,values:function(){var n=[];for(var t in this._)n.push(this._[t]);return n},entries:function(){var n=[];for(var t in this._)n.push({key:f(t),value:this._[t]});return n},size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,f(t),this._[t])}}),oa.nest=function(){function n(t,a,o){if(o>=i.length)return r?r.call(u,a):e?a.sort(e):a;for(var l,s,f,h,g=-1,p=a.length,v=i[o++],d=new c;++g<p;)(h=d.get(l=v(s=a[g])))?h.push(s):d.set(l,[s]);return t?(s=t(),f=function(e,r){s.set(e,n(t,r,o))}):(s={},f=function(e,r){s[e]=n(t,r,o)}),d.forEach(f),s}function t(n,e){if(e>=i.length)return n;var r=[],u=a[e++];return n.forEach(function(n,u){r.push({key:n,values:t(u,e)})}),u?r.sort(function(n,t){return u(n.key,t.key)}):r}var e,r,u={},i=[],a=[];return u.map=function(t,e){return n(e,t,0)},u.entries=function(e){return t(n(oa.map,e,0),0)},u.key=function(n){return i.push(n),u},u.sortKeys=function(n){return a[i.length-1]=n,u},u.sortValues=function(n){return e=n,u},u.rollup=function(n){return r=n,u},u},oa.set=function(n){var t=new m;if(n)for(var e=0,r=n.length;r>e;++e)t.add(n[e]);return t},l(m,{has:h,add:function(n){return this._[s(n+="")]=!0,n},remove:g,values:p,size:v,empty:d,forEach:function(n){for(var t in this._)n.call(this,f(t))}}),oa.behavior={},oa.rebind=function(n,t){for(var e,r=1,u=arguments.length;++r<u;)n[e=arguments[r]]=M(n,t,t[e]);return n};var _a=["webkit","ms","moz","Moz","o","O"];oa.dispatch=function(){for(var n=new _,t=-1,e=arguments.length;++t<e;)n[arguments[t]]=w(n);return n},_.prototype.on=function(n,t){var e=n.indexOf("."),r="";if(e>=0&&(r=n.slice(e+1),n=n.slice(0,e)),n)return arguments.length<2?this[n].on(r):this[n].on(r,t);if(2===arguments.length){if(null==t)for(n in this)this.hasOwnProperty(n)&&this[n].on(r,null);return this}},oa.event=null,oa.requote=function(n){return n.replace(wa,"\\$&")};var wa=/[\\\^\$\*\+\?\|\[\]\(\)\.\{\}]/g,Sa={}.__proto__?function(n,t){n.__proto__=t}:function(n,t){for(var e in t)n[e]=t[e]},ka=function(n,t){return t.querySelector(n)},Na=function(n,t){return t.querySelectorAll(n)},Ea=function(n,t){var e=n.matches||n[x(n,"matchesSelector")];return(Ea=function(n,t){return e.call(n,t)})(n,t)};"function"==typeof Sizzle&&(ka=function(n,t){return Sizzle(n,t)[0]||null},Na=Sizzle,Ea=Sizzle.matchesSelector),oa.selection=function(){return oa.select(sa.documentElement)};var Aa=oa.selection.prototype=[];Aa.select=function(n){var t,e,r,u,i=[];n=A(n);for(var a=-1,o=this.length;++a<o;){i.push(t=[]),t.parentNode=(r=this[a]).parentNode;for(var l=-1,c=r.length;++l<c;)(u=r[l])?(t.push(e=n.call(u,u.__data__,l,a)),e&&"__data__"in u&&(e.__data__=u.__data__)):t.push(null)}return E(i)},Aa.selectAll=function(n){var t,e,r=[];n=C(n);for(var u=-1,i=this.length;++u<i;)for(var a=this[u],o=-1,l=a.length;++o<l;)(e=a[o])&&(r.push(t=ca(n.call(e,e.__data__,o,u))),t.parentNode=e);return E(r)};var Ca={svg:"http://www.w3.org/2000/svg",xhtml:"http://www.w3.org/1999/xhtml",xlink:"http://www.w3.org/1999/xlink",xml:"http://www.w3.org/XML/1998/namespace",xmlns:"http://www.w3.org/2000/xmlns/"};oa.ns={prefix:Ca,qualify:function(n){var t=n.indexOf(":"),e=n;return t>=0&&"xmlns"!==(e=n.slice(0,t))&&(n=n.slice(t+1)),Ca.hasOwnProperty(e)?{space:Ca[e],local:n}:n}},Aa.attr=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node();return n=oa.ns.qualify(n),n.local?e.getAttributeNS(n.space,n.local):e.getAttribute(n)}for(t in n)this.each(z(t,n[t]));return this}return this.each(z(n,t))},Aa.classed=function(n,t){if(arguments.length<2){if("string"==typeof n){var e=this.node(),r=(n=T(n)).length,u=-1;if(t=e.classList){for(;++u<r;)if(!t.contains(n[u]))return!1}else for(t=e.getAttribute("class");++u<r;)if(!q(n[u]).test(t))return!1;return!0}for(t in n)this.each(R(t,n[t]));return this}return this.each(R(n,t))},Aa.style=function(n,e,r){var u=arguments.length;if(3>u){if("string"!=typeof n){2>u&&(e="");for(r in n)this.each(P(r,n[r],e));return this}if(2>u){var i=this.node();return t(i).getComputedStyle(i,null).getPropertyValue(n)}r=""}return this.each(P(n,e,r))},Aa.property=function(n,t){if(arguments.length<2){if("string"==typeof n)return this.node()[n];for(t in n)this.each(j(t,n[t]));return this}return this.each(j(n,t))},Aa.text=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.textContent=null==t?"":t}:null==n?function(){this.textContent=""}:function(){this.textContent=n}):this.node().textContent},Aa.html=function(n){return arguments.length?this.each("function"==typeof n?function(){var t=n.apply(this,arguments);this.innerHTML=null==t?"":t}:null==n?function(){this.innerHTML=""}:function(){this.innerHTML=n}):this.node().innerHTML},Aa.append=function(n){return n=U(n),this.select(function(){return this.appendChild(n.apply(this,arguments))})},Aa.insert=function(n,t){return n=U(n),t=A(t),this.select(function(){return this.insertBefore(n.apply(this,arguments),t.apply(this,arguments)||null)})},Aa.remove=function(){return this.each(F)},Aa.data=function(n,t){function e(n,e){var r,u,i,a=n.length,f=e.length,h=Math.min(a,f),g=new Array(f),p=new Array(f),v=new Array(a);if(t){var d,m=new c,y=new Array(a);for(r=-1;++r<a;)(u=n[r])&&(m.has(d=t.call(u,u.__data__,r))?v[r]=u:m.set(d,u),y[r]=d);for(r=-1;++r<f;)(u=m.get(d=t.call(e,i=e[r],r)))?u!==!0&&(g[r]=u,u.__data__=i):p[r]=H(i),m.set(d,!0);for(r=-1;++r<a;)r in y&&m.get(y[r])!==!0&&(v[r]=n[r])}else{for(r=-1;++r<h;)u=n[r],i=e[r],u?(u.__data__=i,g[r]=u):p[r]=H(i);for(;f>r;++r)p[r]=H(e[r]);for(;a>r;++r)v[r]=n[r]}p.update=g,p.parentNode=g.parentNode=v.parentNode=n.parentNode,o.push(p),l.push(g),s.push(v)}var r,u,i=-1,a=this.length;if(!arguments.length){for(n=new Array(a=(r=this[0]).length);++i<a;)(u=r[i])&&(n[i]=u.__data__);return n}var o=Z([]),l=E([]),s=E([]);if("function"==typeof n)for(;++i<a;)e(r=this[i],n.call(r,r.parentNode.__data__,i));else for(;++i<a;)e(r=this[i],n);return l.enter=function(){return o},l.exit=function(){return s},l},Aa.datum=function(n){return arguments.length?this.property("__data__",n):this.property("__data__")},Aa.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=O(n));for(var i=0,a=this.length;a>i;i++){u.push(t=[]),t.parentNode=(e=this[i]).parentNode;for(var o=0,l=e.length;l>o;o++)(r=e[o])&&n.call(r,r.__data__,o,i)&&t.push(r)}return E(u)},Aa.order=function(){for(var n=-1,t=this.length;++n<t;)for(var e,r=this[n],u=r.length-1,i=r[u];--u>=0;)(e=r[u])&&(i&&i!==e.nextSibling&&i.parentNode.insertBefore(e,i),i=e);return this},Aa.sort=function(n){n=I.apply(this,arguments);for(var t=-1,e=this.length;++t<e;)this[t].sort(n);return this.order()},Aa.each=function(n){return Y(this,function(t,e,r){n.call(t,t.__data__,e,r)})},Aa.call=function(n){var t=ca(arguments);return n.apply(t[0]=this,t),this},Aa.empty=function(){return!this.node()},Aa.node=function(){for(var n=0,t=this.length;t>n;n++)for(var e=this[n],r=0,u=e.length;u>r;r++){var i=e[r];if(i)return i}return null},Aa.size=function(){var n=0;return Y(this,function(){++n}),n};var za=[];oa.selection.enter=Z,oa.selection.enter.prototype=za,za.append=Aa.append,za.empty=Aa.empty,za.node=Aa.node,za.call=Aa.call,za.size=Aa.size,za.select=function(n){for(var t,e,r,u,i,a=[],o=-1,l=this.length;++o<l;){r=(u=this[o]).update,a.push(t=[]),t.parentNode=u.parentNode;for(var c=-1,s=u.length;++c<s;)(i=u[c])?(t.push(r[c]=e=n.call(u.parentNode,i.__data__,c,o)),e.__data__=i.__data__):t.push(null)}return E(a)},za.insert=function(n,t){return arguments.length<2&&(t=V(this)),Aa.insert.call(this,n,t)},oa.select=function(t){var e;return"string"==typeof t?(e=[ka(t,sa)],e.parentNode=sa.documentElement):(e=[t],e.parentNode=n(t)),E([e])},oa.selectAll=function(n){var t;return"string"==typeof n?(t=ca(Na(n,sa)),t.parentNode=sa.documentElement):(t=ca(n),t.parentNode=null),E([t])},Aa.on=function(n,t,e){var r=arguments.length;if(3>r){if("string"!=typeof n){2>r&&(t=!1);for(e in n)this.each(X(e,n[e],t));return this}if(2>r)return(r=this.node()["__on"+n])&&r._;e=!1}return this.each(X(n,t,e))};var La=oa.map({mouseenter:"mouseover",mouseleave:"mouseout"});sa&&La.forEach(function(n){"on"+n in sa&&La.remove(n)});var qa,Ta=0;oa.mouse=function(n){return J(n,k())};var Ra=this.navigator&&/WebKit/.test(this.navigator.userAgent)?-1:0;oa.touch=function(n,t,e){if(arguments.length<3&&(e=t,t=k().changedTouches),t)for(var r,u=0,i=t.length;i>u;++u)if((r=t[u]).identifier===e)return J(n,r)},oa.behavior.drag=function(){function n(){this.on("mousedown.drag",i).on("touchstart.drag",a)}function e(n,t,e,i,a){return function(){function o(){var n,e,r=t(h,v);r&&(n=r[0]-M[0],e=r[1]-M[1],p|=n|e,M=r,g({type:"drag",x:r[0]+c[0],y:r[1]+c[1],dx:n,dy:e}))}function l(){t(h,v)&&(m.on(i+d,null).on(a+d,null),y(p),g({type:"dragend"}))}var c,s=this,f=oa.event.target,h=s.parentNode,g=r.of(s,arguments),p=0,v=n(),d=".drag"+(null==v?"":"-"+v),m=oa.select(e(f)).on(i+d,o).on(a+d,l),y=W(f),M=t(h,v);u?(c=u.apply(s,arguments),c=[c.x-M[0],c.y-M[1]]):c=[0,0],g({type:"dragstart"})}}var r=N(n,"drag","dragstart","dragend"),u=null,i=e(b,oa.mouse,t,"mousemove","mouseup"),a=e(G,oa.touch,y,"touchmove","touchend");return n.origin=function(t){return arguments.length?(u=t,n):u},oa.rebind(n,r,"on")},oa.touches=function(n,t){return arguments.length<2&&(t=k().touches),t?ca(t).map(function(t){var e=J(n,t);return e.identifier=t.identifier,e}):[]};var Da=1e-6,Pa=Da*Da,ja=Math.PI,Ua=2*ja,Fa=Ua-Da,Ha=ja/2,Oa=ja/180,Ia=180/ja,Ya=Math.SQRT2,Za=2,Va=4;oa.interpolateZoom=function(n,t){var e,r,u=n[0],i=n[1],a=n[2],o=t[0],l=t[1],c=t[2],s=o-u,f=l-i,h=s*s+f*f;if(Pa>h)r=Math.log(c/a)/Ya,e=function(n){return[u+n*s,i+n*f,a*Math.exp(Ya*n*r)]};else{var g=Math.sqrt(h),p=(c*c-a*a+Va*h)/(2*a*Za*g),v=(c*c-a*a-Va*h)/(2*c*Za*g),d=Math.log(Math.sqrt(p*p+1)-p),m=Math.log(Math.sqrt(v*v+1)-v);r=(m-d)/Ya,e=function(n){var t=n*r,e=rn(d),o=a/(Za*g)*(e*un(Ya*t+d)-en(d));return[u+o*s,i+o*f,a*e/rn(Ya*t+d)]}}return e.duration=1e3*r,e},oa.behavior.zoom=function(){function n(n){n.on(L,f).on($a+".zoom",g).on("dblclick.zoom",p).on(R,h)}function e(n){return[(n[0]-k.x)/k.k,(n[1]-k.y)/k.k]}function r(n){return[n[0]*k.k+k.x,n[1]*k.k+k.y]}function u(n){k.k=Math.max(A[0],Math.min(A[1],n))}function i(n,t){t=r(t),k.x+=n[0]-t[0],k.y+=n[1]-t[1]}function a(t,e,r,a){t.__chart__={x:k.x,y:k.y,k:k.k},u(Math.pow(2,a)),i(d=e,r),t=oa.select(t),C>0&&(t=t.transition().duration(C)),t.call(n.event)}function o(){b&&b.domain(x.range().map(function(n){return(n-k.x)/k.k}).map(x.invert)),w&&w.domain(_.range().map(function(n){return(n-k.y)/k.k}).map(_.invert))}function l(n){z++||n({type:"zoomstart"})}function c(n){o(),n({type:"zoom",scale:k.k,translate:[k.x,k.y]})}function s(n){--z||(n({type:"zoomend"}),d=null)}function f(){function n(){o=1,i(oa.mouse(u),h),c(a)}function r(){f.on(q,null).on(T,null),g(o),s(a)}var u=this,a=D.of(u,arguments),o=0,f=oa.select(t(u)).on(q,n).on(T,r),h=e(oa.mouse(u)),g=W(u);Ol.call(u),l(a)}function h(){function n(){var n=oa.touches(p);return g=k.k,n.forEach(function(n){n.identifier in d&&(d[n.identifier]=e(n))}),n}function t(){var t=oa.event.target;oa.select(t).on(x,r).on(b,o),_.push(t);for(var e=oa.event.changedTouches,u=0,i=e.length;i>u;++u)d[e[u].identifier]=null;var l=n(),c=Date.now();if(1===l.length){if(500>c-M){var s=l[0];a(p,s,d[s.identifier],Math.floor(Math.log(k.k)/Math.LN2)+1),S()}M=c}else if(l.length>1){var s=l[0],f=l[1],h=s[0]-f[0],g=s[1]-f[1];m=h*h+g*g}}function r(){var n,t,e,r,a=oa.touches(p);Ol.call(p);for(var o=0,l=a.length;l>o;++o,r=null)if(e=a[o],r=d[e.identifier]){if(t)break;n=e,t=r}if(r){var s=(s=e[0]-n[0])*s+(s=e[1]-n[1])*s,f=m&&Math.sqrt(s/m);n=[(n[0]+e[0])/2,(n[1]+e[1])/2],t=[(t[0]+r[0])/2,(t[1]+r[1])/2],u(f*g)}M=null,i(n,t),c(v)}function o(){if(oa.event.touches.length){for(var t=oa.event.changedTouches,e=0,r=t.length;r>e;++e)delete d[t[e].identifier];for(var u in d)return void n()}oa.selectAll(_).on(y,null),w.on(L,f).on(R,h),N(),s(v)}var g,p=this,v=D.of(p,arguments),d={},m=0,y=".zoom-"+oa.event.changedTouches[0].identifier,x="touchmove"+y,b="touchend"+y,_=[],w=oa.select(p),N=W(p);t(),l(v),w.on(L,null).on(R,t)}function g(){var n=D.of(this,arguments);y?clearTimeout(y):(Ol.call(this),v=e(d=m||oa.mouse(this)),l(n)),y=setTimeout(function(){y=null,s(n)},50),S(),u(Math.pow(2,.002*Xa())*k.k),i(d,v),c(n)}function p(){var n=oa.mouse(this),t=Math.log(k.k)/Math.LN2;a(this,n,e(n),oa.event.shiftKey?Math.ceil(t)-1:Math.floor(t)+1)}var v,d,m,y,M,x,b,_,w,k={x:0,y:0,k:1},E=[960,500],A=Ba,C=250,z=0,L="mousedown.zoom",q="mousemove.zoom",T="mouseup.zoom",R="touchstart.zoom",D=N(n,"zoomstart","zoom","zoomend");return $a||($a="onwheel"in sa?(Xa=function(){return-oa.event.deltaY*(oa.event.deltaMode?120:1)},"wheel"):"onmousewheel"in sa?(Xa=function(){return oa.event.wheelDelta},"mousewheel"):(Xa=function(){return-oa.event.detail},"MozMousePixelScroll")),n.event=function(n){n.each(function(){var n=D.of(this,arguments),t=k;Fl?oa.select(this).transition().each("start.zoom",function(){k=this.__chart__||{x:0,y:0,k:1},l(n)}).tween("zoom:zoom",function(){var e=E[0],r=E[1],u=d?d[0]:e/2,i=d?d[1]:r/2,a=oa.interpolateZoom([(u-k.x)/k.k,(i-k.y)/k.k,e/k.k],[(u-t.x)/t.k,(i-t.y)/t.k,e/t.k]);return function(t){var r=a(t),o=e/r[2];this.__chart__=k={x:u-r[0]*o,y:i-r[1]*o,k:o},c(n)}}).each("interrupt.zoom",function(){s(n)}).each("end.zoom",function(){s(n)}):(this.__chart__=k,l(n),c(n),s(n))})},n.translate=function(t){return arguments.length?(k={x:+t[0],y:+t[1],k:k.k},o(),n):[k.x,k.y]},n.scale=function(t){return arguments.length?(k={x:k.x,y:k.y,k:null},u(+t),o(),n):k.k},n.scaleExtent=function(t){return arguments.length?(A=null==t?Ba:[+t[0],+t[1]],n):A},n.center=function(t){return arguments.length?(m=t&&[+t[0],+t[1]],n):m},n.size=function(t){return arguments.length?(E=t&&[+t[0],+t[1]],n):E},n.duration=function(t){return arguments.length?(C=+t,n):C},n.x=function(t){return arguments.length?(b=t,x=t.copy(),k={x:0,y:0,k:1},n):b},n.y=function(t){return arguments.length?(w=t,_=t.copy(),k={x:0,y:0,k:1},n):w},oa.rebind(n,D,"on")};var Xa,$a,Ba=[0,1/0];oa.color=on,on.prototype.toString=function(){return this.rgb()+""},oa.hsl=ln;var Wa=ln.prototype=new on;Wa.brighter=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,this.l/n)},Wa.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new ln(this.h,this.s,n*this.l)},Wa.rgb=function(){return cn(this.h,this.s,this.l)},oa.hcl=sn;var Ja=sn.prototype=new on;Ja.brighter=function(n){return new sn(this.h,this.c,Math.min(100,this.l+Ga*(arguments.length?n:1)))},Ja.darker=function(n){return new sn(this.h,this.c,Math.max(0,this.l-Ga*(arguments.length?n:1)))},Ja.rgb=function(){return fn(this.h,this.c,this.l).rgb()},oa.lab=hn;var Ga=18,Ka=.95047,Qa=1,no=1.08883,to=hn.prototype=new on;to.brighter=function(n){return new hn(Math.min(100,this.l+Ga*(arguments.length?n:1)),this.a,this.b)},to.darker=function(n){return new hn(Math.max(0,this.l-Ga*(arguments.length?n:1)),this.a,this.b)},to.rgb=function(){return gn(this.l,this.a,this.b)},oa.rgb=yn;var eo=yn.prototype=new on;eo.brighter=function(n){n=Math.pow(.7,arguments.length?n:1);var t=this.r,e=this.g,r=this.b,u=30;return t||e||r?(t&&u>t&&(t=u),e&&u>e&&(e=u),r&&u>r&&(r=u),new yn(Math.min(255,t/n),Math.min(255,e/n),Math.min(255,r/n))):new yn(u,u,u)},eo.darker=function(n){return n=Math.pow(.7,arguments.length?n:1),new yn(n*this.r,n*this.g,n*this.b)},eo.hsl=function(){return wn(this.r,this.g,this.b)},eo.toString=function(){return"#"+bn(this.r)+bn(this.g)+bn(this.b)};var ro=oa.map({aliceblue:15792383,antiquewhite:16444375,aqua:65535,aquamarine:8388564,azure:15794175,beige:16119260,bisque:16770244,black:0,blanchedalmond:16772045,blue:255,blueviolet:9055202,brown:10824234,burlywood:14596231,cadetblue:6266528,chartreuse:8388352,chocolate:13789470,coral:16744272,cornflowerblue:6591981,cornsilk:16775388,crimson:14423100,cyan:65535,darkblue:139,darkcyan:35723,darkgoldenrod:12092939,darkgray:11119017,darkgreen:25600,darkgrey:11119017,darkkhaki:12433259,darkmagenta:9109643,darkolivegreen:5597999,darkorange:16747520,darkorchid:10040012,darkred:9109504,darksalmon:15308410,darkseagreen:9419919,darkslateblue:4734347,darkslategray:3100495,darkslategrey:3100495,darkturquoise:52945,darkviolet:9699539,deeppink:16716947,deepskyblue:49151,dimgray:6908265,dimgrey:6908265,dodgerblue:2003199,firebrick:11674146,floralwhite:16775920,forestgreen:2263842,fuchsia:16711935,gainsboro:14474460,ghostwhite:16316671,gold:16766720,goldenrod:14329120,gray:8421504,green:32768,greenyellow:11403055,grey:8421504,honeydew:15794160,hotpink:16738740,indianred:13458524,indigo:4915330,ivory:16777200,khaki:15787660,lavender:15132410,lavenderblush:16773365,lawngreen:8190976,lemonchiffon:16775885,lightblue:11393254,lightcoral:15761536,lightcyan:14745599,lightgoldenrodyellow:16448210,lightgray:13882323,lightgreen:9498256,lightgrey:13882323,lightpink:16758465,lightsalmon:16752762,lightseagreen:2142890,lightskyblue:8900346,lightslategray:7833753,lightslategrey:7833753,lightsteelblue:11584734,lightyellow:16777184,lime:65280,limegreen:3329330,linen:16445670,magenta:16711935,maroon:8388608,mediumaquamarine:6737322,mediumblue:205,mediumorchid:12211667,mediumpurple:9662683,mediumseagreen:3978097,mediumslateblue:8087790,mediumspringgreen:64154,mediumturquoise:4772300,mediumvioletred:13047173,midnightblue:1644912,mintcream:16121850,mistyrose:16770273,moccasin:16770229,navajowhite:16768685,navy:128,oldlace:16643558,olive:8421376,olivedrab:7048739,orange:16753920,orangered:16729344,orchid:14315734,palegoldenrod:15657130,palegreen:10025880,paleturquoise:11529966,palevioletred:14381203,papayawhip:16773077,peachpuff:16767673,peru:13468991,pink:16761035,plum:14524637,powderblue:11591910,purple:8388736,rebeccapurple:6697881,red:16711680,rosybrown:12357519,royalblue:4286945,saddlebrown:9127187,salmon:16416882,sandybrown:16032864,seagreen:3050327,seashell:16774638,sienna:10506797,silver:12632256,skyblue:8900331,slateblue:6970061,slategray:7372944,slategrey:7372944,snow:16775930,springgreen:65407,steelblue:4620980,tan:13808780,teal:32896,thistle:14204888,tomato:16737095,turquoise:4251856,violet:15631086,wheat:16113331,white:16777215,whitesmoke:16119285,yellow:16776960,yellowgreen:10145074});ro.forEach(function(n,t){ro.set(n,Mn(t))}),oa.functor=En,oa.xhr=An(y),oa.dsv=function(n,t){function e(n,e,i){arguments.length<3&&(i=e,e=null);var a=Cn(n,t,null==e?r:u(e),i);return a.row=function(n){return arguments.length?a.response(null==(e=n)?r:u(n)):e},a}function r(n){return e.parse(n.responseText)}function u(n){return function(t){return e.parse(t.responseText,n)}}function i(t){return t.map(a).join(n)}function a(n){return o.test(n)?'"'+n.replace(/\"/g,'""')+'"':n}var o=new RegExp('["'+n+"\n]"),l=n.charCodeAt(0);return e.parse=function(n,t){var r;return e.parseRows(n,function(n,e){if(r)return r(n,e-1);var u=new Function("d","return {"+n.map(function(n,t){return JSON.stringify(n)+": d["+t+"]"}).join(",")+"}");r=t?function(n,e){return t(u(n),e)}:u})},e.parseRows=function(n,t){function e(){if(s>=c)return a;if(u)return u=!1,i;var t=s;if(34===n.charCodeAt(t)){for(var e=t;e++<c;)if(34===n.charCodeAt(e)){if(34!==n.charCodeAt(e+1))break;++e}s=e+2;var r=n.charCodeAt(e+1);return 13===r?(u=!0,10===n.charCodeAt(e+2)&&++s):10===r&&(u=!0),n.slice(t+1,e).replace(/""/g,'"')}for(;c>s;){var r=n.charCodeAt(s++),o=1;if(10===r)u=!0;else if(13===r)u=!0,10===n.charCodeAt(s)&&(++s,++o);else if(r!==l)continue;return n.slice(t,s-o)}return n.slice(t)}for(var r,u,i={},a={},o=[],c=n.length,s=0,f=0;(r=e())!==a;){for(var h=[];r!==i&&r!==a;)h.push(r),r=e();t&&null==(h=t(h,f++))||o.push(h)}return o},e.format=function(t){if(Array.isArray(t[0]))return e.formatRows(t);var r=new m,u=[];return t.forEach(function(n){for(var t in n)r.has(t)||u.push(r.add(t))}),[u.map(a).join(n)].concat(t.map(function(t){return u.map(function(n){return a(t[n])}).join(n)})).join("\n")},e.formatRows=function(n){return n.map(i).join("\n")},e},oa.csv=oa.dsv(",","text/csv"),oa.tsv=oa.dsv(" ","text/tab-separated-values");var uo,io,ao,oo,lo=this[x(this,"requestAnimationFrame")]||function(n){setTimeout(n,17)};oa.timer=function(){qn.apply(this,arguments)},oa.timer.flush=function(){Rn(),Dn()},oa.round=function(n,t){return t?Math.round(n*(t=Math.pow(10,t)))/t:Math.round(n)};var co=["y","z","a","f","p","n","\xb5","m","","k","M","G","T","P","E","Z","Y"].map(jn);oa.formatPrefix=function(n,t){var e=0;return(n=+n)&&(0>n&&(n*=-1),t&&(n=oa.round(n,Pn(n,t))),e=1+Math.floor(1e-12+Math.log(n)/Math.LN10),e=Math.max(-24,Math.min(24,3*Math.floor((e-1)/3)))),co[8+e/3]};var so=/(?:([^{])?([<>=^]))?([+\- ])?([$#])?(0)?(\d+)?(,)?(\.-?\d+)?([a-z%])?/i,fo=oa.map({b:function(n){return n.toString(2)},c:function(n){return String.fromCharCode(n)},o:function(n){return n.toString(8)},x:function(n){return n.toString(16)},X:function(n){return n.toString(16).toUpperCase()},g:function(n,t){return n.toPrecision(t)},e:function(n,t){return n.toExponential(t)},f:function(n,t){return n.toFixed(t)},r:function(n,t){return(n=oa.round(n,Pn(n,t))).toFixed(Math.max(0,Math.min(20,Pn(n*(1+1e-15),t))))}}),ho=oa.time={},go=Date;Hn.prototype={getDate:function(){return this._.getUTCDate()},getDay:function(){return this._.getUTCDay()},getFullYear:function(){return this._.getUTCFullYear()},getHours:function(){return this._.getUTCHours()},getMilliseconds:function(){return this._.getUTCMilliseconds()},getMinutes:function(){return this._.getUTCMinutes()},getMonth:function(){return this._.getUTCMonth()},getSeconds:function(){return this._.getUTCSeconds()},getTime:function(){return this._.getTime()},getTimezoneOffset:function(){return 0},valueOf:function(){return this._.valueOf()},setDate:function(){po.setUTCDate.apply(this._,arguments)},setDay:function(){po.setUTCDay.apply(this._,arguments)},setFullYear:function(){po.setUTCFullYear.apply(this._,arguments)},setHours:function(){po.setUTCHours.apply(this._,arguments)},setMilliseconds:function(){po.setUTCMilliseconds.apply(this._,arguments)},setMinutes:function(){po.setUTCMinutes.apply(this._,arguments)},setMonth:function(){po.setUTCMonth.apply(this._,arguments)},setSeconds:function(){po.setUTCSeconds.apply(this._,arguments)},setTime:function(){po.setTime.apply(this._,arguments)}};var po=Date.prototype;ho.year=On(function(n){return n=ho.day(n),n.setMonth(0,1),n},function(n,t){n.setFullYear(n.getFullYear()+t)},function(n){return n.getFullYear()}),ho.years=ho.year.range,ho.years.utc=ho.year.utc.range,ho.day=On(function(n){var t=new go(2e3,0);return t.setFullYear(n.getFullYear(),n.getMonth(),n.getDate()),t},function(n,t){n.setDate(n.getDate()+t)},function(n){return n.getDate()-1}),ho.days=ho.day.range,ho.days.utc=ho.day.utc.range,ho.dayOfYear=function(n){var t=ho.year(n);return Math.floor((n-t-6e4*(n.getTimezoneOffset()-t.getTimezoneOffset()))/864e5)},["sunday","monday","tuesday","wednesday","thursday","friday","saturday"].forEach(function(n,t){t=7-t;var e=ho[n]=On(function(n){return(n=ho.day(n)).setDate(n.getDate()-(n.getDay()+t)%7),n},function(n,t){n.setDate(n.getDate()+7*Math.floor(t))},function(n){var e=ho.year(n).getDay();return Math.floor((ho.dayOfYear(n)+(e+t)%7)/7)-(e!==t)});ho[n+"s"]=e.range,ho[n+"s"].utc=e.utc.range,ho[n+"OfYear"]=function(n){var e=ho.year(n).getDay();return Math.floor((ho.dayOfYear(n)+(e+t)%7)/7)}}),ho.week=ho.sunday,ho.weeks=ho.sunday.range,ho.weeks.utc=ho.sunday.utc.range,ho.weekOfYear=ho.sundayOfYear;var vo={"-":"",_:" ",0:"0"},mo=/^\s*\d+/,yo=/^%/;oa.locale=function(n){return{numberFormat:Un(n),timeFormat:Yn(n)}};var Mo=oa.locale({decimal:".",thousands:",",grouping:[3],currency:["$",""],dateTime:"%a %b %e %X %Y",date:"%m/%d/%Y",time:"%H:%M:%S",periods:["AM","PM"],days:["Sunday","Monday","Tuesday","Wednesday","Thursday","Friday","Saturday"],
4
+shortDays:["Sun","Mon","Tue","Wed","Thu","Fri","Sat"],months:["January","February","March","April","May","June","July","August","September","October","November","December"],shortMonths:["Jan","Feb","Mar","Apr","May","Jun","Jul","Aug","Sep","Oct","Nov","Dec"]});oa.format=Mo.numberFormat,oa.geo={},st.prototype={s:0,t:0,add:function(n){ft(n,this.t,xo),ft(xo.s,this.s,this),this.s?this.t+=xo.t:this.s=xo.t},reset:function(){this.s=this.t=0},valueOf:function(){return this.s}};var xo=new st;oa.geo.stream=function(n,t){n&&bo.hasOwnProperty(n.type)?bo[n.type](n,t):ht(n,t)};var bo={Feature:function(n,t){ht(n.geometry,t)},FeatureCollection:function(n,t){for(var e=n.features,r=-1,u=e.length;++r<u;)ht(e[r].geometry,t)}},_o={Sphere:function(n,t){t.sphere()},Point:function(n,t){n=n.coordinates,t.point(n[0],n[1],n[2])},MultiPoint:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)n=e[r],t.point(n[0],n[1],n[2])},LineString:function(n,t){gt(n.coordinates,t,0)},MultiLineString:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)gt(e[r],t,0)},Polygon:function(n,t){pt(n.coordinates,t)},MultiPolygon:function(n,t){for(var e=n.coordinates,r=-1,u=e.length;++r<u;)pt(e[r],t)},GeometryCollection:function(n,t){for(var e=n.geometries,r=-1,u=e.length;++r<u;)ht(e[r],t)}};oa.geo.area=function(n){return wo=0,oa.geo.stream(n,ko),wo};var wo,So=new st,ko={sphere:function(){wo+=4*ja},point:b,lineStart:b,lineEnd:b,polygonStart:function(){So.reset(),ko.lineStart=vt},polygonEnd:function(){var n=2*So;wo+=0>n?4*ja+n:n,ko.lineStart=ko.lineEnd=ko.point=b}};oa.geo.bounds=function(){function n(n,t){M.push(x=[s=n,h=n]),f>t&&(f=t),t>g&&(g=t)}function t(t,e){var r=dt([t*Oa,e*Oa]);if(m){var u=yt(m,r),i=[u[1],-u[0],0],a=yt(i,u);bt(a),a=_t(a);var l=t-p,c=l>0?1:-1,v=a[0]*Ia*c,d=Ma(l)>180;if(d^(v>c*p&&c*t>v)){var y=a[1]*Ia;y>g&&(g=y)}else if(v=(v+360)%360-180,d^(v>c*p&&c*t>v)){var y=-a[1]*Ia;f>y&&(f=y)}else f>e&&(f=e),e>g&&(g=e);d?p>t?o(s,t)>o(s,h)&&(h=t):o(t,h)>o(s,h)&&(s=t):h>=s?(s>t&&(s=t),t>h&&(h=t)):t>p?o(s,t)>o(s,h)&&(h=t):o(t,h)>o(s,h)&&(s=t)}else n(t,e);m=r,p=t}function e(){b.point=t}function r(){x[0]=s,x[1]=h,b.point=n,m=null}function u(n,e){if(m){var r=n-p;y+=Ma(r)>180?r+(r>0?360:-360):r}else v=n,d=e;ko.point(n,e),t(n,e)}function i(){ko.lineStart()}function a(){u(v,d),ko.lineEnd(),Ma(y)>Da&&(s=-(h=180)),x[0]=s,x[1]=h,m=null}function o(n,t){return(t-=n)<0?t+360:t}function l(n,t){return n[0]-t[0]}function c(n,t){return t[0]<=t[1]?t[0]<=n&&n<=t[1]:n<t[0]||t[1]<n}var s,f,h,g,p,v,d,m,y,M,x,b={point:n,lineStart:e,lineEnd:r,polygonStart:function(){b.point=u,b.lineStart=i,b.lineEnd=a,y=0,ko.polygonStart()},polygonEnd:function(){ko.polygonEnd(),b.point=n,b.lineStart=e,b.lineEnd=r,0>So?(s=-(h=180),f=-(g=90)):y>Da?g=90:-Da>y&&(f=-90),x[0]=s,x[1]=h}};return function(n){g=h=-(s=f=1/0),M=[],oa.geo.stream(n,b);var t=M.length;if(t){M.sort(l);for(var e,r=1,u=M[0],i=[u];t>r;++r)e=M[r],c(e[0],u)||c(e[1],u)?(o(u[0],e[1])>o(u[0],u[1])&&(u[1]=e[1]),o(e[0],u[1])>o(u[0],u[1])&&(u[0]=e[0])):i.push(u=e);for(var a,e,p=-(1/0),t=i.length-1,r=0,u=i[t];t>=r;u=e,++r)e=i[r],(a=o(u[1],e[0]))>p&&(p=a,s=e[0],h=u[1])}return M=x=null,s===1/0||f===1/0?[[NaN,NaN],[NaN,NaN]]:[[s,f],[h,g]]}}(),oa.geo.centroid=function(n){No=Eo=Ao=Co=zo=Lo=qo=To=Ro=Do=Po=0,oa.geo.stream(n,jo);var t=Ro,e=Do,r=Po,u=t*t+e*e+r*r;return Pa>u&&(t=Lo,e=qo,r=To,Da>Eo&&(t=Ao,e=Co,r=zo),u=t*t+e*e+r*r,Pa>u)?[NaN,NaN]:[Math.atan2(e,t)*Ia,tn(r/Math.sqrt(u))*Ia]};var No,Eo,Ao,Co,zo,Lo,qo,To,Ro,Do,Po,jo={sphere:b,point:St,lineStart:Nt,lineEnd:Et,polygonStart:function(){jo.lineStart=At},polygonEnd:function(){jo.lineStart=Nt}},Uo=Rt(zt,Ut,Ht,[-ja,-ja/2]),Fo=1e9;oa.geo.clipExtent=function(){var n,t,e,r,u,i,a={stream:function(n){return u&&(u.valid=!1),u=i(n),u.valid=!0,u},extent:function(o){return arguments.length?(i=Zt(n=+o[0][0],t=+o[0][1],e=+o[1][0],r=+o[1][1]),u&&(u.valid=!1,u=null),a):[[n,t],[e,r]]}};return a.extent([[0,0],[960,500]])},(oa.geo.conicEqualArea=function(){return Vt(Xt)}).raw=Xt,oa.geo.albers=function(){return oa.geo.conicEqualArea().rotate([96,0]).center([-.6,38.7]).parallels([29.5,45.5]).scale(1070)},oa.geo.albersUsa=function(){function n(n){var i=n[0],a=n[1];return t=null,e(i,a),t||(r(i,a),t)||u(i,a),t}var t,e,r,u,i=oa.geo.albers(),a=oa.geo.conicEqualArea().rotate([154,0]).center([-2,58.5]).parallels([55,65]),o=oa.geo.conicEqualArea().rotate([157,0]).center([-3,19.9]).parallels([8,18]),l={point:function(n,e){t=[n,e]}};return n.invert=function(n){var t=i.scale(),e=i.translate(),r=(n[0]-e[0])/t,u=(n[1]-e[1])/t;return(u>=.12&&.234>u&&r>=-.425&&-.214>r?a:u>=.166&&.234>u&&r>=-.214&&-.115>r?o:i).invert(n)},n.stream=function(n){var t=i.stream(n),e=a.stream(n),r=o.stream(n);return{point:function(n,u){t.point(n,u),e.point(n,u),r.point(n,u)},sphere:function(){t.sphere(),e.sphere(),r.sphere()},lineStart:function(){t.lineStart(),e.lineStart(),r.lineStart()},lineEnd:function(){t.lineEnd(),e.lineEnd(),r.lineEnd()},polygonStart:function(){t.polygonStart(),e.polygonStart(),r.polygonStart()},polygonEnd:function(){t.polygonEnd(),e.polygonEnd(),r.polygonEnd()}}},n.precision=function(t){return arguments.length?(i.precision(t),a.precision(t),o.precision(t),n):i.precision()},n.scale=function(t){return arguments.length?(i.scale(t),a.scale(.35*t),o.scale(t),n.translate(i.translate())):i.scale()},n.translate=function(t){if(!arguments.length)return i.translate();var c=i.scale(),s=+t[0],f=+t[1];return e=i.translate(t).clipExtent([[s-.455*c,f-.238*c],[s+.455*c,f+.238*c]]).stream(l).point,r=a.translate([s-.307*c,f+.201*c]).clipExtent([[s-.425*c+Da,f+.12*c+Da],[s-.214*c-Da,f+.234*c-Da]]).stream(l).point,u=o.translate([s-.205*c,f+.212*c]).clipExtent([[s-.214*c+Da,f+.166*c+Da],[s-.115*c-Da,f+.234*c-Da]]).stream(l).point,n},n.scale(1070)};var Ho,Oo,Io,Yo,Zo,Vo,Xo={point:b,lineStart:b,lineEnd:b,polygonStart:function(){Oo=0,Xo.lineStart=$t},polygonEnd:function(){Xo.lineStart=Xo.lineEnd=Xo.point=b,Ho+=Ma(Oo/2)}},$o={point:Bt,lineStart:b,lineEnd:b,polygonStart:b,polygonEnd:b},Bo={point:Gt,lineStart:Kt,lineEnd:Qt,polygonStart:function(){Bo.lineStart=ne},polygonEnd:function(){Bo.point=Gt,Bo.lineStart=Kt,Bo.lineEnd=Qt}};oa.geo.path=function(){function n(n){return n&&("function"==typeof o&&i.pointRadius(+o.apply(this,arguments)),a&&a.valid||(a=u(i)),oa.geo.stream(n,a)),i.result()}function t(){return a=null,n}var e,r,u,i,a,o=4.5;return n.area=function(n){return Ho=0,oa.geo.stream(n,u(Xo)),Ho},n.centroid=function(n){return Ao=Co=zo=Lo=qo=To=Ro=Do=Po=0,oa.geo.stream(n,u(Bo)),Po?[Ro/Po,Do/Po]:To?[Lo/To,qo/To]:zo?[Ao/zo,Co/zo]:[NaN,NaN]},n.bounds=function(n){return Zo=Vo=-(Io=Yo=1/0),oa.geo.stream(n,u($o)),[[Io,Yo],[Zo,Vo]]},n.projection=function(n){return arguments.length?(u=(e=n)?n.stream||re(n):y,t()):e},n.context=function(n){return arguments.length?(i=null==(r=n)?new Wt:new te(n),"function"!=typeof o&&i.pointRadius(o),t()):r},n.pointRadius=function(t){return arguments.length?(o="function"==typeof t?t:(i.pointRadius(+t),+t),n):o},n.projection(oa.geo.albersUsa()).context(null)},oa.geo.transform=function(n){return{stream:function(t){var e=new ue(t);for(var r in n)e[r]=n[r];return e}}},ue.prototype={point:function(n,t){this.stream.point(n,t)},sphere:function(){this.stream.sphere()},lineStart:function(){this.stream.lineStart()},lineEnd:function(){this.stream.lineEnd()},polygonStart:function(){this.stream.polygonStart()},polygonEnd:function(){this.stream.polygonEnd()}},oa.geo.projection=ae,oa.geo.projectionMutator=oe,(oa.geo.equirectangular=function(){return ae(ce)}).raw=ce.invert=ce,oa.geo.rotation=function(n){function t(t){return t=n(t[0]*Oa,t[1]*Oa),t[0]*=Ia,t[1]*=Ia,t}return n=fe(n[0]%360*Oa,n[1]*Oa,n.length>2?n[2]*Oa:0),t.invert=function(t){return t=n.invert(t[0]*Oa,t[1]*Oa),t[0]*=Ia,t[1]*=Ia,t},t},se.invert=ce,oa.geo.circle=function(){function n(){var n="function"==typeof r?r.apply(this,arguments):r,t=fe(-n[0]*Oa,-n[1]*Oa,0).invert,u=[];return e(null,null,1,{point:function(n,e){u.push(n=t(n,e)),n[0]*=Ia,n[1]*=Ia}}),{type:"Polygon",coordinates:[u]}}var t,e,r=[0,0],u=6;return n.origin=function(t){return arguments.length?(r=t,n):r},n.angle=function(r){return arguments.length?(e=ve((t=+r)*Oa,u*Oa),n):t},n.precision=function(r){return arguments.length?(e=ve(t*Oa,(u=+r)*Oa),n):u},n.angle(90)},oa.geo.distance=function(n,t){var e,r=(t[0]-n[0])*Oa,u=n[1]*Oa,i=t[1]*Oa,a=Math.sin(r),o=Math.cos(r),l=Math.sin(u),c=Math.cos(u),s=Math.sin(i),f=Math.cos(i);return Math.atan2(Math.sqrt((e=f*a)*e+(e=c*s-l*f*o)*e),l*s+c*f*o)},oa.geo.graticule=function(){function n(){return{type:"MultiLineString",coordinates:t()}}function t(){return oa.range(Math.ceil(i/d)*d,u,d).map(h).concat(oa.range(Math.ceil(c/m)*m,l,m).map(g)).concat(oa.range(Math.ceil(r/p)*p,e,p).filter(function(n){return Ma(n%d)>Da}).map(s)).concat(oa.range(Math.ceil(o/v)*v,a,v).filter(function(n){return Ma(n%m)>Da}).map(f))}var e,r,u,i,a,o,l,c,s,f,h,g,p=10,v=p,d=90,m=360,y=2.5;return n.lines=function(){return t().map(function(n){return{type:"LineString",coordinates:n}})},n.outline=function(){return{type:"Polygon",coordinates:[h(i).concat(g(l).slice(1),h(u).reverse().slice(1),g(c).reverse().slice(1))]}},n.extent=function(t){return arguments.length?n.majorExtent(t).minorExtent(t):n.minorExtent()},n.majorExtent=function(t){return arguments.length?(i=+t[0][0],u=+t[1][0],c=+t[0][1],l=+t[1][1],i>u&&(t=i,i=u,u=t),c>l&&(t=c,c=l,l=t),n.precision(y)):[[i,c],[u,l]]},n.minorExtent=function(t){return arguments.length?(r=+t[0][0],e=+t[1][0],o=+t[0][1],a=+t[1][1],r>e&&(t=r,r=e,e=t),o>a&&(t=o,o=a,a=t),n.precision(y)):[[r,o],[e,a]]},n.step=function(t){return arguments.length?n.majorStep(t).minorStep(t):n.minorStep()},n.majorStep=function(t){return arguments.length?(d=+t[0],m=+t[1],n):[d,m]},n.minorStep=function(t){return arguments.length?(p=+t[0],v=+t[1],n):[p,v]},n.precision=function(t){return arguments.length?(y=+t,s=me(o,a,90),f=ye(r,e,y),h=me(c,l,90),g=ye(i,u,y),n):y},n.majorExtent([[-180,-90+Da],[180,90-Da]]).minorExtent([[-180,-80-Da],[180,80+Da]])},oa.geo.greatArc=function(){function n(){return{type:"LineString",coordinates:[t||r.apply(this,arguments),e||u.apply(this,arguments)]}}var t,e,r=Me,u=xe;return n.distance=function(){return oa.geo.distance(t||r.apply(this,arguments),e||u.apply(this,arguments))},n.source=function(e){return arguments.length?(r=e,t="function"==typeof e?null:e,n):r},n.target=function(t){return arguments.length?(u=t,e="function"==typeof t?null:t,n):u},n.precision=function(){return arguments.length?n:0},n},oa.geo.interpolate=function(n,t){return be(n[0]*Oa,n[1]*Oa,t[0]*Oa,t[1]*Oa)},oa.geo.length=function(n){return Wo=0,oa.geo.stream(n,Jo),Wo};var Wo,Jo={sphere:b,point:b,lineStart:_e,lineEnd:b,polygonStart:b,polygonEnd:b},Go=we(function(n){return Math.sqrt(2/(1+n))},function(n){return 2*Math.asin(n/2)});(oa.geo.azimuthalEqualArea=function(){return ae(Go)}).raw=Go;var Ko=we(function(n){var t=Math.acos(n);return t&&t/Math.sin(t)},y);(oa.geo.azimuthalEquidistant=function(){return ae(Ko)}).raw=Ko,(oa.geo.conicConformal=function(){return Vt(Se)}).raw=Se,(oa.geo.conicEquidistant=function(){return Vt(ke)}).raw=ke;var Qo=we(function(n){return 1/n},Math.atan);(oa.geo.gnomonic=function(){return ae(Qo)}).raw=Qo,Ne.invert=function(n,t){return[n,2*Math.atan(Math.exp(t))-Ha]},(oa.geo.mercator=function(){return Ee(Ne)}).raw=Ne;var nl=we(function(){return 1},Math.asin);(oa.geo.orthographic=function(){return ae(nl)}).raw=nl;var tl=we(function(n){return 1/(1+n)},function(n){return 2*Math.atan(n)});(oa.geo.stereographic=function(){return ae(tl)}).raw=tl,Ae.invert=function(n,t){return[-t,2*Math.atan(Math.exp(n))-Ha]},(oa.geo.transverseMercator=function(){var n=Ee(Ae),t=n.center,e=n.rotate;return n.center=function(n){return n?t([-n[1],n[0]]):(n=t(),[n[1],-n[0]])},n.rotate=function(n){return n?e([n[0],n[1],n.length>2?n[2]+90:90]):(n=e(),[n[0],n[1],n[2]-90])},e([0,0,90])}).raw=Ae,oa.geom={},oa.geom.hull=function(n){function t(n){if(n.length<3)return[];var t,u=En(e),i=En(r),a=n.length,o=[],l=[];for(t=0;a>t;t++)o.push([+u.call(this,n[t],t),+i.call(this,n[t],t),t]);for(o.sort(qe),t=0;a>t;t++)l.push([o[t][0],-o[t][1]]);var c=Le(o),s=Le(l),f=s[0]===c[0],h=s[s.length-1]===c[c.length-1],g=[];for(t=c.length-1;t>=0;--t)g.push(n[o[c[t]][2]]);for(t=+f;t<s.length-h;++t)g.push(n[o[s[t]][2]]);return g}var e=Ce,r=ze;return arguments.length?t(n):(t.x=function(n){return arguments.length?(e=n,t):e},t.y=function(n){return arguments.length?(r=n,t):r},t)},oa.geom.polygon=function(n){return Sa(n,el),n};var el=oa.geom.polygon.prototype=[];el.area=function(){for(var n,t=-1,e=this.length,r=this[e-1],u=0;++t<e;)n=r,r=this[t],u+=n[1]*r[0]-n[0]*r[1];return.5*u},el.centroid=function(n){var t,e,r=-1,u=this.length,i=0,a=0,o=this[u-1];for(arguments.length||(n=-1/(6*this.area()));++r<u;)t=o,o=this[r],e=t[0]*o[1]-o[0]*t[1],i+=(t[0]+o[0])*e,a+=(t[1]+o[1])*e;return[i*n,a*n]},el.clip=function(n){for(var t,e,r,u,i,a,o=De(n),l=-1,c=this.length-De(this),s=this[c-1];++l<c;){for(t=n.slice(),n.length=0,u=this[l],i=t[(r=t.length-o)-1],e=-1;++e<r;)a=t[e],Te(a,s,u)?(Te(i,s,u)||n.push(Re(i,a,s,u)),n.push(a)):Te(i,s,u)&&n.push(Re(i,a,s,u)),i=a;o&&n.push(n[0]),s=u}return n};var rl,ul,il,al,ol,ll=[],cl=[];Ye.prototype.prepare=function(){for(var n,t=this.edges,e=t.length;e--;)n=t[e].edge,n.b&&n.a||t.splice(e,1);return t.sort(Ve),t.length},tr.prototype={start:function(){return this.edge.l===this.site?this.edge.a:this.edge.b},end:function(){return this.edge.l===this.site?this.edge.b:this.edge.a}},er.prototype={insert:function(n,t){var e,r,u;if(n){if(t.P=n,t.N=n.N,n.N&&(n.N.P=t),n.N=t,n.R){for(n=n.R;n.L;)n=n.L;n.L=t}else n.R=t;e=n}else this._?(n=ar(this._),t.P=null,t.N=n,n.P=n.L=t,e=n):(t.P=t.N=null,this._=t,e=null);for(t.L=t.R=null,t.U=e,t.C=!0,n=t;e&&e.C;)r=e.U,e===r.L?(u=r.R,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.R&&(ur(this,e),n=e,e=n.U),e.C=!1,r.C=!0,ir(this,r))):(u=r.L,u&&u.C?(e.C=u.C=!1,r.C=!0,n=r):(n===e.L&&(ir(this,e),n=e,e=n.U),e.C=!1,r.C=!0,ur(this,r))),e=n.U;this._.C=!1},remove:function(n){n.N&&(n.N.P=n.P),n.P&&(n.P.N=n.N),n.N=n.P=null;var t,e,r,u=n.U,i=n.L,a=n.R;if(e=i?a?ar(a):i:a,u?u.L===n?u.L=e:u.R=e:this._=e,i&&a?(r=e.C,e.C=n.C,e.L=i,i.U=e,e!==a?(u=e.U,e.U=n.U,n=e.R,u.L=n,e.R=a,a.U=e):(e.U=u,u=e,n=e.R)):(r=n.C,n=e),n&&(n.U=u),!r){if(n&&n.C)return void(n.C=!1);do{if(n===this._)break;if(n===u.L){if(t=u.R,t.C&&(t.C=!1,u.C=!0,ur(this,u),t=u.R),t.L&&t.L.C||t.R&&t.R.C){t.R&&t.R.C||(t.L.C=!1,t.C=!0,ir(this,t),t=u.R),t.C=u.C,u.C=t.R.C=!1,ur(this,u),n=this._;break}}else if(t=u.L,t.C&&(t.C=!1,u.C=!0,ir(this,u),t=u.L),t.L&&t.L.C||t.R&&t.R.C){t.L&&t.L.C||(t.R.C=!1,t.C=!0,ur(this,t),t=u.L),t.C=u.C,u.C=t.L.C=!1,ir(this,u),n=this._;break}t.C=!0,n=u,u=u.U}while(!n.C);n&&(n.C=!1)}}},oa.geom.voronoi=function(n){function t(n){var t=new Array(n.length),r=o[0][0],u=o[0][1],i=o[1][0],a=o[1][1];return or(e(n),o).cells.forEach(function(e,o){var l=e.edges,c=e.site,s=t[o]=l.length?l.map(function(n){var t=n.start();return[t.x,t.y]}):c.x>=r&&c.x<=i&&c.y>=u&&c.y<=a?[[r,a],[i,a],[i,u],[r,u]]:[];s.point=n[o]}),t}function e(n){return n.map(function(n,t){return{x:Math.round(i(n,t)/Da)*Da,y:Math.round(a(n,t)/Da)*Da,i:t}})}var r=Ce,u=ze,i=r,a=u,o=sl;return n?t(n):(t.links=function(n){return or(e(n)).edges.filter(function(n){return n.l&&n.r}).map(function(t){return{source:n[t.l.i],target:n[t.r.i]}})},t.triangles=function(n){var t=[];return or(e(n)).cells.forEach(function(e,r){for(var u,i,a=e.site,o=e.edges.sort(Ve),l=-1,c=o.length,s=o[c-1].edge,f=s.l===a?s.r:s.l;++l<c;)u=s,i=f,s=o[l].edge,f=s.l===a?s.r:s.l,r<i.i&&r<f.i&&cr(a,i,f)<0&&t.push([n[r],n[i.i],n[f.i]])}),t},t.x=function(n){return arguments.length?(i=En(r=n),t):r},t.y=function(n){return arguments.length?(a=En(u=n),t):u},t.clipExtent=function(n){return arguments.length?(o=null==n?sl:n,t):o===sl?null:o},t.size=function(n){return arguments.length?t.clipExtent(n&&[[0,0],n]):o===sl?null:o&&o[1]},t)};var sl=[[-1e6,-1e6],[1e6,1e6]];oa.geom.delaunay=function(n){return oa.geom.voronoi().triangles(n)},oa.geom.quadtree=function(n,t,e,r,u){function i(n){function i(n,t,e,r,u,i,a,o){if(!isNaN(e)&&!isNaN(r))if(n.leaf){var l=n.x,s=n.y;if(null!=l)if(Ma(l-e)+Ma(s-r)<.01)c(n,t,e,r,u,i,a,o);else{var f=n.point;n.x=n.y=n.point=null,c(n,f,l,s,u,i,a,o),c(n,t,e,r,u,i,a,o)}else n.x=e,n.y=r,n.point=t}else c(n,t,e,r,u,i,a,o)}function c(n,t,e,r,u,a,o,l){var c=.5*(u+o),s=.5*(a+l),f=e>=c,h=r>=s,g=h<<1|f;n.leaf=!1,n=n.nodes[g]||(n.nodes[g]=hr()),f?u=c:o=c,h?a=s:l=s,i(n,t,e,r,u,a,o,l)}var s,f,h,g,p,v,d,m,y,M=En(o),x=En(l);if(null!=t)v=t,d=e,m=r,y=u;else if(m=y=-(v=d=1/0),f=[],h=[],p=n.length,a)for(g=0;p>g;++g)s=n[g],s.x<v&&(v=s.x),s.y<d&&(d=s.y),s.x>m&&(m=s.x),s.y>y&&(y=s.y),f.push(s.x),h.push(s.y);else for(g=0;p>g;++g){var b=+M(s=n[g],g),_=+x(s,g);v>b&&(v=b),d>_&&(d=_),b>m&&(m=b),_>y&&(y=_),f.push(b),h.push(_)}var w=m-v,S=y-d;w>S?y=d+w:m=v+S;var k=hr();if(k.add=function(n){i(k,n,+M(n,++g),+x(n,g),v,d,m,y)},k.visit=function(n){gr(n,k,v,d,m,y)},k.find=function(n){return pr(k,n[0],n[1],v,d,m,y)},g=-1,null==t){for(;++g<p;)i(k,n[g],f[g],h[g],v,d,m,y);--g}else n.forEach(k.add);return f=h=n=s=null,k}var a,o=Ce,l=ze;return(a=arguments.length)?(o=sr,l=fr,3===a&&(u=e,r=t,e=t=0),i(n)):(i.x=function(n){return arguments.length?(o=n,i):o},i.y=function(n){return arguments.length?(l=n,i):l},i.extent=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=+n[0][0],e=+n[0][1],r=+n[1][0],u=+n[1][1]),i):null==t?null:[[t,e],[r,u]]},i.size=function(n){return arguments.length?(null==n?t=e=r=u=null:(t=e=0,r=+n[0],u=+n[1]),i):null==t?null:[r-t,u-e]},i)},oa.interpolateRgb=vr,oa.interpolateObject=dr,oa.interpolateNumber=mr,oa.interpolateString=yr;var fl=/[-+]?(?:\d+\.?\d*|\.?\d+)(?:[eE][-+]?\d+)?/g,hl=new RegExp(fl.source,"g");oa.interpolate=Mr,oa.interpolators=[function(n,t){var e=typeof t;return("string"===e?ro.has(t.toLowerCase())||/^(#|rgb\(|hsl\()/i.test(t)?vr:yr:t instanceof on?vr:Array.isArray(t)?xr:"object"===e&&isNaN(t)?dr:mr)(n,t)}],oa.interpolateArray=xr;var gl=function(){return y},pl=oa.map({linear:gl,poly:Er,quad:function(){return Sr},cubic:function(){return kr},sin:function(){return Ar},exp:function(){return Cr},circle:function(){return zr},elastic:Lr,back:qr,bounce:function(){return Tr}}),vl=oa.map({"in":y,out:_r,"in-out":wr,"out-in":function(n){return wr(_r(n))}});oa.ease=function(n){var t=n.indexOf("-"),e=t>=0?n.slice(0,t):n,r=t>=0?n.slice(t+1):"in";return e=pl.get(e)||gl,r=vl.get(r)||y,br(r(e.apply(null,la.call(arguments,1))))},oa.interpolateHcl=Rr,oa.interpolateHsl=Dr,oa.interpolateLab=Pr,oa.interpolateRound=jr,oa.transform=function(n){var t=sa.createElementNS(oa.ns.prefix.svg,"g");return(oa.transform=function(n){if(null!=n){t.setAttribute("transform",n);var e=t.transform.baseVal.consolidate()}return new Ur(e?e.matrix:dl)})(n)},Ur.prototype.toString=function(){return"translate("+this.translate+")rotate("+this.rotate+")skewX("+this.skew+")scale("+this.scale+")"};var dl={a:1,b:0,c:0,d:1,e:0,f:0};oa.interpolateTransform=$r,oa.layout={},oa.layout.bundle=function(){return function(n){for(var t=[],e=-1,r=n.length;++e<r;)t.push(Jr(n[e]));return t}},oa.layout.chord=function(){function n(){var n,c,f,h,g,p={},v=[],d=oa.range(i),m=[];for(e=[],r=[],n=0,h=-1;++h<i;){for(c=0,g=-1;++g<i;)c+=u[h][g];v.push(c),m.push(oa.range(i)),n+=c}for(a&&d.sort(function(n,t){return a(v[n],v[t])}),o&&m.forEach(function(n,t){n.sort(function(n,e){return o(u[t][n],u[t][e])})}),n=(Ua-s*i)/n,c=0,h=-1;++h<i;){for(f=c,g=-1;++g<i;){var y=d[h],M=m[y][g],x=u[y][M],b=c,_=c+=x*n;p[y+"-"+M]={index:y,subindex:M,startAngle:b,endAngle:_,value:x}}r[y]={index:y,startAngle:f,endAngle:c,value:v[y]},c+=s}for(h=-1;++h<i;)for(g=h-1;++g<i;){var w=p[h+"-"+g],S=p[g+"-"+h];(w.value||S.value)&&e.push(w.value<S.value?{source:S,target:w}:{source:w,target:S})}l&&t()}function t(){e.sort(function(n,t){return l((n.source.value+n.target.value)/2,(t.source.value+t.target.value)/2)})}var e,r,u,i,a,o,l,c={},s=0;return c.matrix=function(n){return arguments.length?(i=(u=n)&&u.length,e=r=null,c):u},c.padding=function(n){return arguments.length?(s=n,e=r=null,c):s},c.sortGroups=function(n){return arguments.length?(a=n,e=r=null,c):a},c.sortSubgroups=function(n){return arguments.length?(o=n,e=null,c):o},c.sortChords=function(n){return arguments.length?(l=n,e&&t(),c):l},c.chords=function(){return e||n(),e},c.groups=function(){return r||n(),r},c},oa.layout.force=function(){function n(n){return function(t,e,r,u){if(t.point!==n){var i=t.cx-n.x,a=t.cy-n.y,o=u-e,l=i*i+a*a;if(l>o*o/m){if(v>l){var c=t.charge/l;n.px-=i*c,n.py-=a*c}return!0}if(t.point&&l&&v>l){var c=t.pointCharge/l;n.px-=i*c,n.py-=a*c}}return!t.charge}}function t(n){n.px=oa.event.x,n.py=oa.event.y,l.resume()}var e,r,u,i,a,o,l={},c=oa.dispatch("start","tick","end"),s=[1,1],f=.9,h=ml,g=yl,p=-30,v=Ml,d=.1,m=.64,M=[],x=[];return l.tick=function(){if((u*=.99)<.005)return e=null,c.end({type:"end",alpha:u=0}),!0;var t,r,l,h,g,v,m,y,b,_=M.length,w=x.length;for(r=0;w>r;++r)l=x[r],h=l.source,g=l.target,y=g.x-h.x,b=g.y-h.y,(v=y*y+b*b)&&(v=u*a[r]*((v=Math.sqrt(v))-i[r])/v,y*=v,b*=v,g.x-=y*(m=h.weight+g.weight?h.weight/(h.weight+g.weight):.5),g.y-=b*m,h.x+=y*(m=1-m),h.y+=b*m);if((m=u*d)&&(y=s[0]/2,b=s[1]/2,r=-1,m))for(;++r<_;)l=M[r],l.x+=(y-l.x)*m,l.y+=(b-l.y)*m;if(p)for(ru(t=oa.geom.quadtree(M),u,o),r=-1;++r<_;)(l=M[r]).fixed||t.visit(n(l));for(r=-1;++r<_;)l=M[r],l.fixed?(l.x=l.px,l.y=l.py):(l.x-=(l.px-(l.px=l.x))*f,l.y-=(l.py-(l.py=l.y))*f);c.tick({type:"tick",alpha:u})},l.nodes=function(n){return arguments.length?(M=n,l):M},l.links=function(n){return arguments.length?(x=n,l):x},l.size=function(n){return arguments.length?(s=n,l):s},l.linkDistance=function(n){return arguments.length?(h="function"==typeof n?n:+n,l):h},l.distance=l.linkDistance,l.linkStrength=function(n){return arguments.length?(g="function"==typeof n?n:+n,l):g},l.friction=function(n){return arguments.length?(f=+n,l):f},l.charge=function(n){return arguments.length?(p="function"==typeof n?n:+n,l):p},l.chargeDistance=function(n){return arguments.length?(v=n*n,l):Math.sqrt(v)},l.gravity=function(n){return arguments.length?(d=+n,l):d},l.theta=function(n){return arguments.length?(m=n*n,l):Math.sqrt(m)},l.alpha=function(n){return arguments.length?(n=+n,u?n>0?u=n:(e.c=null,e.t=NaN,e=null,c.end({type:"end",alpha:u=0})):n>0&&(c.start({type:"start",alpha:u=n}),e=qn(l.tick)),l):u},l.start=function(){function n(n,r){if(!e){for(e=new Array(u),l=0;u>l;++l)e[l]=[];for(l=0;c>l;++l){var i=x[l];e[i.source.index].push(i.target),e[i.target.index].push(i.source)}}for(var a,o=e[t],l=-1,s=o.length;++l<s;)if(!isNaN(a=o[l][n]))return a;return Math.random()*r}var t,e,r,u=M.length,c=x.length,f=s[0],v=s[1];for(t=0;u>t;++t)(r=M[t]).index=t,r.weight=0;for(t=0;c>t;++t)r=x[t],"number"==typeof r.source&&(r.source=M[r.source]),"number"==typeof r.target&&(r.target=M[r.target]),++r.source.weight,++r.target.weight;for(t=0;u>t;++t)r=M[t],isNaN(r.x)&&(r.x=n("x",f)),isNaN(r.y)&&(r.y=n("y",v)),isNaN(r.px)&&(r.px=r.x),isNaN(r.py)&&(r.py=r.y);if(i=[],"function"==typeof h)for(t=0;c>t;++t)i[t]=+h.call(this,x[t],t);else for(t=0;c>t;++t)i[t]=h;if(a=[],"function"==typeof g)for(t=0;c>t;++t)a[t]=+g.call(this,x[t],t);else for(t=0;c>t;++t)a[t]=g;if(o=[],"function"==typeof p)for(t=0;u>t;++t)o[t]=+p.call(this,M[t],t);else for(t=0;u>t;++t)o[t]=p;return l.resume()},l.resume=function(){return l.alpha(.1)},l.stop=function(){return l.alpha(0)},l.drag=function(){return r||(r=oa.behavior.drag().origin(y).on("dragstart.force",Qr).on("drag.force",t).on("dragend.force",nu)),arguments.length?void this.on("mouseover.force",tu).on("mouseout.force",eu).call(r):r},oa.rebind(l,c,"on")};var ml=20,yl=1,Ml=1/0;oa.layout.hierarchy=function(){function n(u){var i,a=[u],o=[];for(u.depth=0;null!=(i=a.pop());)if(o.push(i),(c=e.call(n,i,i.depth))&&(l=c.length)){for(var l,c,s;--l>=0;)a.push(s=c[l]),s.parent=i,s.depth=i.depth+1;r&&(i.value=0),i.children=c}else r&&(i.value=+r.call(n,i,i.depth)||0),delete i.children;return au(u,function(n){var e,u;t&&(e=n.children)&&e.sort(t),r&&(u=n.parent)&&(u.value+=n.value)}),o}var t=cu,e=ou,r=lu;return n.sort=function(e){return arguments.length?(t=e,n):t},n.children=function(t){return arguments.length?(e=t,n):e},n.value=function(t){return arguments.length?(r=t,n):r},n.revalue=function(t){return r&&(iu(t,function(n){n.children&&(n.value=0)}),au(t,function(t){var e;t.children||(t.value=+r.call(n,t,t.depth)||0),(e=t.parent)&&(e.value+=t.value)})),t},n},oa.layout.partition=function(){function n(t,e,r,u){var i=t.children;if(t.x=e,t.y=t.depth*u,t.dx=r,t.dy=u,i&&(a=i.length)){var a,o,l,c=-1;for(r=t.value?r/t.value:0;++c<a;)n(o=i[c],e,l=o.value*r,u),e+=l}}function t(n){var e=n.children,r=0;if(e&&(u=e.length))for(var u,i=-1;++i<u;)r=Math.max(r,t(e[i]));return 1+r}function e(e,i){var a=r.call(this,e,i);return n(a[0],0,u[0],u[1]/t(a[0])),a}var r=oa.layout.hierarchy(),u=[1,1];return e.size=function(n){return arguments.length?(u=n,e):u},uu(e,r)},oa.layout.pie=function(){function n(a){var o,l=a.length,c=a.map(function(e,r){return+t.call(n,e,r)}),s=+("function"==typeof r?r.apply(this,arguments):r),f=("function"==typeof u?u.apply(this,arguments):u)-s,h=Math.min(Math.abs(f)/l,+("function"==typeof i?i.apply(this,arguments):i)),g=h*(0>f?-1:1),p=oa.sum(c),v=p?(f-l*g)/p:0,d=oa.range(l),m=[];return null!=e&&d.sort(e===xl?function(n,t){return c[t]-c[n]}:function(n,t){return e(a[n],a[t])}),d.forEach(function(n){m[n]={data:a[n],value:o=c[n],startAngle:s,endAngle:s+=o*v+g,padAngle:h}}),m}var t=Number,e=xl,r=0,u=Ua,i=0;return n.value=function(e){return arguments.length?(t=e,n):t},n.sort=function(t){return arguments.length?(e=t,n):e},n.startAngle=function(t){return arguments.length?(r=t,n):r},n.endAngle=function(t){return arguments.length?(u=t,n):u},n.padAngle=function(t){return arguments.length?(i=t,n):i},n};var xl={};oa.layout.stack=function(){function n(o,l){if(!(h=o.length))return o;var c=o.map(function(e,r){return t.call(n,e,r)}),s=c.map(function(t){return t.map(function(t,e){return[i.call(n,t,e),a.call(n,t,e)]})}),f=e.call(n,s,l);c=oa.permute(c,f),s=oa.permute(s,f);var h,g,p,v,d=r.call(n,s,l),m=c[0].length;for(p=0;m>p;++p)for(u.call(n,c[0][p],v=d[p],s[0][p][1]),g=1;h>g;++g)u.call(n,c[g][p],v+=s[g-1][p][1],s[g][p][1]);return o}var t=y,e=pu,r=vu,u=gu,i=fu,a=hu;return n.values=function(e){return arguments.length?(t=e,n):t},n.order=function(t){return arguments.length?(e="function"==typeof t?t:bl.get(t)||pu,n):e},n.offset=function(t){return arguments.length?(r="function"==typeof t?t:_l.get(t)||vu,n):r},n.x=function(t){return arguments.length?(i=t,n):i},n.y=function(t){return arguments.length?(a=t,n):a},n.out=function(t){return arguments.length?(u=t,n):u},n};var bl=oa.map({"inside-out":function(n){var t,e,r=n.length,u=n.map(du),i=n.map(mu),a=oa.range(r).sort(function(n,t){return u[n]-u[t]}),o=0,l=0,c=[],s=[];for(t=0;r>t;++t)e=a[t],l>o?(o+=i[e],c.push(e)):(l+=i[e],s.push(e));return s.reverse().concat(c)},reverse:function(n){return oa.range(n.length).reverse()},"default":pu}),_l=oa.map({silhouette:function(n){var t,e,r,u=n.length,i=n[0].length,a=[],o=0,l=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];r>o&&(o=r),a.push(r)}for(e=0;i>e;++e)l[e]=(o-a[e])/2;return l},wiggle:function(n){var t,e,r,u,i,a,o,l,c,s=n.length,f=n[0],h=f.length,g=[];for(g[0]=l=c=0,e=1;h>e;++e){for(t=0,u=0;s>t;++t)u+=n[t][e][1];for(t=0,i=0,o=f[e][0]-f[e-1][0];s>t;++t){for(r=0,a=(n[t][e][1]-n[t][e-1][1])/(2*o);t>r;++r)a+=(n[r][e][1]-n[r][e-1][1])/o;i+=a*n[t][e][1]}g[e]=l-=u?i/u*o:0,c>l&&(c=l)}for(e=0;h>e;++e)g[e]-=c;return g},expand:function(n){var t,e,r,u=n.length,i=n[0].length,a=1/u,o=[];for(e=0;i>e;++e){for(t=0,r=0;u>t;t++)r+=n[t][e][1];if(r)for(t=0;u>t;t++)n[t][e][1]/=r;else for(t=0;u>t;t++)n[t][e][1]=a}for(e=0;i>e;++e)o[e]=0;return o},zero:vu});oa.layout.histogram=function(){function n(n,i){for(var a,o,l=[],c=n.map(e,this),s=r.call(this,c,i),f=u.call(this,s,c,i),i=-1,h=c.length,g=f.length-1,p=t?1:1/h;++i<g;)a=l[i]=[],a.dx=f[i+1]-(a.x=f[i]),a.y=0;if(g>0)for(i=-1;++i<h;)o=c[i],o>=s[0]&&o<=s[1]&&(a=l[oa.bisect(f,o,1,g)-1],a.y+=p,a.push(n[i]));return l}var t=!0,e=Number,r=bu,u=Mu;return n.value=function(t){return arguments.length?(e=t,n):e},n.range=function(t){return arguments.length?(r=En(t),n):r},n.bins=function(t){return arguments.length?(u="number"==typeof t?function(n){return xu(n,t)}:En(t),n):u},n.frequency=function(e){return arguments.length?(t=!!e,n):t},n},oa.layout.pack=function(){function n(n,i){var a=e.call(this,n,i),o=a[0],l=u[0],c=u[1],s=null==t?Math.sqrt:"function"==typeof t?t:function(){return t};if(o.x=o.y=0,au(o,function(n){n.r=+s(n.value)}),au(o,Nu),r){var f=r*(t?1:Math.max(2*o.r/l,2*o.r/c))/2;au(o,function(n){n.r+=f}),au(o,Nu),au(o,function(n){n.r-=f})}return Cu(o,l/2,c/2,t?1:1/Math.max(2*o.r/l,2*o.r/c)),a}var t,e=oa.layout.hierarchy().sort(_u),r=0,u=[1,1];return n.size=function(t){return arguments.length?(u=t,n):u},n.radius=function(e){return arguments.length?(t=null==e||"function"==typeof e?e:+e,n):t},n.padding=function(t){return arguments.length?(r=+t,n):r},uu(n,e)},oa.layout.tree=function(){function n(n,u){var s=a.call(this,n,u),f=s[0],h=t(f);if(au(h,e),h.parent.m=-h.z,iu(h,r),c)iu(f,i);else{var g=f,p=f,v=f;iu(f,function(n){n.x<g.x&&(g=n),n.x>p.x&&(p=n),n.depth>v.depth&&(v=n)});var d=o(g,p)/2-g.x,m=l[0]/(p.x+o(p,g)/2+d),y=l[1]/(v.depth||1);iu(f,function(n){n.x=(n.x+d)*m,n.y=n.depth*y})}return s}function t(n){for(var t,e={A:null,children:[n]},r=[e];null!=(t=r.pop());)for(var u,i=t.children,a=0,o=i.length;o>a;++a)r.push((i[a]=u={_:i[a],parent:t,children:(u=i[a].children)&&u.slice()||[],A:null,a:null,z:0,m:0,c:0,s:0,t:null,i:a}).a=u);return e.children[0]}function e(n){var t=n.children,e=n.parent.children,r=n.i?e[n.i-1]:null;if(t.length){Du(n);var i=(t[0].z+t[t.length-1].z)/2;r?(n.z=r.z+o(n._,r._),n.m=n.z-i):n.z=i}else r&&(n.z=r.z+o(n._,r._));n.parent.A=u(n,r,n.parent.A||e[0])}function r(n){n._.x=n.z+n.parent.m,n.m+=n.parent.m}function u(n,t,e){if(t){for(var r,u=n,i=n,a=t,l=u.parent.children[0],c=u.m,s=i.m,f=a.m,h=l.m;a=Tu(a),u=qu(u),a&&u;)l=qu(l),i=Tu(i),i.a=n,r=a.z+f-u.z-c+o(a._,u._),r>0&&(Ru(Pu(a,n,e),n,r),c+=r,s+=r),f+=a.m,c+=u.m,h+=l.m,s+=i.m;a&&!Tu(i)&&(i.t=a,i.m+=f-s),u&&!qu(l)&&(l.t=u,l.m+=c-h,e=n)}return e}function i(n){n.x*=l[0],n.y=n.depth*l[1]}var a=oa.layout.hierarchy().sort(null).value(null),o=Lu,l=[1,1],c=null;return n.separation=function(t){return arguments.length?(o=t,n):o},n.size=function(t){return arguments.length?(c=null==(l=t)?i:null,n):c?null:l},n.nodeSize=function(t){return arguments.length?(c=null==(l=t)?null:i,n):c?l:null},uu(n,a)},oa.layout.cluster=function(){function n(n,i){var a,o=t.call(this,n,i),l=o[0],c=0;au(l,function(n){var t=n.children;t&&t.length?(n.x=Uu(t),n.y=ju(t)):(n.x=a?c+=e(n,a):0,n.y=0,a=n)});var s=Fu(l),f=Hu(l),h=s.x-e(s,f)/2,g=f.x+e(f,s)/2;return au(l,u?function(n){n.x=(n.x-l.x)*r[0],n.y=(l.y-n.y)*r[1]}:function(n){n.x=(n.x-h)/(g-h)*r[0],n.y=(1-(l.y?n.y/l.y:1))*r[1]}),o}var t=oa.layout.hierarchy().sort(null).value(null),e=Lu,r=[1,1],u=!1;return n.separation=function(t){return arguments.length?(e=t,n):e},n.size=function(t){return arguments.length?(u=null==(r=t),n):u?null:r},n.nodeSize=function(t){return arguments.length?(u=null!=(r=t),n):u?r:null},uu(n,t)},oa.layout.treemap=function(){function n(n,t){for(var e,r,u=-1,i=n.length;++u<i;)r=(e=n[u]).value*(0>t?0:t),e.area=isNaN(r)||0>=r?0:r}function t(e){var i=e.children;if(i&&i.length){var a,o,l,c=f(e),s=[],h=i.slice(),p=1/0,v="slice"===g?c.dx:"dice"===g?c.dy:"slice-dice"===g?1&e.depth?c.dy:c.dx:Math.min(c.dx,c.dy);for(n(h,c.dx*c.dy/e.value),s.area=0;(l=h.length)>0;)s.push(a=h[l-1]),s.area+=a.area,"squarify"!==g||(o=r(s,v))<=p?(h.pop(),p=o):(s.area-=s.pop().area,u(s,v,c,!1),v=Math.min(c.dx,c.dy),s.length=s.area=0,p=1/0);s.length&&(u(s,v,c,!0),s.length=s.area=0),i.forEach(t)}}function e(t){var r=t.children;if(r&&r.length){var i,a=f(t),o=r.slice(),l=[];for(n(o,a.dx*a.dy/t.value),l.area=0;i=o.pop();)l.push(i),l.area+=i.area,null!=i.z&&(u(l,i.z?a.dx:a.dy,a,!o.length),l.length=l.area=0);r.forEach(e)}}function r(n,t){for(var e,r=n.area,u=0,i=1/0,a=-1,o=n.length;++a<o;)(e=n[a].area)&&(i>e&&(i=e),e>u&&(u=e));return r*=r,t*=t,r?Math.max(t*u*p/r,r/(t*i*p)):1/0}function u(n,t,e,r){var u,i=-1,a=n.length,o=e.x,c=e.y,s=t?l(n.area/t):0;
5
+if(t==e.dx){for((r||s>e.dy)&&(s=e.dy);++i<a;)u=n[i],u.x=o,u.y=c,u.dy=s,o+=u.dx=Math.min(e.x+e.dx-o,s?l(u.area/s):0);u.z=!0,u.dx+=e.x+e.dx-o,e.y+=s,e.dy-=s}else{for((r||s>e.dx)&&(s=e.dx);++i<a;)u=n[i],u.x=o,u.y=c,u.dx=s,c+=u.dy=Math.min(e.y+e.dy-c,s?l(u.area/s):0);u.z=!1,u.dy+=e.y+e.dy-c,e.x+=s,e.dx-=s}}function i(r){var u=a||o(r),i=u[0];return i.x=i.y=0,i.value?(i.dx=c[0],i.dy=c[1]):i.dx=i.dy=0,a&&o.revalue(i),n([i],i.dx*i.dy/i.value),(a?e:t)(i),h&&(a=u),u}var a,o=oa.layout.hierarchy(),l=Math.round,c=[1,1],s=null,f=Ou,h=!1,g="squarify",p=.5*(1+Math.sqrt(5));return i.size=function(n){return arguments.length?(c=n,i):c},i.padding=function(n){function t(t){var e=n.call(i,t,t.depth);return null==e?Ou(t):Iu(t,"number"==typeof e?[e,e,e,e]:e)}function e(t){return Iu(t,n)}if(!arguments.length)return s;var r;return f=null==(s=n)?Ou:"function"==(r=typeof n)?t:"number"===r?(n=[n,n,n,n],e):e,i},i.round=function(n){return arguments.length?(l=n?Math.round:Number,i):l!=Number},i.sticky=function(n){return arguments.length?(h=n,a=null,i):h},i.ratio=function(n){return arguments.length?(p=n,i):p},i.mode=function(n){return arguments.length?(g=n+"",i):g},uu(i,o)},oa.random={normal:function(n,t){var e=arguments.length;return 2>e&&(t=1),1>e&&(n=0),function(){var e,r,u;do e=2*Math.random()-1,r=2*Math.random()-1,u=e*e+r*r;while(!u||u>1);return n+t*e*Math.sqrt(-2*Math.log(u)/u)}},logNormal:function(){var n=oa.random.normal.apply(oa,arguments);return function(){return Math.exp(n())}},bates:function(n){var t=oa.random.irwinHall(n);return function(){return t()/n}},irwinHall:function(n){return function(){for(var t=0,e=0;n>e;e++)t+=Math.random();return t}}},oa.scale={};var wl={floor:y,ceil:y};oa.scale.linear=function(){return Wu([0,1],[0,1],Mr,!1)};var Sl={s:1,g:1,p:1,r:1,e:1};oa.scale.log=function(){return ri(oa.scale.linear().domain([0,1]),10,!0,[1,10])};var kl=oa.format(".0e"),Nl={floor:function(n){return-Math.ceil(-n)},ceil:function(n){return-Math.floor(-n)}};oa.scale.pow=function(){return ui(oa.scale.linear(),1,[0,1])},oa.scale.sqrt=function(){return oa.scale.pow().exponent(.5)},oa.scale.ordinal=function(){return ai([],{t:"range",a:[[]]})},oa.scale.category10=function(){return oa.scale.ordinal().range(El)},oa.scale.category20=function(){return oa.scale.ordinal().range(Al)},oa.scale.category20b=function(){return oa.scale.ordinal().range(Cl)},oa.scale.category20c=function(){return oa.scale.ordinal().range(zl)};var El=[2062260,16744206,2924588,14034728,9725885,9197131,14907330,8355711,12369186,1556175].map(xn),Al=[2062260,11454440,16744206,16759672,2924588,10018698,14034728,16750742,9725885,12955861,9197131,12885140,14907330,16234194,8355711,13092807,12369186,14408589,1556175,10410725].map(xn),Cl=[3750777,5395619,7040719,10264286,6519097,9216594,11915115,13556636,9202993,12426809,15186514,15190932,8666169,11356490,14049643,15177372,8077683,10834324,13528509,14589654].map(xn),zl=[3244733,7057110,10406625,13032431,15095053,16616764,16625259,16634018,3253076,7652470,10607003,13101504,7695281,10394312,12369372,14342891,6513507,9868950,12434877,14277081].map(xn);oa.scale.quantile=function(){return oi([],[])},oa.scale.quantize=function(){return li(0,1,[0,1])},oa.scale.threshold=function(){return ci([.5],[0,1])},oa.scale.identity=function(){return si([0,1])},oa.svg={},oa.svg.arc=function(){function n(){var n=Math.max(0,+e.apply(this,arguments)),c=Math.max(0,+r.apply(this,arguments)),s=a.apply(this,arguments)-Ha,f=o.apply(this,arguments)-Ha,h=Math.abs(f-s),g=s>f?0:1;if(n>c&&(p=c,c=n,n=p),h>=Fa)return t(c,g)+(n?t(n,1-g):"")+"Z";var p,v,d,m,y,M,x,b,_,w,S,k,N=0,E=0,A=[];if((m=(+l.apply(this,arguments)||0)/2)&&(d=i===Ll?Math.sqrt(n*n+c*c):+i.apply(this,arguments),g||(E*=-1),c&&(E=tn(d/c*Math.sin(m))),n&&(N=tn(d/n*Math.sin(m)))),c){y=c*Math.cos(s+E),M=c*Math.sin(s+E),x=c*Math.cos(f-E),b=c*Math.sin(f-E);var C=Math.abs(f-s-2*E)<=ja?0:1;if(E&&mi(y,M,x,b)===g^C){var z=(s+f)/2;y=c*Math.cos(z),M=c*Math.sin(z),x=b=null}}else y=M=0;if(n){_=n*Math.cos(f-N),w=n*Math.sin(f-N),S=n*Math.cos(s+N),k=n*Math.sin(s+N);var L=Math.abs(s-f+2*N)<=ja?0:1;if(N&&mi(_,w,S,k)===1-g^L){var q=(s+f)/2;_=n*Math.cos(q),w=n*Math.sin(q),S=k=null}}else _=w=0;if(h>Da&&(p=Math.min(Math.abs(c-n)/2,+u.apply(this,arguments)))>.001){v=c>n^g?0:1;var T=p,R=p;if(ja>h){var D=null==S?[_,w]:null==x?[y,M]:Re([y,M],[S,k],[x,b],[_,w]),P=y-D[0],j=M-D[1],U=x-D[0],F=b-D[1],H=1/Math.sin(Math.acos((P*U+j*F)/(Math.sqrt(P*P+j*j)*Math.sqrt(U*U+F*F)))/2),O=Math.sqrt(D[0]*D[0]+D[1]*D[1]);R=Math.min(p,(n-O)/(H-1)),T=Math.min(p,(c-O)/(H+1))}if(null!=x){var I=yi(null==S?[_,w]:[S,k],[y,M],c,T,g),Y=yi([x,b],[_,w],c,T,g);p===T?A.push("M",I[0],"A",T,",",T," 0 0,",v," ",I[1],"A",c,",",c," 0 ",1-g^mi(I[1][0],I[1][1],Y[1][0],Y[1][1]),",",g," ",Y[1],"A",T,",",T," 0 0,",v," ",Y[0]):A.push("M",I[0],"A",T,",",T," 0 1,",v," ",Y[0])}else A.push("M",y,",",M);if(null!=S){var Z=yi([y,M],[S,k],n,-R,g),V=yi([_,w],null==x?[y,M]:[x,b],n,-R,g);p===R?A.push("L",V[0],"A",R,",",R," 0 0,",v," ",V[1],"A",n,",",n," 0 ",g^mi(V[1][0],V[1][1],Z[1][0],Z[1][1]),",",1-g," ",Z[1],"A",R,",",R," 0 0,",v," ",Z[0]):A.push("L",V[0],"A",R,",",R," 0 0,",v," ",Z[0])}else A.push("L",_,",",w)}else A.push("M",y,",",M),null!=x&&A.push("A",c,",",c," 0 ",C,",",g," ",x,",",b),A.push("L",_,",",w),null!=S&&A.push("A",n,",",n," 0 ",L,",",1-g," ",S,",",k);return A.push("Z"),A.join("")}function t(n,t){return"M0,"+n+"A"+n+","+n+" 0 1,"+t+" 0,"+-n+"A"+n+","+n+" 0 1,"+t+" 0,"+n}var e=hi,r=gi,u=fi,i=Ll,a=pi,o=vi,l=di;return n.innerRadius=function(t){return arguments.length?(e=En(t),n):e},n.outerRadius=function(t){return arguments.length?(r=En(t),n):r},n.cornerRadius=function(t){return arguments.length?(u=En(t),n):u},n.padRadius=function(t){return arguments.length?(i=t==Ll?Ll:En(t),n):i},n.startAngle=function(t){return arguments.length?(a=En(t),n):a},n.endAngle=function(t){return arguments.length?(o=En(t),n):o},n.padAngle=function(t){return arguments.length?(l=En(t),n):l},n.centroid=function(){var n=(+e.apply(this,arguments)+ +r.apply(this,arguments))/2,t=(+a.apply(this,arguments)+ +o.apply(this,arguments))/2-Ha;return[Math.cos(t)*n,Math.sin(t)*n]},n};var Ll="auto";oa.svg.line=function(){return Mi(y)};var ql=oa.map({linear:xi,"linear-closed":bi,step:_i,"step-before":wi,"step-after":Si,basis:zi,"basis-open":Li,"basis-closed":qi,bundle:Ti,cardinal:Ei,"cardinal-open":ki,"cardinal-closed":Ni,monotone:Fi});ql.forEach(function(n,t){t.key=n,t.closed=/-closed$/.test(n)});var Tl=[0,2/3,1/3,0],Rl=[0,1/3,2/3,0],Dl=[0,1/6,2/3,1/6];oa.svg.line.radial=function(){var n=Mi(Hi);return n.radius=n.x,delete n.x,n.angle=n.y,delete n.y,n},wi.reverse=Si,Si.reverse=wi,oa.svg.area=function(){return Oi(y)},oa.svg.area.radial=function(){var n=Oi(Hi);return n.radius=n.x,delete n.x,n.innerRadius=n.x0,delete n.x0,n.outerRadius=n.x1,delete n.x1,n.angle=n.y,delete n.y,n.startAngle=n.y0,delete n.y0,n.endAngle=n.y1,delete n.y1,n},oa.svg.chord=function(){function n(n,o){var l=t(this,i,n,o),c=t(this,a,n,o);return"M"+l.p0+r(l.r,l.p1,l.a1-l.a0)+(e(l,c)?u(l.r,l.p1,l.r,l.p0):u(l.r,l.p1,c.r,c.p0)+r(c.r,c.p1,c.a1-c.a0)+u(c.r,c.p1,l.r,l.p0))+"Z"}function t(n,t,e,r){var u=t.call(n,e,r),i=o.call(n,u,r),a=l.call(n,u,r)-Ha,s=c.call(n,u,r)-Ha;return{r:i,a0:a,a1:s,p0:[i*Math.cos(a),i*Math.sin(a)],p1:[i*Math.cos(s),i*Math.sin(s)]}}function e(n,t){return n.a0==t.a0&&n.a1==t.a1}function r(n,t,e){return"A"+n+","+n+" 0 "+ +(e>ja)+",1 "+t}function u(n,t,e,r){return"Q 0,0 "+r}var i=Me,a=xe,o=Ii,l=pi,c=vi;return n.radius=function(t){return arguments.length?(o=En(t),n):o},n.source=function(t){return arguments.length?(i=En(t),n):i},n.target=function(t){return arguments.length?(a=En(t),n):a},n.startAngle=function(t){return arguments.length?(l=En(t),n):l},n.endAngle=function(t){return arguments.length?(c=En(t),n):c},n},oa.svg.diagonal=function(){function n(n,u){var i=t.call(this,n,u),a=e.call(this,n,u),o=(i.y+a.y)/2,l=[i,{x:i.x,y:o},{x:a.x,y:o},a];return l=l.map(r),"M"+l[0]+"C"+l[1]+" "+l[2]+" "+l[3]}var t=Me,e=xe,r=Yi;return n.source=function(e){return arguments.length?(t=En(e),n):t},n.target=function(t){return arguments.length?(e=En(t),n):e},n.projection=function(t){return arguments.length?(r=t,n):r},n},oa.svg.diagonal.radial=function(){var n=oa.svg.diagonal(),t=Yi,e=n.projection;return n.projection=function(n){return arguments.length?e(Zi(t=n)):t},n},oa.svg.symbol=function(){function n(n,r){return(Pl.get(t.call(this,n,r))||$i)(e.call(this,n,r))}var t=Xi,e=Vi;return n.type=function(e){return arguments.length?(t=En(e),n):t},n.size=function(t){return arguments.length?(e=En(t),n):e},n};var Pl=oa.map({circle:$i,cross:function(n){var t=Math.sqrt(n/5)/2;return"M"+-3*t+","+-t+"H"+-t+"V"+-3*t+"H"+t+"V"+-t+"H"+3*t+"V"+t+"H"+t+"V"+3*t+"H"+-t+"V"+t+"H"+-3*t+"Z"},diamond:function(n){var t=Math.sqrt(n/(2*Ul)),e=t*Ul;return"M0,"+-t+"L"+e+",0 0,"+t+" "+-e+",0Z"},square:function(n){var t=Math.sqrt(n)/2;return"M"+-t+","+-t+"L"+t+","+-t+" "+t+","+t+" "+-t+","+t+"Z"},"triangle-down":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+e+"L"+t+","+-e+" "+-t+","+-e+"Z"},"triangle-up":function(n){var t=Math.sqrt(n/jl),e=t*jl/2;return"M0,"+-e+"L"+t+","+e+" "+-t+","+e+"Z"}});oa.svg.symbolTypes=Pl.keys();var jl=Math.sqrt(3),Ul=Math.tan(30*Oa);Aa.transition=function(n){for(var t,e,r=Fl||++Yl,u=Ki(n),i=[],a=Hl||{time:Date.now(),ease:Nr,delay:0,duration:250},o=-1,l=this.length;++o<l;){i.push(t=[]);for(var c=this[o],s=-1,f=c.length;++s<f;)(e=c[s])&&Qi(e,s,u,r,a),t.push(e)}return Wi(i,u,r)},Aa.interrupt=function(n){return this.each(null==n?Ol:Bi(Ki(n)))};var Fl,Hl,Ol=Bi(Ki()),Il=[],Yl=0;Il.call=Aa.call,Il.empty=Aa.empty,Il.node=Aa.node,Il.size=Aa.size,oa.transition=function(n,t){return n&&n.transition?Fl?n.transition(t):n:oa.selection().transition(n)},oa.transition.prototype=Il,Il.select=function(n){var t,e,r,u=this.id,i=this.namespace,a=[];n=A(n);for(var o=-1,l=this.length;++o<l;){a.push(t=[]);for(var c=this[o],s=-1,f=c.length;++s<f;)(r=c[s])&&(e=n.call(r,r.__data__,s,o))?("__data__"in r&&(e.__data__=r.__data__),Qi(e,s,i,u,r[i][u]),t.push(e)):t.push(null)}return Wi(a,i,u)},Il.selectAll=function(n){var t,e,r,u,i,a=this.id,o=this.namespace,l=[];n=C(n);for(var c=-1,s=this.length;++c<s;)for(var f=this[c],h=-1,g=f.length;++h<g;)if(r=f[h]){i=r[o][a],e=n.call(r,r.__data__,h,c),l.push(t=[]);for(var p=-1,v=e.length;++p<v;)(u=e[p])&&Qi(u,p,o,a,i),t.push(u)}return Wi(l,o,a)},Il.filter=function(n){var t,e,r,u=[];"function"!=typeof n&&(n=O(n));for(var i=0,a=this.length;a>i;i++){u.push(t=[]);for(var e=this[i],o=0,l=e.length;l>o;o++)(r=e[o])&&n.call(r,r.__data__,o,i)&&t.push(r)}return Wi(u,this.namespace,this.id)},Il.tween=function(n,t){var e=this.id,r=this.namespace;return arguments.length<2?this.node()[r][e].tween.get(n):Y(this,null==t?function(t){t[r][e].tween.remove(n)}:function(u){u[r][e].tween.set(n,t)})},Il.attr=function(n,t){function e(){this.removeAttribute(o)}function r(){this.removeAttributeNS(o.space,o.local)}function u(n){return null==n?e:(n+="",function(){var t,e=this.getAttribute(o);return e!==n&&(t=a(e,n),function(n){this.setAttribute(o,t(n))})})}function i(n){return null==n?r:(n+="",function(){var t,e=this.getAttributeNS(o.space,o.local);return e!==n&&(t=a(e,n),function(n){this.setAttributeNS(o.space,o.local,t(n))})})}if(arguments.length<2){for(t in n)this.attr(t,n[t]);return this}var a="transform"==n?$r:Mr,o=oa.ns.qualify(n);return Ji(this,"attr."+n,t,o.local?i:u)},Il.attrTween=function(n,t){function e(n,e){var r=t.call(this,n,e,this.getAttribute(u));return r&&function(n){this.setAttribute(u,r(n))}}function r(n,e){var r=t.call(this,n,e,this.getAttributeNS(u.space,u.local));return r&&function(n){this.setAttributeNS(u.space,u.local,r(n))}}var u=oa.ns.qualify(n);return this.tween("attr."+n,u.local?r:e)},Il.style=function(n,e,r){function u(){this.style.removeProperty(n)}function i(e){return null==e?u:(e+="",function(){var u,i=t(this).getComputedStyle(this,null).getPropertyValue(n);return i!==e&&(u=Mr(i,e),function(t){this.style.setProperty(n,u(t),r)})})}var a=arguments.length;if(3>a){if("string"!=typeof n){2>a&&(e="");for(r in n)this.style(r,n[r],e);return this}r=""}return Ji(this,"style."+n,e,i)},Il.styleTween=function(n,e,r){function u(u,i){var a=e.call(this,u,i,t(this).getComputedStyle(this,null).getPropertyValue(n));return a&&function(t){this.style.setProperty(n,a(t),r)}}return arguments.length<3&&(r=""),this.tween("style."+n,u)},Il.text=function(n){return Ji(this,"text",n,Gi)},Il.remove=function(){var n=this.namespace;return this.each("end.transition",function(){var t;this[n].count<2&&(t=this.parentNode)&&t.removeChild(this)})},Il.ease=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].ease:("function"!=typeof n&&(n=oa.ease.apply(oa,arguments)),Y(this,function(r){r[e][t].ease=n}))},Il.delay=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].delay:Y(this,"function"==typeof n?function(r,u,i){r[e][t].delay=+n.call(r,r.__data__,u,i)}:(n=+n,function(r){r[e][t].delay=n}))},Il.duration=function(n){var t=this.id,e=this.namespace;return arguments.length<1?this.node()[e][t].duration:Y(this,"function"==typeof n?function(r,u,i){r[e][t].duration=Math.max(1,n.call(r,r.__data__,u,i))}:(n=Math.max(1,n),function(r){r[e][t].duration=n}))},Il.each=function(n,t){var e=this.id,r=this.namespace;if(arguments.length<2){var u=Hl,i=Fl;try{Fl=e,Y(this,function(t,u,i){Hl=t[r][e],n.call(t,t.__data__,u,i)})}finally{Hl=u,Fl=i}}else Y(this,function(u){var i=u[r][e];(i.event||(i.event=oa.dispatch("start","end","interrupt"))).on(n,t)});return this},Il.transition=function(){for(var n,t,e,r,u=this.id,i=++Yl,a=this.namespace,o=[],l=0,c=this.length;c>l;l++){o.push(n=[]);for(var t=this[l],s=0,f=t.length;f>s;s++)(e=t[s])&&(r=e[a][u],Qi(e,s,a,i,{time:r.time,ease:r.ease,delay:r.delay+r.duration,duration:r.duration})),n.push(e)}return Wi(o,a,i)},oa.svg.axis=function(){function n(n){n.each(function(){var n,c=oa.select(this),s=this.__chart__||e,f=this.__chart__=e.copy(),h=null==l?f.ticks?f.ticks.apply(f,o):f.domain():l,g=null==t?f.tickFormat?f.tickFormat.apply(f,o):y:t,p=c.selectAll(".tick").data(h,f),v=p.enter().insert("g",".domain").attr("class","tick").style("opacity",Da),d=oa.transition(p.exit()).style("opacity",Da).remove(),m=oa.transition(p.order()).style("opacity",1),M=Math.max(u,0)+a,x=Zu(f),b=c.selectAll(".domain").data([0]),_=(b.enter().append("path").attr("class","domain"),oa.transition(b));v.append("line"),v.append("text");var w,S,k,N,E=v.select("line"),A=m.select("line"),C=p.select("text").text(g),z=v.select("text"),L=m.select("text"),q="top"===r||"left"===r?-1:1;if("bottom"===r||"top"===r?(n=na,w="x",k="y",S="x2",N="y2",C.attr("dy",0>q?"0em":".71em").style("text-anchor","middle"),_.attr("d","M"+x[0]+","+q*i+"V0H"+x[1]+"V"+q*i)):(n=ta,w="y",k="x",S="y2",N="x2",C.attr("dy",".32em").style("text-anchor",0>q?"end":"start"),_.attr("d","M"+q*i+","+x[0]+"H0V"+x[1]+"H"+q*i)),E.attr(N,q*u),z.attr(k,q*M),A.attr(S,0).attr(N,q*u),L.attr(w,0).attr(k,q*M),f.rangeBand){var T=f,R=T.rangeBand()/2;s=f=function(n){return T(n)+R}}else s.rangeBand?s=f:d.call(n,f,s);v.call(n,s,f),m.call(n,f,f)})}var t,e=oa.scale.linear(),r=Zl,u=6,i=6,a=3,o=[10],l=null;return n.scale=function(t){return arguments.length?(e=t,n):e},n.orient=function(t){return arguments.length?(r=t in Vl?t+"":Zl,n):r},n.ticks=function(){return arguments.length?(o=ca(arguments),n):o},n.tickValues=function(t){return arguments.length?(l=t,n):l},n.tickFormat=function(e){return arguments.length?(t=e,n):t},n.tickSize=function(t){var e=arguments.length;return e?(u=+t,i=+arguments[e-1],n):u},n.innerTickSize=function(t){return arguments.length?(u=+t,n):u},n.outerTickSize=function(t){return arguments.length?(i=+t,n):i},n.tickPadding=function(t){return arguments.length?(a=+t,n):a},n.tickSubdivide=function(){return arguments.length&&n},n};var Zl="bottom",Vl={top:1,right:1,bottom:1,left:1};oa.svg.brush=function(){function n(t){t.each(function(){var t=oa.select(this).style("pointer-events","all").style("-webkit-tap-highlight-color","rgba(0,0,0,0)").on("mousedown.brush",i).on("touchstart.brush",i),a=t.selectAll(".background").data([0]);a.enter().append("rect").attr("class","background").style("visibility","hidden").style("cursor","crosshair"),t.selectAll(".extent").data([0]).enter().append("rect").attr("class","extent").style("cursor","move");var o=t.selectAll(".resize").data(v,y);o.exit().remove(),o.enter().append("g").attr("class",function(n){return"resize "+n}).style("cursor",function(n){return Xl[n]}).append("rect").attr("x",function(n){return/[ew]$/.test(n)?-3:null}).attr("y",function(n){return/^[ns]/.test(n)?-3:null}).attr("width",6).attr("height",6).style("visibility","hidden"),o.style("display",n.empty()?"none":null);var l,f=oa.transition(t),h=oa.transition(a);c&&(l=Zu(c),h.attr("x",l[0]).attr("width",l[1]-l[0]),r(f)),s&&(l=Zu(s),h.attr("y",l[0]).attr("height",l[1]-l[0]),u(f)),e(f)})}function e(n){n.selectAll(".resize").attr("transform",function(n){return"translate("+f[+/e$/.test(n)]+","+h[+/^s/.test(n)]+")"})}function r(n){n.select(".extent").attr("x",f[0]),n.selectAll(".extent,.n>rect,.s>rect").attr("width",f[1]-f[0])}function u(n){n.select(".extent").attr("y",h[0]),n.selectAll(".extent,.e>rect,.w>rect").attr("height",h[1]-h[0])}function i(){function i(){32==oa.event.keyCode&&(C||(M=null,L[0]-=f[1],L[1]-=h[1],C=2),S())}function v(){32==oa.event.keyCode&&2==C&&(L[0]+=f[1],L[1]+=h[1],C=0,S())}function d(){var n=oa.mouse(b),t=!1;x&&(n[0]+=x[0],n[1]+=x[1]),C||(oa.event.altKey?(M||(M=[(f[0]+f[1])/2,(h[0]+h[1])/2]),L[0]=f[+(n[0]<M[0])],L[1]=h[+(n[1]<M[1])]):M=null),E&&m(n,c,0)&&(r(k),t=!0),A&&m(n,s,1)&&(u(k),t=!0),t&&(e(k),w({type:"brush",mode:C?"move":"resize"}))}function m(n,t,e){var r,u,i=Zu(t),l=i[0],c=i[1],s=L[e],v=e?h:f,d=v[1]-v[0];return C&&(l-=s,c-=d+s),r=(e?p:g)?Math.max(l,Math.min(c,n[e])):n[e],C?u=(r+=s)+d:(M&&(s=Math.max(l,Math.min(c,2*M[e]-r))),r>s?(u=r,r=s):u=s),v[0]!=r||v[1]!=u?(e?o=null:a=null,v[0]=r,v[1]=u,!0):void 0}function y(){d(),k.style("pointer-events","all").selectAll(".resize").style("display",n.empty()?"none":null),oa.select("body").style("cursor",null),q.on("mousemove.brush",null).on("mouseup.brush",null).on("touchmove.brush",null).on("touchend.brush",null).on("keydown.brush",null).on("keyup.brush",null),z(),w({type:"brushend"})}var M,x,b=this,_=oa.select(oa.event.target),w=l.of(b,arguments),k=oa.select(b),N=_.datum(),E=!/^(n|s)$/.test(N)&&c,A=!/^(e|w)$/.test(N)&&s,C=_.classed("extent"),z=W(b),L=oa.mouse(b),q=oa.select(t(b)).on("keydown.brush",i).on("keyup.brush",v);if(oa.event.changedTouches?q.on("touchmove.brush",d).on("touchend.brush",y):q.on("mousemove.brush",d).on("mouseup.brush",y),k.interrupt().selectAll("*").interrupt(),C)L[0]=f[0]-L[0],L[1]=h[0]-L[1];else if(N){var T=+/w$/.test(N),R=+/^n/.test(N);x=[f[1-T]-L[0],h[1-R]-L[1]],L[0]=f[T],L[1]=h[R]}else oa.event.altKey&&(M=L.slice());k.style("pointer-events","none").selectAll(".resize").style("display",null),oa.select("body").style("cursor",_.style("cursor")),w({type:"brushstart"}),d()}var a,o,l=N(n,"brushstart","brush","brushend"),c=null,s=null,f=[0,0],h=[0,0],g=!0,p=!0,v=$l[0];return n.event=function(n){n.each(function(){var n=l.of(this,arguments),t={x:f,y:h,i:a,j:o},e=this.__chart__||t;this.__chart__=t,Fl?oa.select(this).transition().each("start.brush",function(){a=e.i,o=e.j,f=e.x,h=e.y,n({type:"brushstart"})}).tween("brush:brush",function(){var e=xr(f,t.x),r=xr(h,t.y);return a=o=null,function(u){f=t.x=e(u),h=t.y=r(u),n({type:"brush",mode:"resize"})}}).each("end.brush",function(){a=t.i,o=t.j,n({type:"brush",mode:"resize"}),n({type:"brushend"})}):(n({type:"brushstart"}),n({type:"brush",mode:"resize"}),n({type:"brushend"}))})},n.x=function(t){return arguments.length?(c=t,v=$l[!c<<1|!s],n):c},n.y=function(t){return arguments.length?(s=t,v=$l[!c<<1|!s],n):s},n.clamp=function(t){return arguments.length?(c&&s?(g=!!t[0],p=!!t[1]):c?g=!!t:s&&(p=!!t),n):c&&s?[g,p]:c?g:s?p:null},n.extent=function(t){var e,r,u,i,l;return arguments.length?(c&&(e=t[0],r=t[1],s&&(e=e[0],r=r[0]),a=[e,r],c.invert&&(e=c(e),r=c(r)),e>r&&(l=e,e=r,r=l),(e!=f[0]||r!=f[1])&&(f=[e,r])),s&&(u=t[0],i=t[1],c&&(u=u[1],i=i[1]),o=[u,i],s.invert&&(u=s(u),i=s(i)),u>i&&(l=u,u=i,i=l),(u!=h[0]||i!=h[1])&&(h=[u,i])),n):(c&&(a?(e=a[0],r=a[1]):(e=f[0],r=f[1],c.invert&&(e=c.invert(e),r=c.invert(r)),e>r&&(l=e,e=r,r=l))),s&&(o?(u=o[0],i=o[1]):(u=h[0],i=h[1],s.invert&&(u=s.invert(u),i=s.invert(i)),u>i&&(l=u,u=i,i=l))),c&&s?[[e,u],[r,i]]:c?[e,r]:s&&[u,i])},n.clear=function(){return n.empty()||(f=[0,0],h=[0,0],a=o=null),n},n.empty=function(){return!!c&&f[0]==f[1]||!!s&&h[0]==h[1]},oa.rebind(n,l,"on")};var Xl={n:"ns-resize",e:"ew-resize",s:"ns-resize",w:"ew-resize",nw:"nwse-resize",ne:"nesw-resize",se:"nwse-resize",sw:"nesw-resize"},$l=[["n","e","s","w","nw","ne","se","sw"],["e","w"],["n","s"],[]],Bl=ho.format=Mo.timeFormat,Wl=Bl.utc,Jl=Wl("%Y-%m-%dT%H:%M:%S.%LZ");Bl.iso=Date.prototype.toISOString&&+new Date("2000-01-01T00:00:00.000Z")?ea:Jl,ea.parse=function(n){var t=new Date(n);return isNaN(t)?null:t},ea.toString=Jl.toString,ho.second=On(function(n){return new go(1e3*Math.floor(n/1e3))},function(n,t){n.setTime(n.getTime()+1e3*Math.floor(t))},function(n){return n.getSeconds()}),ho.seconds=ho.second.range,ho.seconds.utc=ho.second.utc.range,ho.minute=On(function(n){return new go(6e4*Math.floor(n/6e4))},function(n,t){n.setTime(n.getTime()+6e4*Math.floor(t))},function(n){return n.getMinutes()}),ho.minutes=ho.minute.range,ho.minutes.utc=ho.minute.utc.range,ho.hour=On(function(n){var t=n.getTimezoneOffset()/60;return new go(36e5*(Math.floor(n/36e5-t)+t))},function(n,t){n.setTime(n.getTime()+36e5*Math.floor(t))},function(n){return n.getHours()}),ho.hours=ho.hour.range,ho.hours.utc=ho.hour.utc.range,ho.month=On(function(n){return n=ho.day(n),n.setDate(1),n},function(n,t){n.setMonth(n.getMonth()+t)},function(n){return n.getMonth()}),ho.months=ho.month.range,ho.months.utc=ho.month.utc.range;var Gl=[1e3,5e3,15e3,3e4,6e4,3e5,9e5,18e5,36e5,108e5,216e5,432e5,864e5,1728e5,6048e5,2592e6,7776e6,31536e6],Kl=[[ho.second,1],[ho.second,5],[ho.second,15],[ho.second,30],[ho.minute,1],[ho.minute,5],[ho.minute,15],[ho.minute,30],[ho.hour,1],[ho.hour,3],[ho.hour,6],[ho.hour,12],[ho.day,1],[ho.day,2],[ho.week,1],[ho.month,1],[ho.month,3],[ho.year,1]],Ql=Bl.multi([[".%L",function(n){return n.getMilliseconds()}],[":%S",function(n){return n.getSeconds()}],["%I:%M",function(n){return n.getMinutes()}],["%I %p",function(n){return n.getHours()}],["%a %d",function(n){return n.getDay()&&1!=n.getDate()}],["%b %d",function(n){return 1!=n.getDate()}],["%B",function(n){return n.getMonth()}],["%Y",zt]]),nc={range:function(n,t,e){return oa.range(Math.ceil(n/e)*e,+t,e).map(ua)},floor:y,ceil:y};Kl.year=ho.year,ho.scale=function(){return ra(oa.scale.linear(),Kl,Ql)};var tc=Kl.map(function(n){return[n[0].utc,n[1]]}),ec=Wl.multi([[".%L",function(n){return n.getUTCMilliseconds()}],[":%S",function(n){return n.getUTCSeconds()}],["%I:%M",function(n){return n.getUTCMinutes()}],["%I %p",function(n){return n.getUTCHours()}],["%a %d",function(n){return n.getUTCDay()&&1!=n.getUTCDate()}],["%b %d",function(n){return 1!=n.getUTCDate()}],["%B",function(n){return n.getUTCMonth()}],["%Y",zt]]);tc.year=ho.year.utc,ho.scale.utc=function(){return ra(oa.scale.linear(),tc,ec)},oa.text=An(function(n){return n.responseText}),oa.json=function(n,t){return Cn(n,"application/json",ia,t)},oa.html=function(n,t){return Cn(n,"text/html",aa,t)},oa.xml=An(function(n){return n.responseXML}),"function"==typeof define&&define.amd?(this.d3=oa,define(oa)):"object"==typeof module&&module.exports?module.exports=oa:this.d3=oa}();
\ No newline at end of file