@cryptotaxi247 / netdata-1 / commits / 152067489

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, &currentios, &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